前言
各位师傅大家好,我是qmx_07,今天给大家讲解GDI图形绘制的相关内容,比如绘制线条,矩形,圆形这些图案绘制
绘图消息(WM_PAINT)
刚创建窗口时,整个窗口显示区域都是无效的,在第一条WM_PAINT消息(通常发生在winMain呼叫UpdateWinodw的时候)指示窗口要绘画内容
BeginPaint-获取窗口客户区的设备上下文
HDC BeginPaint(
HWND hwnd, // 获取窗口句柄
LPPAINTSTRUCT lpPaint // paint information,传出参数,本质是一个结构体指针
);
作用:BeginPaint呼叫令整个显示区域有效,并传回一个「设备内容句柄」
EndPaint——释放设备内容句柄
HDC BeginPaint(
HWND hwnd, // 获取窗口句柄
LPPAINTSTRUCT lpPaint // paint information,传出参数,本质是一个结构体指针
);
作用:EndPaint会释放设备内容句柄,让整个内容显示区域变得无效,避免内存泄露,保证了GDI对象的稳定
注意:BeginPaint 和 EndPaint必须配套使用
客户区和非客户区
客户区:可以显示文字和绘制图形
非客户区:滚动条,菜单栏,状态栏,由windows系统管理
应用程序主要负责客户区的外观和操作
哪些操作会触发WM_PAINT
尺寸被修改:最大化、最小化、还原、修改窗口尺寸大小
从屏幕外移动回屏幕内
图形绘制
绘制线条
创建画笔
函数原型:
CreatePen( _In_ int iStyle //画笔的样式
_In_ int cWidth,//画笔宽度
_In_ COLORREF color);//画笔颜色 一般使用三原色RGB进行调制
查看iStyle的声明,会显示画笔样式
选择画笔
函数原型:
SelectObject(
_In_ HDC hdc,//窗口句柄
_In_ HGDIOBJ h);//要操作的对象
移动画笔
MoveToEx( _In_ HDC hdc,//窗口句柄
_In_ int x,//x轴
_In_ int y,//y轴
_Out_opt_ LPPOINT lppt);//看下面底层原型,其实也是个坐标对象
typedef struct tagPOINT // 坐标对象
{
LONG x;
LONG y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
完成绘制
LineTo( _In_ HDC hdc, _In_ int x, _In_ int y);//Windows api提供的绘制线条接口
代码实例
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
//创建画笔
HPEN hBluePen = CreatePen(PS_SOLID, 5, RGB(0, 0, 255));
//选择画笔
HGDIOBJ hGdiObj = SelectObject(hdc, hBluePen);
//移动画笔到起点
POINT pt = { 0 };
MoveToEx(hdc, 100, 100, &pt);
//绘制线条
LineTo(hdc, 100, 400);
DeleteObject(hBluePen);
EndPaint(hWnd, &ps);
}
通过落笔的位置和最终的位置,两点确定一条线
绘制矩形
我们不需要像上面绘制线条,手动拼接出一个矩形,windows API 给我们提供了一个函数,我们先看一下思路:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
//创建画笔
HPEN hBluePen = CreatePen(PS_SOLID, 5, RGB(0, 0, 255));
//选择画笔
HGDIOBJ hGdiObj = SelectObject(hdc, hBluePen);
//绘制矩形
Rectangle(hdc, 150, 100, 300, 200);//句柄,上下左右
eleteObject(hBluePen);
EndPaint(hWnd, &ps);
}
实心画刷
如果说 我们想要把这个矩形,填充 该怎么办呢?
换一个实心画刷
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
//创建画刷
HBRUSH hSoildBrush = CreateSolidBrush(RGB(0, 0, 255));
//选择画刷
HGDIOBJ hGdiObj = SelectObject(hdc, hSoildBrush);
//绘制矩形
Rectangle(hdc, 150, 100, 300, 200);
DeleteObject(hSoildBrush);
EndPaint(hWnd, &ps);
}
通过改变画笔的形式,就可以操作图案了
阴影画刷
同样的 阴影画刷,也是更改画笔的形式来操作
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
//创建阴影画刷
HBRUSH hHatchBrush = CreateHatchBrush(HS_FDIAGONAL, RGB(0, 0, 255));
//选择阴影画刷
HGDIOBJ hGdiObj = SelectObject(hdc, hHatchBrush);
//绘制矩形
Rectangle(hdc, 150, 100, 300, 200);
DeleteObject(hHatchBrush);
EndPaint(hWnd, &ps);
}
同样的,阴影画刷也可以进行样式选择
打印字体
普通字体
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
SetTextColor(hdc, RGB(255, 0,0 ));//设置字体颜色
TextOut(hdc, 200, 200, L"qmx_07", wcslen(L"qmx_07"));//设置显示字体的位置,以及字符串内容,字符串的长度
EndPaint(hWnd, &ps);
}
上面是显示普通字体,如果我们想要打印更好看的,艺术字体呢?
艺术字体
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
HFONT hFont = CreateFont(100, 25, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, L"宋体");//调用 系统的字体,只需要设置几个内容,高度,宽度,以及编码格式,调用的字体,其他都选0
SelectObject(hdc, hFont);
SetTextColor(hdc, RGB(255, 0, 0));
RECT rect;
SetRect(&rect, 100, 100, 100, 100);//调整字体位置
DrawText(hdc, L"这是一个例子", -1, &rect, DT_NOCLIP);//艺术字输出,最后一个的意思是 输出的方式,显示不裁剪
DeleteObject(hFont);
EndPaint(hWnd, &ps);
}
通过调用操作系统的字体,RECT进行调整位置,输出更好看的字体
画圆形
画曲线
曲线是根据多个点位置,来确定图形的
代码实例:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
POINT pi[4] = {
10,120,
180,300
,300,180
,120,10
};//四个点的位置
PolyBezier(hdc, pi, 4);//画曲线
EndPaint(hWnd, &ps);
}
画圆形
圆形也是根据矩形的两个点,来拼凑成圆形
代码实例:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
Arc(hdc, 100, 200, 200, 100, 350,
350, 350, 350);//通过两点,然后拼接全圆
EndPaint(hWnd, &ps);
}
break;
总结
今天学习了WM_PAINT的机制,以及绘制图形的知识,下一章节讲解 鼠标键盘消息