下午在弄远程控制的时候,需要将目标机器当前桌面的图像块信息发送到客户端并且在客户端显示出来。
简单的来讲,服务器端可以将屏幕内容抓下来发生给客户端。简单的抓屏基本是流程是:
GetDC --> GetBitmap --> GetDIBits等来保持dc相关的位图数据。用GDI需要关于位图文件结构,比如说要构造位图文件头信息、位图Header信息、数据块信息的填充等。使用GDIPlus可以简化这部分处理,因为Image类提供了一个save()方法用于保存图片信息,而且还可以按照各种编码形式进行存储为不同的格式。
最初的想法是GetDC后,直接将dc中的位图句柄HBitmap获取出来,然后用HBitmap来构造一个Gdiplus的Bitmap对象,然后调用Bitmap对象的save方法,这样非常简单,几行代码就完成了。代码如下:
执行发现hOldBmp = (HBITMAP)::SelectObject(hdc, hNewBmp); 返回的hOldBmp为空。注意上面的代码中hNewBmp是空的,我本意是想获取hdc原来关联的HBitmap对象,所以我将一个空的位图对象选入到hdc中,返回原来的老的位图对象,失败了。最初想法是可能hNewBmp为空导致的select不出来老的位图对象。于是我创建了一了一个hNewBmp,然后对dc调用SelectObject,发现还是返回的老的位图对象还是空的,查了msdn关于SelectObject函数的说明,发现关于SelectObject函数在选入位图对象的时候有一句说明:
位图选择只能针对内存DC使用,并且一次只能将一个位图选入到一个内存DC中。原来与此,那简单,修改了下代码:
OK了。
关于SelectObject函数使用,需要注意:
1、如果是将位图GDI对象选入到dc中,只能选入到内存DC而不能是窗口相关DC,并且只能将一个位图选入到一个内存DC中;
2、使用SelectObject将一个新的Gdi对象选入到dc中,使用完毕后需要回复原来dc的内容,也就是重新调用SelectObject函数将原来的Gdi对象重新选入到dc中,这就需要在第一次SelectObject的时候需要保存其返回的老的Gdi对象句柄;