知道了位图数据和指针,怎么样将其保存在电脑上?
发布网友
发布时间:2022-08-24 18:30
我来回答
共1个回答
热心网友
时间:2024-01-28 18:19
下面是关于mouse_event的示例代码:
POINT lpPoint;
GetCursorPos(&lpPoint);
SetCursorPos(lpPoint.x, lpPoint.y);
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
上面的代码表示鼠标的双击,若要表示单击,用两个mouse_event即可(一次放下,一次松开)。
注意,不管是模拟键盘还是鼠标事件,都要注意还原,即按完键要松开,一个keydown对应一个keyup;鼠标单击完也要松开, 不然可能影响程序的功能 远程截取屏幕显示
服务端在接收到客户端的屏幕数据请求后,通过使用当前屏幕设备的句柄,开始向开辟的内存区域复制屏幕数据,得到与设备相关的GDI位图;然后再通过设置位图信息头、调色板等,最后得到与设备无关的DIB位图。
2.1获取当前屏幕的设备相关位图[3](DDB)
设备相关位图(DDB)也称为图形设备接口(GDI)位图,在MFC库中用CBitmap类来存储。该对象包含与设备相关的GDI模块数据结构。应用程序在截获屏幕显示数据的时候,将数据填充到开辟的相容性内存区域中,并与CBitmap对象的句柄建立关联,从而得到GDI位图数据的备份。但由于GDI位图中关于位的安排完全依赖于显示设备,在不同类型计算机间传递GDI位图是没有意义的。所以还需要进一步转化,得到设备无关位图DIB。
(1)得到当前屏幕的分辨率,从而确定截取屏幕的范围;
ScreenX=GetSystemMetrics(SM_CXSCREEN);
ScreenY=GetSystemMetrics(SM_CYSCREEN);
(2)得到屏幕HDC,并开辟相容性内存区域,建立相容性的HBITMAP;
HDC hdcmy=CreateDC("DISPLAY",NULL,NULL, NULL);
HDC hbufdc=CreateCompatibleDC(hdcmy);
HBITMAP hBit=CreateCompatibleBitmap(hdcmy, ScreenX,ScreenY);
(3)将当前屏幕内容复制到之前开辟的内存区域中,得到当前屏幕的GDI位图;
HBITMAP hOldBitmap=(HBITMAP)SelectObject(hbufdc,hBit);
StretchBlt(hbufdc,0,0,ScreenX,ScreenY,hdcmy,0,0,ScreenX,ScreenY,SRCCOPY);
hBit=(HBITMAP)SelectObject(hbufdc,hOldBitmap);
2.2转化设备相关位图(DDB)至设备无关位图[3](DIB)
DIB自带颜色信息,可以实现调色板管理,任何运行Windows的计算机中都可以处理这种标准的位图格式,BMP文件中就包含了一个DIB,主要由位图文件头、位图信息头、调色板和DIB图像数据4个部分组成,DDB向DIB的转化实际上就是利用DDB中包含的图像信息,填充DIB除位图文件头的另外3个部分,从而得到与设备无关的位图数据。最后可再通过添加位图文件头,构成一幅标准的BMP图像。
(1)通过BITMAP句柄hBit,得到位图信息,随后填充BITMAPINFOHEADER结构,计算InfoHeader长度,初始化调色板,最后分配存储空间存放上述信息头与调色板数据;
GetObject(hBit,sizeof(bitmap),(LPSTR)&bitmap);
int ncolors=1<<(bitmap.bmPlanes*bitmap.bmBitsPixel);
DWORD dwLen=sizeof(BITMAPINFOHEADER)+ncolors*sizeof (RGBQUAD);
HANDLE hDib=GlobalAlloc(GMEM_FIXED,dwLen);
(2)计算位图数据实际占用的字节数,使其宽度大于或者等于离4最近的整数倍,修正原biSizeImage数值,然后重新计算并分配空间用于存储信息头,调色板和实际图像数据;
bi.biSizeImage=((((bi.biWidth*bi.biBitCount)+31)&~31)/8)*bi.biHeight;
dwLen += bi.biSizeImage;
if(handle=GlobalReAlloc(hDib,dwLen,GMEM_MOVEABLE)) hDib=handle;
(3)向开辟的指定存储区域中复制上述信息头、调色板以及实际图像信息3部分数据,最后返回该存储区域的句柄,得到最终的DIB位图;
LPBITMAPINFOHEADER lpbi=(LPBITMAPINFOHEADER)hDib;
GetDIBits( hdc, bitmap,0L,(DWORD)bi.biHeight,(LPBYTE)lpbi +(bi.biSize+ncolors
*sizeof(RGBQUAD)),(LPBITMAPINFO)lpbi,(DWORD)DIB_RGB_COLORS);
3 屏幕数据传送控制
屏幕数据的传送控制主要在如何确认服务端与客户端之间的连接,服务端如何定时分块发送屏幕数据,客户端如何拼接屏幕数据并显示图像,服务端如何响应客户端的鼠标事件等几个方面。
3.1服务端与客户端的连接确认
双方连接可以由客户端指定服务端IP地址,或者在子网段内发送通信对方标识,服务端接收到该标识后,向客户端发送确认标识,客户端收到确认信息后,表明双方实现连接。
以下代码为客户端程序片断,服务端程序将发送和接收函数的顺序对调即可。
char cFlag[8]="CopyScr\0";
send(sktClient,cFlag,8,0);//发送client端标志
recv(sktClient,cFlag,8,0);//接收server端标志
3.2服务端定时分块发送屏幕数据
客户端以某一定时器设定为间隔,向服务端请求屏幕数据,服务端收到请求后,首先获取当前屏幕的GDI位图数据,并转化为DIB位图数据,随后采用分块传送的方式,向客户端发送屏幕的位图数据,分块过程如下所示:
(1)发送屏幕位图数据的相关信息,诸如尺寸、长度、高度等信息至客户端;
send(sktClient,(char*)&ScrInfo,sizeof(ScrInfo)+1,0);
(2)分块发送DIB位图数据,以SENDBLOCK为分块尺寸,同时调整当前数据指针位置;
LPBYTE plmagePoint=(LPBYTE)hDib;
for(WORD i=0;i<(ScrInfo.dwSize/SENDBLOCK);i++){
send(sktClient,(char*)plmagePoint,sizeof(BYTE)*SENDBLOCK,0);
plmagePoint=plmagePoint + SENDBLOCK;
recv(sktClient,(char*)&StopFlag,sizeof(int)+1,0);}
(3)当屏幕位图数据不是刚好等于分块尺寸倍数的时候,用于处理余下的数据传送;
if (ScrInfo.dwSize %SENDBLOCK)
send(sktClient,(char*)plmagePoint,ScrInfo.dwSize%SENDBLOCK,0);
3.3客户端拼接屏幕数据并显示图像
客户端的屏幕数据拼接程序,刚好与服务端的屏幕数据切分程序相对应,首先是接收屏幕位图相关信息,然后按照指定的分块大小接收屏幕数据,最后将小于分块尺寸的屏幕数据单独进行接收处理,得到服务端完整的一次屏幕数据,位图采用StretchDIBits函数显示。
StretchDIBits(dc,0,0,rect.right,rect.bottom,0,0,
((LPBITMAPINFOHEADER)SvrData)->biWidth,
((LPBITMAPINFOHEADER)SvrData)->biHeight,
(LPBYTE)SvrData+(sizeof(BITMAPINFOHEADER)+color*sizeof(RGBQUAD)),
(LPBITMAPINFO)SvrData,DIB_RGB_COLORS,SRCCOPY);
3.4服务端响应客户端的鼠标事件
当使用鼠标点击客户端中显示服务端当前屏幕的区域,客户端程序将会记录下具体的左/右键,单/双击,X/Y坐标位置等信息,作为鼠标事件发送给服务端,服务端随后进行解析,并作出相应的响应,从而实现客户端得到服务端屏幕并加以控制的功能。
mouse_event(MOUSEEVENTF_LEFTDOWN ,0,0,0,GetMessageExtraInfo());