上一篇:diff命令的好用功能 - 下一篇:Windows XP优化技巧大全
版权声明:可以任意转载,但转载时必须标明原作者charlee、原始链接http://tech.idv2.com/2009/02/26/screencapture-in-vc-tips/以及本声明。
最近想用VC写一个抓图程序。好久没用VC了,绝大部分知识都忘得一干二净了。 经过查阅无数资料之后终于得出一个差不多像样的程序来。 在这里说说基本思路吧。代码就不上了。
功能需求:执行抓图功能后,按下鼠标左键移动鼠标,可以在屏幕上框出一个框, 松开鼠标左键即可把选中部分的图像复制到主窗口中。然后再根据情况保存成图片。
基本思路如下:
1. 屏幕截图可以通过BitBlt来实现。用以下方法创建一个指向整个屏幕的DC:
CDC *pScreenDC = new CDC();
HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);
pScreenDC->Attach(hScreenDC);
要使用BitBlt,memDC是不可少的,因此要创建memDC:
CDC *pMemDC = new CDC(); pMemDC->CreateCompatibleDC(pScreenDC);
然后创建位图:
CBitmap *pBitmap = new CBitmap(); pBitmap->CreateCompatibleBitmap(pScreenDC, pRect->Width(), pRect->Height()); # pRect为用户选取的范围 CBitmap *pOldBitmap = pMemDC->SelectObject(pBitmap);
之后就可以把指定区域的内容复制到位图中。
pMemDC->BitBlt(0, 0, pRect->Width(), pRect->Height(), pScreenDC, 0, 0, SRCCOPY);
然后做些收尾工作,将位图对象返回即可:
pBitmap = pMemDC->SelectObject(pOldBitmap); pMemDC->DeleteDC(); delete pMemDC; return pBitmap;
需要将位图绘制到画面上时,使用同样的方法即可,只是这次BitBlt的方向是从 pMemDC 到 CClientDC dc(this)。
2. 在屏幕上直接画方框是不现实的,但可以换个思路:做个跟屏幕一样大的对话框, 将屏幕内容复制到这个对话框上,再在这个对话框上画方框。 这样看起来就像是在整个屏幕上画一样。
在资源编辑器中建一个对话框,不用加任何控件,并去掉标题栏。
在对话框的OnInitDialog()中首先按照上述方法将整个屏幕复制到对话框上。 屏幕大小可以用 GetSystemMetric 函数获得:
UINT nScreenWidth = GetSystemMetrics(SM_CXSCREEN); UINT nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
然后将窗口大小设置为全屏,并设置为总在最前。这样,对话框打开时屏幕不会发生任何变化, 但实质上屏幕已不再是原来的“屏幕”,而是由对话框“画出”的东西了。
3. 关于文档和视图的分工:文档负责处理数据,数据处理完后放在文档类的成员变量中即可, 并执行 UpdateAllViews(NULL) 来更新视图。 视图类在 OnDraw 中,通过 GetDocument() 函数获得自己的文档,取出其中的数据, 再将其绘制到画面上。
2009/3/1更新
4. 怎样快速进行图像运算:有时需要对图像做类似于Photoshop的滤镜一样的操作,要针对每个像素进行计算。 如果此时先建立DC再通过DC进行GetPixel/SetPixel,那速度是相当慢而且极其浪费CPU。 应该这样做:
// 获取位图信息 BITMAP bitmap; pBitmap->GetBitmap(&bitmap); // CBitmap * pBitmap; // 为位图数据分配内存 DWORD count = bitmap.bmWidth * bitmap.bmHeight * bitmap.bmBitsPixel / 8; BYTE * pData = (BYTE*)malloc(sizeof(BYTE) * count); // 获取位图数据 pBitmap->GetBitmapBits(count, pData);
上述代码只能在位图宽度是8的整数、32位图像的情况下使用,其他情况没有测试。 此时,获取到的pData就是位图数据,四个字节一组,分别是(R, G, B, 保留), 像素顺序是从左上角到右下角。
这样直接对pData进行计算即可。计算完成后,再用SetBitmapBits将图像放回位图中:
pBitmap->SetBitmapBits(count, pData);
2009-03-01 10:07
@welco 估计不能。BitBlt是GDI的函数,应该没办法处理DirectX的。
2009-03-21 14:07
抓出来 怎么保存呢

2009-02-28 14:17
BitBlt 能抓directx不