怎样取得屏幕上发生变化的区域的内容?(200分)

  • 主题发起人 主题发起人 lxggc
  • 开始时间 开始时间
L

lxggc

Unregistered / Unconfirmed
GUEST, unregistred user!
本人想做一个远程监控对方屏幕的程序,要求在发送屏幕图像数据的时候只传输上次
发送以后发生了变化的区域。请赐教。(如果用directx,请给出源程序)
 
思考中、、、
 
可以看看http://www.delphibbs.com/delphibbs/dispq.asp?lid=762741
 
这个大家讨论很久了,也没讨论出什么有效的方法
如果你找到什么好方法,麻烦通知我,谢谢!
 
根據VNC的做法,就是多放HOOK(放幾個就要看你自已了)
比如WM_Paint等
通過HOOK得知窗口的Handle,相應的可以得知Top,left,width,height
用Bitblt或用DirectX將此區域的圖像取出(有關抓屏已有很多例子,你自已Search吧)
取出新的圖塊後再和舊的圖像中相應圖塊進行XOR運算,相同部分將會為黑色。
將XOR過後的圖塊進行壓縮將會壓得非常小。
注意:用SCANLINE指針運算。(進行 "XOR" 或 "=" 等的運算48萬次隻要9毫秒)
用BitBlt抓屏(800*600)要35ms
(聲明,此35毫秒是在16bit,TBITMAP也是pf16bit的情況下,pixelformat不同會產生不同的結果)
不設定pixelFormat將獲得最快的抓屏速度,但所得圖為DDB,如有設定則為DIB。
你可以去看這幾個熱點問題:
http://delphibbs.com/delphibbs/dispq.asp?lid=762741
http://delphibbs.com/delphibbs/dispq.asp?lid=530544

OK,祝你成功。

最後說一句,我也再做這個東東。我認為重點在壓縮部分,當網絡很快時採用……,當網絡很慢時採用……。
哈哈……

 
看一下这个。
http://delphibbs.com/delphibbs/dispq.asp?lid=538683

简单办法就是异或。
 
阿拉也想知道
 
  其根本的原理是先捕获屏幕画面,然后回传给客户机,由于画面的数据量很大所以,
很多木马程序都是在画面改变的时候才回传改变部分的画面,常用的手段是最小矩形法,
下面以一段算法举例:


