简单图形绘制
在win32上面绘制图形其实是比较简单的。要想进行图形绘制,关键是找到设备上下文。就我目前所知道的,获得设备上下文主要有这么几种方式:一、根据BeginPaint获得设备上下文,这主要在WM_PAINT使用;二、根据GetDC获得设备上下文,这主要用在非WM_PAINT消息中;三、CreateDC获得设备上下文,这个主要用在屏幕的截取;四、根据CreateCompatibleDC获得设备上下文,然后通过BitBlt进行绘制,这个一般用在图形界面较多的绘制场景。
WM_PAINT下用BeginPaint获得设备上下文是比较常用的方式,比如下面一段代码
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
MoveToEx(hdc, 100,100,NULL);
LineTo(hdc, 150,230);
Rectangle(hdc, 200, 200, 300, 300);
Ellipse(hdc, 15,15, 130, 130);
EndPaint(hdc, &ps);
break;
同样一段代码,如果是在鼠标响应的时候调用
case WM_RBUTTONUP:
hdc = GetDC(hWnd);
// TODO: Add any drawing code here...
MoveToEx(hdc, 100,100,NULL);
LineTo(hdc, 150,230);
Rectangle(hdc, 200, 200, 300, 300);
Ellipse(hdc, 15,15, 130, 130);
ReleaseDC(hWnd, hdc);
break;
画笔和画刷
要绘制出漂亮的图形,需要用到画笔和画刷了,简单来说,画笔是用来画线和边框的,那画刷就是用来填充那些封闭图形的。画笔能够控制线条的颜色、样式、大小等,画刷能够控制填充的类型、颜色、方式等。下面介绍画笔画刷的创建和使用,还有各种图形的绘制。颜色都用RGB进行设置。矩形、椭圆、弓形、扇形、多边形等这些是填充图形,都用当前的画笔画轮廓,用当前的画刷和多边形填充模式画填充。在绘制多条折线或多个多边形时,顶点数组定义时,需要注意:顶点是连续定义的,也按一笔画绘制。
画笔画刷的使用步骤:(两者使用一致)
- 创建画笔或画刷。
- 选取画笔或画刷(选入设备环境,记得保留先前画笔和画刷)(用SelectObject,此函数返回值为先前画笔画刷)。
- 使用绘图函数进行绘图。
- 删除自己所创建的画笔或画刷。(用DeleteObject)
用到的API接口
BeginPaint 函数为指定窗口进行绘图工作的准备,并用将和绘图有关的信息填充到一个PAINTSTRUCT结构中。
HDC BeginPaint(
[in] HWND hWnd, //窗口句柄
[out] LPPAINTSTRUCT lpPaint // 绘制信息
);
EndPaint 函数标记指定窗口的绘画过程结束;这个函数在每次调用BeginPaint函数之后被请求,但仅仅在绘画完成以后。
BOOL EndPaint(
HWND hWnd, // 窗口句柄
CONST PAINTSTRUCT *lpPaint // 绘制窗口的数据
);
MoveToEx 是函数,功能是将当前绘图位置移动到某个具体的点,同时也可获得之前位置的坐标。
BOOL MoveToEx(
[in] HDC hdc, //传入参数,设备上下文句柄。
[in] int x, //传入参数:新位置的X坐标。
[in] int y, //传入参数:新位置的Y坐标。
[out] LPPOINT lppt //传出参数:一个指向POINT结构的指针,用来存放上一个点的位置,若此参数为NULL,则不保存上一个点的位置
);
LineTo 用当前画笔画一条线,从当前位置连到一个指定的点。这个函数调用完毕,当前位置变成x,y。
BOOL LineTo(
[in] HDC hdc, //设备场景句柄
[in] int x, //线段终点X坐标位置,采用逻辑坐标表示。这个点不会实际画出来;它不属于线段的一部份
[in] int y //线段终点Y坐标位置,采用逻辑坐标表示。这个点不会实际画出来;它不属于线段的一部份
);
Rectangle 是一个函数,使用该函数画一个矩形,可以用当前的画笔画矩形轮廓,用当前画刷进行填充。
BOOL Rectangle(
[in] HDC hdc, //设备环境句柄。
[in] int left, //指定矩形左上角的逻辑X坐标。
[in] int top, //指定矩形左上角的逻辑Y坐标。
[in] int right, //指定矩形右下角的逻辑X坐标。
[in] int bottom //指定矩形右下角的逻辑Y坐标。
);
Ellipse 画一个椭圆。圆心是标识的矩形的中心。椭圆轮廓会被设备环境当前画笔绘画,同时椭圆被当前画刷填充。
BOOL Ellipse(
[in] HDC hdc, //设备环境句柄。
[in] int left, //矩形左上角横座标
[in] int top, //矩形左上角纵座标
[in] int right, //矩形右角横座标
[in] int bottom //矩形右下角纵座标
);
SetPixel 该函数将指定坐标处的像素设为指定的颜色。
COLORREF SetPixel(
[in] HDC hdc, //设备环境句柄。
[in] int x, //指定要设置的点的X轴坐标,按逻辑单位表示坐标。
[in] int y, //指定要设置的点的Y轴坐标,按逻辑单位表示坐标。
[in] COLORREF color //指定要用来绘制该点的颜色。
);
GetPixel 函数功能,该函数检索指定坐标点的像素的RGB颜色值。
COLORREF GetPixel(
[in] HDC hdc, //设备环境句柄。
[in] int x, //指定要检查的像素点的逻辑X轴坐标。
[in] int y //指定要检查的像素点的逻辑Y轴坐标。
);
Polygon 根据顶点绘制多边形
BOOL Polygon( HDC hdc,
CONST POINT *lpPoints, // 多边形的顶点
int nCount ); // 顶点的数量
// DrawPic.cpp : 定义应用程序的入口点。
//
#include "framework.h"
#include "DrawPic.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此处放置代码。
// 初始化全局字符串
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_DRAWPIC, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DRAWPIC));
MSG msg;
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DRAWPIC));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_DRAWPIC);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目标: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目标: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
HPEN hpen1, oldhpen, hpen2, hpen3, hpen4, hpen5, hpen;
HBRUSH hbrush1, oldhbrush, hbrush2, hbrush3, hbrush4, hbrush5, hbrush6;
static int xClient, yClient;
static POINT apt[5] = { 90,50,110,10,130,50,150,10,180,50 };//5个点
static POINT capt[] = { 200, 50, 230, 10, 260, 50, 290, 10, 310, 50,
200, 100, 230, 60, 260, 100, 290, 60, 310, 100,
200, 150, 230, 110, 260, 150, 290, 110, 310, 150 };
static DWORD asz[] = { 5,5,5 };
static POINT bapt[4] = { 350,50,350,80,370,50,450,10 };//4个点
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_SIZE:
{
xClient = LOWORD(lParam);
yClient = HIWORD(lParam);
break;
}
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
//还可以使用CreatePenIndirect创建画笔
//画一个红色点
SetPixel(hdc, 20, 50, RGB(255, 0, 0));
//画一条直线
hpen1 = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));//实线
oldhpen = (HPEN)SelectObject(hdc, hpen1);//选入画笔
MoveToEx(hdc, 30, 50, NULL);
LineTo(hdc, 70, 50);
SelectObject(hdc, oldhpen);//恢复先前画笔
DeleteObject(hpen1);//记得自创画笔一定删除
//画一条5个点折线
hpen2 = CreatePen(PS_DASH, 1, RGB(255, 255, 0));//段线
oldhpen = (HPEN)SelectObject(hdc, hpen2);//选入画笔
Polyline(hdc, apt, 5); //其后缀不带To,表示该函数不使用也不改变设备当前位置
SelectObject(hdc, oldhpen);//恢复先前画笔
DeleteObject(hpen2);//记得自创画笔一定删除
//画3条折线
hpen3 = CreatePen(PS_DASHDOT, 1, RGB(255, 0, 255));//线点
SetBkColor(hdc, RGB(0, 0, 222));// 设置当前背景颜色
oldhpen = (HPEN)SelectObject(hdc, hpen3);//选入画笔
PolyPolyline(hdc, capt, asz, 3);
SelectObject(hdc, oldhpen);//恢复先前画笔
DeleteObject(hpen3);//记得自创画笔一定删除
//画贝塞尔曲线(最少需要4个点)
hpen4 = (HPEN)GetStockObject(BLACK_PEN);//获得Windows预设的画笔画刷
oldhpen = (HPEN)SelectObject(hdc, hpen4);//选入画笔
PolyBezier(hdc, bapt, 4);// 4个点: 1和4是端点, 2.3点是控制点
// 7个点 : 1.4.7是端点, 其余是控制点
SelectObject(hdc, oldhpen);//恢复先前画笔
DeleteObject(hpen4);//记得自创画笔一定删除
//画无边框矩形
hbrush1 = CreateSolidBrush(RGB(0, 255, 0)); //绿色实心画刷
hpen = CreatePen(PS_NULL, 1, 0); //创建空画笔
oldhpen = (HPEN)SelectObject(hdc, hpen); //重点:填充图形的边框由当前画笔绘制
oldhbrush = (HBRUSH)SelectObject(hdc, hbrush1);//选入环境句柄
Rectangle(hdc, 10, 80, 70, 140);
SelectObject(hdc, oldhpen);
SelectObject(hdc, oldhbrush);
DeleteObject(hbrush1);//删除画刷
//圆角矩形
SetBkColor(hdc, RGB(0, 0, 0));// 设置当前背景颜色
hbrush2 = CreateHatchBrush(HS_FDIAGONAL, RGB(255, 255, 0));//创建画刷
oldhbrush = (HBRUSH)SelectObject(hdc, hbrush2);//选入设备环境
RoundRect(hdc, 90, 80, 150, 140, 20, 20);//画图
SelectObject(hdc, oldhbrush);//恢复先前画刷
DeleteObject(hbrush2);//删除画刷
//椭圆
SetBkColor(hdc, RGB(222, 0, 0));// 设置当前背景颜色
hbrush3 = CreateHatchBrush(HS_CROSS, RGB(255, 255, 0));
oldhbrush = (HBRUSH)SelectObject(hdc, hbrush3);
Ellipse(hdc, 10, 160, 70, 200);
SelectObject(hdc, oldhbrush);
DeleteObject(hbrush3);
//普通弧
SetDCPenColor(hdc, RGB(255, 0, 255)); //设置句柄颜色
hpen5 = (HPEN)GetStockObject(DC_PEN);
oldhpen = (HPEN)SelectObject(hdc, hpen5);
Arc(hdc, 90, 160, 150, 200, 90, 180, 150, 170);
SelectObject(hdc, oldhpen);
DeleteObject(hpen5);
//圆弧
MoveToEx(hdc, 190, 200, NULL);
AngleArc(hdc, 190, 200, 30, 10, 90); //终点会与当前位置连接起来
//弓形、弦
hbrush4 = CreateSolidBrush(RGB(155, 155, 155));
oldhbrush = (HBRUSH)SelectObject(hdc, hbrush4);
Chord(hdc, 240, 160, 300, 240, 270, 180, 290, 230);
SelectObject(hdc, oldhbrush);
DeleteObject(hbrush4);
//扇形
SetBkColor(hdc, RGB(35, 55, 111));// 设置当前背景颜色
hbrush5 = CreateHatchBrush(HS_HORIZONTAL, RGB(0, 255, 0));
oldhbrush = (HBRUSH)SelectObject(hdc, hbrush5);
Pie(hdc, 330, 160, 370, 220, 333, 26, 370, 220);
SelectObject(hdc, oldhbrush);
DeleteObject(hbrush5);
//绘制多边形,
POINT dot[5]{ 100,300,200,300,125,350,150,250,175,350 };//按笔画顺序绘制5个点
SetPolyFillMode(hdc, ALTERNATE);//设置填充模式
hbrush6 = CreateSolidBrush(RGB(0, 255, 0)); //绿色实心画刷
oldhbrush = (HBRUSH)SelectObject(hdc, hbrush6);
Polygon(hdc, dot, 5);//绘制多边形
SelectObject(hdc, oldhbrush);
DeleteObject(hbrush6);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
位图绘制
绘制位图步骤:
- 创建兼容DC(CreateCopatibleDC函数)
- 加载位图(LoadImage函数和LoadBitmap函数)
- 选取位图对象,使用BitBlt函数进行贴图(SelectObject函数)
- 释放兼容DC(DeleteDC函数)
加载位图API函数:
LoadImage
LoadImage是一种函数,功能是装载图标,光标,或位图。
HANDLE LoadImage(HINSTANCE hinst,// 处理包含被装载图像模块的实例句柄。若要装载OEM图像,则设此参数值为0。
LPCTSTR lpszName,// 图像资源名称
UINT uType, // 指定被装载图像类型,IMAGE_BITMAP:装载位图;IMAGE_CURSOR:装载光标;IMAGE_ICON:装载图标。
int cxDesired,// 指定图标或光标的宽度,以像素为单位
int cyDesired,// 指定图标或光标的高度,以像素为单位
UINT fuLoad);// 加载标识,含义见链接
LoadBitmap
该函数从模块的可执行文件中加载指定的位图资源,该函数已经被函数LoadImage替代。
void DrawBitMap(HDC hdc)
{
//创建兼容DC
HDC hdc_bmp = CreateCompatibleDC(hdc);
//加载位图
HBITMAP map = (HBITMAP)LoadImage(NULL, _TEXT("H:\\植物大战僵尸素材\\interface\\background1.bmp")
, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//选取位图对象,是用BitBlt函数贴图
SelectObject(hdc_bmp, map);
BitBlt(hdc, 0, 0, 1400, 600, hdc_bmp, 0, 0, SRCCOPY);
//释放兼容DC
DeleteDC(hdc_bmp);
}
双缓冲绘制
为什么需要使用双缓冲技术?可能很多朋友会问,不知道你们有没有发现,当屏幕刷新的时候会有闪烁,这样让人的体验感极差。原因是绘图与显示器刷新不同步,有时间差,为解决这一问题,这就需要用到双缓冲技术来绘图了。双缓冲技术是相对单缓冲而言的,单缓冲就是直接在设备DC上绘图;而双缓冲就是先在一个与设备DC相兼容的内存缓冲区里进行绘图,然后再一次性复制到设备DC上。一次性在屏幕上显示就不会出现闪烁的现象。
这里需要注意的是:我们创建的兼容DC,不能直接在上面绘图,这里还需要一块画布,那我们创建的兼容DC就相当于画板,有了画板、画布,将画布选放在画板兼容DC上就可以进行绘图了。然后一次性贴在设备DC上就搞定了。如下:
HDC mdc=CreateComatibleDC(hdc); // 创建兼容DC 画板
HBITMAP bmp=CreatrCompatibleBitnap(hdc,600,600); // 创建画布
SelectObject(mdc,bmp); // 将画布选入画板
双缓冲绘图步骤:
- 在内存中创建兼容DC缓冲区(依次包括创建兼容DCCreateComatibleDC、创建画布CreatrCompatibleBitnap、将画布选入SelectObject)。
- 在缓冲区进行画图操作(可以画图形、也可以贴位图)。
- 将兼容缓冲区一次性复制到设备DC上。(复制用Bitblt函数)
- 释放内存缓冲区。(DeleteDC函数)
CreateCompatibleDC:
该函数创建一个与指定设备兼容的内存设备上下文环境(DC)
HDC CreateCompatibleDC(HDC hdc);
CreateCompatibleBitmap:
该函数创建与指定的设备环境相关的设备兼容的位图.
HBITMAP CreateCompatibleBitmap(HDC hdc,
int nWidth, // 定位图的宽度,单位为像素
int nHeight);// 指定位图的高度,单位为像素
BitBlt:
BitBlt是一个计算机函数,该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境.
BOOL BitBlt( _In_ HDC hdcDest,
_In_ int nXDest, // 指定目标矩形区域左上角的X轴逻辑坐标
_In_ int nYDest, // 指定目标矩形区域左上角的Y轴逻辑坐标
_In_ int nWidth, // 指定源在目标矩形区域的逻辑宽度
_In_ int nHeight, // 指定源在目标矩形区域的逻辑高度
_In_ HDC hdcSrc, // 指向源设备环境的句柄
_In_ int nXSrc, // 指定源矩形区域左上角的X轴逻辑坐标
_In_ int nYSrc, // 指定源矩形区域左上角的Y轴逻辑坐标
_In_ DWORD dwRop); //指定光栅操作代码。这些代码将定义源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以完成最后的颜色。
单双缓冲技术操作对比:
单缓冲技术绘制两个矩形:
// 直接在设备DC上绘制
Rectangle(hdc, 100, 100, 200, 200);
Rectangle(hdc, 300, 300, 200, 200);
双缓冲技术绘制两个矩形:
// 1.创建兼容缓冲区
mdc = CreateCompatibleDC(hdc); // 创建兼容DC
bmp = CreateCompatibleBitmap(hdc, 600, 600); // 创建兼容位图画布
SelectObject(mdc, bmp); // 选入
// 2.在缓冲区绘制
Rectangle(mdc, 100, 100, 200, 200);
Rectangle(mdc, 300, 300, 200, 200);
// 3.一次性复制到设备DC
BitBlt(hdc, 0, 0, 500, 500, mdc, 0, 0, SRCCOPY);
// 4.释放缓冲区DC
DeleteDC(mdc);
单缓冲绘制位图:
// 1.创建兼容DC
maphdc = CreateCompatibleDC(hdc);
// 2.加载位图
HBITMAP map = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
// 3.选取位图对象,使用BitBlt函数贴图
SelectObject(maphdc, map);
BitBlt(hdc, 0, 0, 1500, 1500, maphdc, 0, 0, SRCCOPY);
// 4.释放兼容DC
DeleteDC(maphdc);
双缓冲绘制位图:
void DrawTest(HDC hdc)
{
// 1.创建兼容缓冲区
HDC mdc = CreateCompatibleDC(hdc); // 创建兼容DC
HBITMAP bmp = CreateCompatibleBitmap(hdc, 1400, 600); // 创建兼容位图画布
SelectObject(mdc, bmp); // 选入
// 2.在缓冲区绘制
HDC maphdc = CreateCompatibleDC(hdc); /*创建兼容DC*/
/*贴第一张位图*/
HBITMAP map1 = (HBITMAP)LoadImage(NULL, _TEXT("H:\\植物大战僵尸素材\\interface\\background1.bmp")
, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
SelectObject(maphdc, map1);
BitBlt(mdc, 0, 0, 1400, 600, maphdc, 0, 0, SRCCOPY);
/*贴第二张位图*/
HBITMAP map2 = (HBITMAP)LoadImage(NULL, _TEXT("H:\\植物大战僵尸素材\\Card\\Plants\\Peashooter.bmp")
, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
SelectObject(maphdc, map2);
BitBlt(mdc, 425, 200, 100, 60, maphdc, 0, 0, SRCCOPY);
DeleteDC(maphdc); /*释放兼容DC*/
// 3.一次性复制到设备DC
BitBlt(hdc, 0, 0, 1400, 600, mdc, 0, 0, SRCCOPY);
// 4.释放缓冲区DC
DeleteDC(mdc);
}
透明位图的显示
TransparentBlt 函数在Windows98/Windows2000以上版本运行,系统中需要包含 Msimg32.dll,使用时可以链接 Msimg32.lib。
BOOL TransparentBlt(
HDC hdcDest, // 目标DC
int nXOriginDest, // 目标X偏移
int nYOriginDest, // 目标Y偏移
int nWidthDest, // 目标宽度
int hHeightDest, // 目标高度
HDC hdcSrc, // 源DC
int nXOriginSrc, // 源X起点
int nYOriginSrc, // 源Y起点
int nWidthSrc, // 源宽度
int nHeightSrc, // 源高度
UINT crTransparent // 透明色,COLORREF类型
);
demo
#pragma comment( lib, "MSIMG32.LIB")
void DrawTest(HDC hdc)
{
// 1.创建兼容缓冲区
HDC mdc = CreateCompatibleDC(hdc); // 创建兼容DC
HBITMAP bmp = CreateCompatibleBitmap(hdc, 1400, 600); // 创建兼容位图画布
SelectObject(mdc, bmp); // 选入
// 2.在缓冲区绘制
HDC maphdc = CreateCompatibleDC(hdc); /*创建兼容DC*/
/*贴第一张位图*/
HBITMAP map1 = (HBITMAP)LoadImage(NULL, _TEXT("H:\\植物大战僵尸素材\\interface\\background1.bmp")
, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
SelectObject(maphdc, map1);
BitBlt(mdc, 0, 0, 1400, 600, maphdc, 0, 0, SRCCOPY);
/*贴第二张位图*/
HBITMAP map2 = (HBITMAP)LoadImage(NULL, _TEXT("H:\\植物大战僵尸素材\\Zombies\\Zombie\\Zombie2.bmp")
, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
SelectObject(maphdc, map2);
TransparentBlt(mdc, 430, 200, 166, 144, maphdc, 0, 0, 166, 144, RGB(255, 255, 255));
DeleteDC(maphdc); /*释放兼容DC*/
// 3.一次性复制到设备DC
BitBlt(hdc, 0, 0, 1400, 600, mdc, 0, 0, SRCCOPY);
// 4.释放缓冲区DC
DeleteDC(mdc);
}