看到一段代码,内容是:
//获取窗口DC
HDC hdc = GetDC(hWnd);
//获取窗口的客户区区域
RECT rect;
GetClientRect(hWnd, &rect);
//获取当前窗口的位图
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hBitmapSrc;
hBitmapSrc = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
SelectObject(hMemDC, hBitmapSrc);
BitBlt(hMemDC, 0, 0, rect.right, rect.bottom, hdc, 0, 0, SRCCOPY);
SaveBitmap(hBitmapSrc , "C:\\123.bmp"); // SaveBitmap()是自定义的一个函数,用来把传递进来的位图句柄保存成图片文件
// 结果是C:\\123.bmp内容是hWnd的窗口内容
原来一直觉得,HBITMAP选进设备DC以后,是将图片数据拷贝到DC上,从这段代码当然这里自然而然猜想,HBITMAP选进DC后,对DC的操作会影响到HBIMAP。
于是添加了如下测试代码:
//把窗口填充成白色
SelectObject(hdc, GetStockObject(WHITE_PEN));
SelectObject(hdc, GetStockObject(WHITE_BRUSH));
Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
HDC hMemDC2 = CreateCompatibleDC(hdc);
SelectObject(hMemDC2, hBitmapSrc);
BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC2, 0, 0, SRCCOPY);
先把原窗口拷贝成白色,然后再把选入了hBitmapSrc的内存DC拷贝到原窗口上,测试发现,窗口还是白色,无效。这是为什么呢。
百度下CreateCompatibleBitmap,发现百度百科里面介绍:
HDC hdc=GetDC(hwnd);
HDC memdc=CreateCompatibleDC(hdc);
RECT rc;
BITMAP bmp;
HBITMAP holdbmp,hbmp=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_CLOCK));//从资源加载位图
holdbmp=(HBITMAP)SelectObject(memdc,hbmp);//这里把hbmp的位图选择到兼容DC memdc,之后这个兼容DC就拥有和
//hbmp同样大小的绘图区域,注意超出位图返回的GDI输出都是无效的.
GetObject(hbmp,sizeof(BITMAP),&bmp);//这里获取
位图的大小信息,事实上也是兼容DC绘图输出的范围
SetRect(&rc,0,0,bmp.bmWidth,bmp.bmHeight);
DrawText(memdc,"Center Line Text" -1,&rc,DT_VCENTER|DT_SINGLELINE|DT_CENTER);//在兼容DC中间位置输出字符串
//这样以来我们就相当于把hbmp这个位图加上了文字标注,我们可以把这个增加了文字标注的位图保存起来.一个简单的图像处理基本就OK了.
SelectObject(memdc,holdbmp);//复原兼容DC数据.
DeleteDC(memdc);
ReleaseDC(hwnd, hdc);
这说明我的猜想是对的,如果HBITMAP选进了DC,对DC的操作的确会影响到HBITMAP。但代码测试不无效时为什么呢。
突然想到,可能使一个HBITMAP不能同时选进两个DC。做了如下测试
//获取窗口DC
HDC hdc = GetDC(hWnd);
//获取窗口的客户区区域
RECT rect;
GetClientRect(hWnd, &rect);
//获取当前窗口的位图
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hBitmapSrc;
hBitmapSrc = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
HGDIOBJ hOldBt = SelectObject(hMemDC, hBitmapSrc); // 修改,保存老位图句柄
BitBlt(hMemDC, 0, 0, rect.right, rect.bottom, hdc, 0, 0, SRCCOPY);
//获取当前窗口位图的像素颜色数据
BYTE *pBitmapDataSrc = new BYTE[(rect.right-rect.left)*(rect.bottom-rect.top)*4];
GetBitmapBits(hBitmapSrc, (rect.right-rect.left)*(rect.bottom-rect.top)*4, pBitmapDataSrc);
//把窗口填充成白色
SelectObject(hdc, GetStockObject(WHITE_PEN));
SelectObject(hdc, GetStockObject(WHITE_BRUSH));
Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
TextOut(hMemDC, 100, 100, _T("123456abcd"), 10); // 新加内容,为了验证是否是之后拷贝上去的,多画了点东西
SelectObject(hMemDC, hOldBt); // 新加内容
HDC hMemDC2 = CreateCompatibleDC(hdc);
SelectObject(hMemDC2, hBitmapSrc);
BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC2, 0, 0, SRCCOPY);
return;
验证无误。