#define MAXXCount 10 //屏幕X方向最多分割块数
#define MAXYCount 5 //... Y................
#define DestNum 1000 //每块的偏移检测点最大个数
COLORREF Colors[MAXXCount][MAXYCount][DestNum];
COLORREF BakColors[MAXXCount]{MAXYCount][DestNum];
TPoint Dests[DestNum];
int Sw;
int Sh;
int xCount;
int yCount;
int ItemWidth;
int ItemHeight;
int Dnum;
int Qlity;
//得到消息后执行:
//另外:接收到的数据包中分析出 Dnum ,Qlity
//Dnum:偏移观测点数量
//Qlity:图象要求质量
__fastcall TForm1::CopyScreen(int DNum,int Qlity){
ItemWidth=Sw/xCount;
ItemHeight=Sh/yCount;
Sw=Screen->Width;
Sh=Screen->Height;
xCount=(Sw>1000)?8:6;
yCount=(Sh>1000)?3:2;
for (int num1=0;num1 Dests[num1].x=random(ItemWidth);
Dests[num1].y=random(ItemHeight);
}
CatchScreen(DNum,Qlity);
}
//收到刷屏消息后只执行:
CatchScreen(DNum,Qlity);
__fastcall TForm1::CatchScreen(int DNum,int Qlity){
//函数功能:扫描改变的屏幕区域,并切经过优化处理,最后发送这些区域数据
//DNum: 偏移量 Qlity:图象质量
HDC dc=GetDC(GetDesktopWindow());
Graphics::TBitmap *bm=new Graphics::TBitmap;
bm->Width=Sw;
bm->Height=Sh;
BitBlt(bm->Canvas->Handle,0,0,Sw-1,Sh-1,dc,0,0);
int num1,num2,num3;
int nowx,nowy;
bool Change;
bool ItemChange[MAXXCount][MAXYCount];
for (num1=0;num1 nowx=ItemWidth*num1;
for (num2=0;num2 nowy=ItemHeight*num2;
Change=false;
for (num3=0;num3 Colors[num1][num2][num3]=bm->Canvas->Pixels[nowx+Dests[num3].x][nowy+Dests[num3].y];
if (Colors[num1][num2][num3]!=BakColors[num1][num2][num3]){
BakColors[num1][num2][num3]=Colors[num1][num2][num3];
ItemChange[num1][num2]=true;
}
}
}
}

int CNum,MaxCNum;
int ChangedNum=0;
TRect *Rect;
int num4;
int MinSize=10000;
int m;
TRect MinRect;
Graphics::TBitmap *bt2=new Graphics::TBitmap;
TJPEGImage *j=new TJPEGImage;
//************************
j->Quality=Qlity;
//************************
CopyScreenUint CopyScreen;
CopyScreenItemUint CopyScreenItem;
TMemoryStream *ms=new TMemoryStream;
ms->Write(&TcpMsg,sizeof(TcpMsgUint));
ms->Write(&CopyScreen,sizeof(CopyScreenUint));
do{
for (num1=0;num1 for (num2=0;num2 for (num3=num1+1;num3<=xCount;num3++){
MaxCNum=0;
for (num4=num2+1;num4<=yCount;num4++){ //遍历所有矩形
CNum=GetChangedNum(TRect(num1,num2,num3,num4));
if (CNum>MaxCNum) MaxCNum=CNum;
m=(num3-num1)*(num4-num2);
if (2*m-CNum MinSize=2*m-CNum;
MinRect=TRect(num1,num2,num3,num4);
}
}
}
TMemoryStream *ms;
BitBlt(bt2->Canvas->Handle,0,0,ItemWidth-1,ItemHeight-1,bt->Canvas->Handle,0,0);
j->Assign(bt2);
j->SaveToStream(ms2);
CopyScreenItem.Rect=TRect(num1,num2,num3,num4);
CopyScreenItem.FileType=JPEGFILE; //JPEGFILE 定义为:#define JPEGFILE 1
ms2->Position=0;
CopyScreenItem.Length=ms2->Size;
ms->Write(&amp;CopyScreenItem,sizeof(ScreenItemUint));
ms->CopyFrom(ms2,ms2->Size);
ChangedNum++;
}while(MaxCNum>0);
TcpMsg.Type=MsgCopyScreen;
ms->Position=0;
TcpMsg.Length=ms->Size-sizeof(TcpMsgUint);
CopyScreen.Count=ChangedNum;
ms->Write(&amp;TcpMsg,sizeof(TcpMsgUint));
ms->Write(&amp;CopyScreen,sizeof(CopyScreenUInt));
ms->Position=0;
sock->SendStream(ms);
}

  这个程序把屏幕画面切分为了多个部分,并存储画面为JPG格式,这样压缩率就变的十
分的高了。通过这种方法压缩处理过的数据,变得十分小,甚至在屏幕没有改变的情况下,
传送的数据量为0,在这里不做过多分析了,有兴趣的朋友,可以多看看。
 
我认为分块比较的话,那不如全图XOR下,再压缩。在最后的数据传输上都是差不多大的
不知道“分块比较”和“全图XOR下,再压缩”两者的速度有没有明显的差别
只是愚见 :)
 
全图XOR是行不通的,因为要还原图象必须参考上一副图象,假如上一副图象丢失了该怎么办呢?
 
http://delphi.mychangshu.com/downfile.asp?ID=945&amp;location=fastscreen.doc
 
但是分块比较还是要原图为比较基础的呀!
 
利用VNC 的 VNCHOOK。DLL 吧, 帮你完成了 通知屏幕更新部分的 RECT ,鼠标,键盘的
消息, 我用过,帅极了

不过对学习过程来说,用人家的东西不太好,没帮助
 
to 活着viva:
VNC 的 VNCHOOK。DLL 哪里有。
 
留E-MAIL 吧, 发给你
 
:活着VIVA: 你好,最近我也在思考同样的问题
能否能我一份 VHCHOOK.dll

谢谢
 
:活着VIVA: 你好 E-mail:yuanzhicheng@263.net
 
能否能我一份 VHCHOOK.dll?先谢谢了
 
后退
顶部