位图的加载方式:
LoadBitmap:加载资源视图中的bmp图片
HBITMAP LoadBitmap(
HINSTANCE hInstance,
LPCTSTR lpBitmapName
);
LoadImage:可以加载位图、图标、光标多种图像数据,既可以从资源视图中加载,也可以从磁盘中直接加载
HANDLE LoadImage(
HINSTANCE hinst,
LPCTSTR lpszName,
UINT uType, // 类型:位图、图标、光标
int cxDesired,
int cyDesired,
UINT fuLoad
);
如何理解DC以及如何将图片绘制到DC上?
我们将DC(设备)看成一个打印机,位图看成一个需要打印的A4纸,将我们要显示的过程看成打印机打印纸张的过程,打印的东西呈现在新的A4纸上,也就是实现了位图的绘制。当我们需要多次绘制时,类似多次打印纸张时,只需要再换一张纸张即可继续打印。
为什么要使用兼容DC?
因为Windows不允许直接将位图绘制到需要显示的窗口DC(设备上下文)上,只能将位图先放入兼容的设备上下文中(兼容DC),然后将兼容上下文的内容拷贝到设备上下文中,才能实现位图的绘制。
如何将兼容上下文的内容拷贝到设备上下文?
使用BitBlt或者StretchBlt两个API,它们实现的功能就是将兼容DC(源DC)中的内容拷贝目标DC(需要显示的DC)中。他们的区别是,BitBlt不能进行位图的缩放功能,而Stretch能实现缩放。
BitBlt
BOOL BitBlt(
HDC hdcDest, // 目标DC句柄
int nXDest, int nYDest, int nWidth, int nHeight, // 目标区域
HDC hdcSrc, // 源DC句柄
int nXSrc, int nYSrc, //源区域的左上角
DWORD dwRop // 操作的方式,一般为SRCCOPY(拷贝)
);
StretchBlt
BOOL StretchBlt(
HDC hdcDest, //目标DC的句柄
int xDest, int yDest, int wDest, int hDest, //目标DC的区域
HDC hdcSrc, //源DC的句柄
int xSrc, int ySrc, int wSrc, __in int hSrc, //源DC的区域
DWORD rop //操作标志,一般为SRCCOPY,意思为拷贝
);
示例:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
HDC hMemDC = ::CreateCompatibleDC(hdc);
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, g_hBmpBack);
BITMAP bmp;
::GetObject(g_hBmpBack, sizeof(BITMAP), &bmp);
::BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0, SRCCOPY);
/*RECT rc;
::GetClientRect(hWnd, &rc);
int nWidth = rc.right - rc.left;
int nHeight = rc.bottom - rc.top;
::StretchBlt(hdc, 0, 0, nWidth, nHeight, hMemDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);*/
::SelectObject(hMemDC, hOldBmp);
::DeleteDC(hMemDC);
EndPaint(hWnd, &ps);
}
break;
绘制位图的步骤:
1)获得目标DC句柄
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
2)创建与目标DC兼容的临时内存DC
HDC hMemDC = ::CreateCompatibleDC(hdc);
3)将位图句柄选入到临时内存DC中
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, g_hBmpBack);
4)使用BitBlt函数将临时内存DC中的位图拷贝到目标DC上来
BITMAP bmp;
::GetObject(g_hBmpBack, sizeof(BITMAP), &bmp);//根据位图句柄获取到位图的数据到bmp中
::BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0, SRCCOPY);
5)将现在的位图句柄选出临时内存DC,也就是将我们原来的位图句柄选入内存DC中。这里为什么需要选出来?如果不选出来,当前的位图句柄还在内存DC中,使用DeleteDC后将会同时删除现在使用的位图句柄。
::SelectObject(hMemDC, hOldBmp);
6)销毁临时的内存DC
::DeleteDC(hMemDC);
7)结束绘制
EndPaint(hWnd, &ps);
示例源码