当屏幕刷新的时候闪烁,原因是绘图与显示器刷新不同步,有时间差,为解决这一问题,这就需要用到双缓冲技术来绘图了。双缓冲技术是相对单缓冲而言的,单缓冲就是直接在设备DC上绘图;而双缓冲就是先在一个与设备DC相兼容的内存缓冲区里进行绘图,然后再一次性复制到设备DC上。一次性在屏幕上显示就不会出现闪烁的现象。
加载图标、游标、动画游标或位图。
HANDLE LoadImageA(
[in, optional] HINSTANCE hInst,
[in] LPCSTR name,
[in] UINT type,
[in] int cx,
[in] int cy,
[in] UINT fuLoad
);
参数解析
参数名 | 含义 |
---|---|
hInst | 【1】DLL 或可执行文件 (.exe 模块的句柄) ,其中包含要加载的图像。 有关详细信息,请参阅 GetModuleHandle。 请注意,从 32 位 Windows 开始,实例句柄 (HINSTANCE) ,例如由 WinMain 系统函数调用公开的应用程序实例句柄,而模块句柄 (HMODULE) 也是如此。【2】若要加载 OEM 映像,请将此参数设置为 NULL。【3】若要加载独立资源 (图标、游标或位图文件) (例如,c:\myimage.bmp),请将此参数设置为 NULL。 |
name | 要加载的图像。 如果 hinst 参数为非 NULL 且 fuLoad 参数省略 LR_LOADFROMFILE, 则 lpszName 在 hinst 模块中指定映像资源。 如果要从模块按名称加载映像资源, lpszName 参数是指向包含映像资源名称的以 null 结尾的字符串的指针。 如果要从模块中按序号加载图像资源,请使用 MAKEINTRESOURCE 宏将图像序号转换为可传递给 LoadImage 函数的窗体。 |
type | 要加载的图像的类型. 见下表 |
cx | 图标或光标的宽度(以像素为单位)。 如果此参数为零且 fuLoad 参数 LR_DEFAULTSIZE,则函数使用 SM_CXICON 或 SM_CXCURSOR 系统指标值来设置宽度。 如果此参数为零且未使用 LR_DEFAULTSIZE ,则函数使用实际资源宽度。 |
cy | 图标或光标的高度(以像素为单位)。 如果此参数为零且 fuLoad 参数 LR_DEFAULTSIZE,则函数使用 SM_CYICON 或 SM_CYCURSOR 系统指标值来设置高度。 如果此参数为零且未使用 LR_DEFAULTSIZE ,则函数使用实际资源高度。 |
fuLoad | 见下表 |
返回值
类型: HANDLE
如果函数成功,则返回值是新加载的图像的句柄。
如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。
备注
如果 IS_INTRESOURCE (lpszName) 为 TRUE, 则 lpszName 指定给定资源的整数标识符。 否则,它是指向以 null 结尾的字符串的指针。 如果字符串的第一个字符是磅号 (#) ,则其余字符表示指定资源的整数标识符的十进制数。 例如,字符串“#258”表示标识符 258。
使用完加载的位图、游标或图标而不指定 LR_SHARED 标志时,可以通过调用下表中的某个函数来释放其关联的内存。
资源 | 发布函数 |
---|---|
Bitmap | DeleteObject |
游标 | DestroyCursor |
图标 | DestroyIcon |
**hInst: **
如果 hinst 参数为 NULL 且 fuLoad 参数省略 LR_LOADFROMFILE 值, 则 lpszName 指定要加载的 OEM 映像。 OEM 映像标识符在 Winuser.h 中定义,并具有以下前缀。
前缀 | 含义 |
---|---|
OBM_ | OEM 位图 |
OIC_ | OEM 图标 |
Ocr_ | OEM 游标 |
type:
值 | 含义 |
---|---|
IMAGE_BITMAP | 加载位图。 |
IMAGE_CURSOR | 加载游标。 |
IMAGE_ICON | 含义加载图标。 |
fuLoad:
此参数可使用以下一个或多个值。
Value | 含义 |
---|---|
LR_CREATEDIBSECTION | 当 uType 参数指定IMAGE_BITMAP时,会导致函数返回 DIB 节位图而不是兼容的位图。 此标志可用于加载位图而不将其映射到显示设备的颜色。 |
LR_DEFAULTCOLOR | 默认标志;它不执行任何作用。 这意味着“不 LR_MONOCHROME”。 |
LR_DEFAULTSIZE | 如果 cxDesired 或 cyDesired 值设置为零,则使用由光标或图标的系统指标值指定的宽度或高度。 如果未指定此标志, 并且 cxDesired 和 cyDesired 设置为零,则函数将使用实际资源大小。 如果资源包含多个图像,则函数使用第一个图像的大小。 |
LR_LOADFROMFILE | 从 lpszName 指定的文件中加载独立图像, (图标、游标或位图文件) 。 |
LR_LOADMAP3DCOLORS | 在颜色表中搜索图像,并将以下灰色阴影替换为相应的三维颜色。Dk Gray,RGB (128,128,128) 与 COLOR_3DSHADOW灰色,RGB (192,192,192) 与 COLOR_3DFACELt Gray,RGB (223,223,223 ) ,COLOR_3DLIGHT如果要加载颜色深度大于 8bpp 的位图,请不要使用此选项。 |
LR_LOADTRANSPARENT | 检索图像中第一个像素的颜色值,并将颜色表中的相应条目替换为默认窗口颜色 (COLOR_WINDOW) 。 使用该条目的图像中的所有像素都将成为默认窗口颜色。 此值仅适用于具有相应颜色表的图像。如果要加载颜色深度大于 8bpp 的位图,请不要使用此选项。如果 fuLoad 同时包括 LR_LOADTRANSPARENT 和 LR_LOADMAP3DCOLORS 值, LR_LOADTRANSPARENT 优先。 但是,颜色表项替换为 COLOR_3DFACE 而不是 COLOR_WINDOW。 |
LR_MONOCHROME | 加载黑白图像。 |
LR_SHARED | 如果多次加载映像,则共享映像句柄。 如果未设置 LR_SHARED ,则对同一资源的 LoadImage 的第二次调用将再次加载映像并返回不同的句柄。使用此标志时,系统会在不再需要资源时销毁资源。不要对具有非标准大小的图像使用 LR_SHARED ,这些图像在加载后可能会更改,或者从文件加载。加载系统图标或游标时,必须使用 LR_SHARED ,否则函数将无法加载资源。无论请求的大小如何,此函数都会找到缓存中请求的资源名称的第一个映像。 |
LR_VGACOLOR | 使用真正的 VGA 颜色。 |
CreateCompatibleDC 函数 (DC) 创建与指定设备兼容的内存设备上下文。
HDC CreateCompatibleDC(
[in] HDC hdc
);
参数名 | 含义 |
---|---|
hdc | 现有 DC 的句柄。 如果此句柄为 NULL,则该函数将创建与应用程序的当前屏幕兼容的内存 DC。 |
返回值
如果函数成功,则返回值是内存 DC 的句柄。
如果函数失败,则返回值为 NULL。
备注
BitBlt 函数执行与从指定源设备上下文到目标设备上下文中的像素矩形对应的颜色数据的位块传输。
BOOL BitBlt(
[in] HDC hdc,
[in] int x,
[in] int y,
[in] int cx,
[in] int cy,
[in] HDC hdcSrc,
[in] int x1,
[in] int y1,
[in] DWORD rop
);
参数解析:
参数名 | 含义 |
---|---|
hdc | 目标设备上下文的句柄。 |
x | 目标矩形左上角的 x 坐标(以逻辑单位为单位)。 |
y | 目标矩形左上角的 y 坐标(以逻辑单位为单位)。 |
cx | 源矩形和目标矩形的宽度(以逻辑单位为单位)。 |
cy | 源和目标矩形的高度(以逻辑单位为单位)。 |
hdcSrc | 源设备上下文的句柄。 |
x1 | 源矩形左上角的 x 坐标(以逻辑单位为单位)。 |
y1 | 源矩形左上角的 y 坐标(以逻辑单位为单位)。 |
rop | 光栅操作代码。 这些代码定义源矩形的颜色数据如何与目标矩形的颜色数据组合,以实现最终颜色。 |
**光栅操作代码: **
Value | 含义 |
---|---|
黑暗 | 使用与物理调色板中的索引 0 关联的颜色填充目标矩形。 (对于默认的物理调色板,该颜色为黑色。) |
CAPTUREBLT | 包括在生成的图像中窗口顶部分层的任何窗口。 默认情况下,图像仅包含窗口。 请注意,这通常无法用于打印设备上下文。 |
DSTINVERT | 反转目标矩形。 |
MERGECOPY | 使用布尔 AND 运算符将源矩形的颜色与当前在 hdcDest 中选择的画笔合并。 |
MERGEPAINT | 使用布尔 OR 运算符将倒置源矩形的颜色与目标矩形的颜色合并。 |
NOMIRRORBITMAP | 防止位图镜像。 |
NOTSRCCOPY | 将倒置源矩形复制到目标。 |
NOTSRCERASE | 使用布尔 OR 运算符合并源矩形和目标矩形的颜色,然后反转生成的颜色。 |
PATCOPY | 将当前在 hdcDest 中选择的画笔复制到目标位图中。 |
PATINVERT | 使用布尔 XOR 运算符将当前在 hdcDest 中选择的画笔的颜色与目标矩形的颜色组合在一起。 |
PATPAINT | 使用布尔 OR 运算符将当前在 hdcDest 中选择的画笔的颜色与倒置源矩形的颜色组合在一起。 此操作的结果与目标矩形的颜色结合使用,方法是使用布尔 OR 运算符。 |
SRCAND | 使用布尔 AND 运算符合并源矩形和目标矩形的颜色。 |
SRCCOPY | 将源矩形直接复制到目标矩形。 |
SRCERASE | 使用布尔 AND 运算符将目标矩形的反转颜色与源矩形的颜色组合在一起。 |
SRCINVERT | 使用布尔 XOR 运算符合并源矩形和目标矩形的颜色。 |
SRCPAINT | 使用布尔 OR 运算符合并源矩形和目标矩形的颜色。 |
白 | 使用与物理调色板中的索引 1 关联的颜色填充目标矩形。 (对于默认的物理调色板,该颜色为白色。) |
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。
备注
代码示例
if (!BitBlt(hdcMemDC,
0, 0,
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
hdcWindow,
0, 0,
SRCCOPY))
{
MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
goto done;
}
StretchBlt 函数将一个位图从源矩形复制到目标矩形中,并拉伸或压缩位图以适应目标矩形的尺寸(如有必要)。 系统根据当前在目标设备上下文中设置的拉伸模式拉伸或压缩位图。
BOOL StretchBlt(
[in] HDC hdcDest,
[in] int xDest,
[in] int yDest,
[in] int wDest,
[in] int hDest,
[in] HDC hdcSrc,
[in] int xSrc,
[in] int ySrc,
[in] int wSrc,
[in] int hSrc,
[in] DWORD rop
);
参数解析:
参数名 | 含义 |
---|---|
hdcDest | 目标设备上下文的句柄。 |
xDest | 目标矩形左上角的 x 坐标(以逻辑单位为单位)。 |
yDest | 目标矩形左上角的 y 坐标(以逻辑单位为单位)。 |
wDest | 目标矩形的宽度(以逻辑单元表示)。 |
hDest | 目标矩形的高度(以逻辑单元表示)。 |
hdcSrc | 源设备上下文的句柄。 |
xSrc | 源矩形左上角的 x 坐标(以逻辑单位为单位)。 |
ySrc | 源矩形左上角的 y 坐标(以逻辑单位为单位)。 |
wSrc | 源矩形的宽度(以逻辑单元表示)。 |
hSrc | 源矩形的高度(以逻辑单元表示)。 |
rop | 要执行的光栅操作。 光栅操作代码定义系统如何在涉及画笔、源位图和目标位图的输出操作中组合颜色。参考上面的表 |
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。
备注
TransparentBlt 函数执行与从指定源设备上下文到目标设备上下文中的像素矩形对应的颜色数据的位块传输。
BOOL TransparentBlt(
[in] HDC hdcDest,
[in] int xoriginDest,
[in] int yoriginDest,
[in] int wDest,
[in] int hDest,
[in] HDC hdcSrc,
[in] int xoriginSrc,
[in] int yoriginSrc,
[in] int wSrc,
[in] int hSrc,
[in] UINT crTransparent
);
参数解析:
参数名 | 含义 |
---|---|
hdcDest | 目标设备上下文的句柄。 |
xoriginDest | 目标矩形左上角的 x 坐标(以逻辑单位为单位)。 |
yoriginDest | 目标矩形左上角的 y 坐标(以逻辑单位为单位)。 |
wDest | 目标矩形的宽度(以逻辑单元表示)。 |
hDest | 目标矩形的高度(以逻辑单元表示)。 |
hdcSrc | 源设备上下文的句柄。 |
xoriginSrc | 源矩形的 x 坐标(以逻辑单位为单位)。 |
yoriginSrc | 源矩形的 y 坐标(以逻辑单位为单位)。 |
wSrc | 源矩形的宽度(以逻辑单元表示)。 |
hSrc | 源矩形的高度(以逻辑单元表示)。 |
crTransparent | 要视为透明的源位图中的 RGB 颜色。 |
返回值:
如果函数成功,则返回值为 TRUE。
如果函数失败,则返回值为 FALSE。
备注:
DeleteDC 函数 (DC) 删除指定的设备上下文。
BOOL DeleteDC(
[in] HDC hdc // 设备上下文的句柄。
);
返回值:
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。
备注:
应用程序不得删除通过调用 GetDC 函数获取其句柄的 DC。 相反,它必须调用 ReleaseDC 函数来释放 DC。
#include
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("NueXini");
HWND hWnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Error"), szAppName, MB_ICONERROR | MB_OK);
return 0;
}
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc, hdcMem;
PAINTSTRUCT ps;
HBITMAP hBitMap;
BITMAP bm;
switch (message)
{
case WM_CREATE:
return 0;
case WM_SIZE:
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
hdcMem = CreateCompatibleDC(hdc);
hBitMap = (HBITMAP)LoadImage(NULL, TEXT("../monster.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
SelectObject(hdcMem, hBitMap);
GetObject(hBitMap, sizeof(BITMAP), &bm);
// 原样输出位图
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
// 复制上面的位图
StretchBlt(hdc, 0, bm.bmHeight, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
// 获取一个颜色像素,输出透明位图
TransparentBlt(hdc, bm.bmWidth + 10, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, GetPixel(hdcMem, 0, 0));
// 复制上面的位图, 缩小2倍
StretchBlt(hdc, bm.bmWidth + 10, bm.bmHeight, bm.bmWidth / 2, bm.bmHeight / 2, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
// 获取一个颜色像素,输出缩小2倍的透明位图
TransparentBlt(hdc, bm.bmWidth * 2, 0, bm.bmWidth / 2, bm.bmHeight / 2, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, GetPixel(hdcMem, 0, 0));
// 释放位图
DeleteObject(hBitMap);
// 释放内存DC
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
enjoy it ~