Win32编程之绘图编程(四)
一、绘图基础
- 绘图设备DC(Device Context),绘图上下文/绘图描述表
- HDC:DC句柄,表示绘图设备
- GDI:Windows graphics device interface(Win32提供的绘图API)
- 颜色的使用:COLORREF:实际DWORD;例如:COLORREF nColor = 0;
- 赋值使用RGB宏:例如:nColor = RGB(0,0, 255)
- 获取RGB值:GetRValue/GetGValue/GetBValue;例如:BYTE nRed = GetRValue(nColor)
计算机使用红、绿、蓝:
R:0~255
G:0~255
B:0~255
每一个颜色是3个字节24位,保存范围:0~2^24-1
二、基本图形绘制
(1).SetPixel设置指定点的颜色
1 2 3 4 5 6 | COLORREF SetPixel( HDC hdc, //DC句柄 int x, //X坐标 int y, //Y坐标 COLORREF crColor //设置的颜色 ); <br>返回指定点原来的颜色 |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | void OnDrawPoint( HDC hdc) { for ( int i = 0; i < 256; i++) { for ( int j = 0; j < 256; j++) { SetPixel(hdc, i, j, RGB(i, j, 0)); } } } void OnPaint( HWND hWnd) { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hWnd, &ps); OnDrawPoint(hdc); EndPaint(hWnd, &ps); } //窗口处理函数(自定义,处理消息) LRESULT CALLBACK WindProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { switch (msgID) { case WM_PAINT: { OnPaint(hWnd); break ; } default : break ; } return DefWindowProc(hWnd, msgID, wParam, lParam); } |
(2).线的使用(直接,弧线)
- MoveToEx:指名窗口当前点
- LineTo:从窗口当前点到指定点绘制一条直线
- 当前点:上一次绘图时最后一点,初始为(0,0)点
示例代码:
1 2 3 4 5 6 | void OnDrawLine( HDC hdc) { //改变窗口当前点坐标 MoveToEx(hdc, 100, 100, NULL); LineTo(hdc, 300, 300); LineTo(hdc, 0, 300); } |
(3).封闭图形:能够用画刷填充的图形(Rectangle/Ellipse)
示例代码:
1 2 3 4 5 6 7 | void OnDrawRect( HDC hdc) { Rectangle(hdc, 100, 100, 300, 300); } void OnDrawEll( HDC hdc) { Ellipse(hdc, 100, 100, 300, 300); } |
三、GDI绘图对象
1.画笔使用流程
(1)、创建画笔
A.画笔的作用:线的颜色、线型、线粗
B.画笔的使用:
1 2 3 4 5 6 | HPEN CreatePen( int fnPenStyle; //画笔的样式 int nWidth; //画笔的粗细 COLORREF crColor //画笔的颜色 ); 创建成功后返回画笔句柄<br>PS_SOILD:实心线,可以支持多个像素宽,其他线型只能是一个像素宽 |
(2).将画笔应用到DC中
1 2 3 4 5 6 | HGDIOBJ SelectObject( HDC hdc; //绘图设备句柄 HGDIOBJ hgdiobj //GDI绘图对象句柄,画笔句柄 ); 返回原来的GDI绘图对象句柄 注意保存原来DC当中的画笔 |
(3).绘图
(4).取出DC中当中的画笔
将原来的画笔,使用SelectObject函数,放入到设备DC中,就会将我们创建的画笔取出
(5).释放画笔
1 2 3 4 | BOOL DeleteObject( HGDIOBJ hObject //GDI绘图对象句柄,画笔句柄 ); 只能删除不被DC使用的画笔,所以在释放前,必须将画笔从DC中取出 |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | void OnDrawEll( HDC hdc) { Ellipse(hdc, 100, 100, 300, 300); } void OnPaint( HWND hWnd) { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hWnd, &ps); HPEN hPen = CreatePen(PS_SOLID, 10, RGB(255, 0, 0)); HGDIOBJ nOldPen = SelectObject(hdc, hPen); OnDrawEll(hdc); //绘制圆形 SelectObject(hdc, nOldPen); DeleteObject(hPen); EndPaint(hWnd, &ps); } //窗口处理函数(自定义,处理消息) LRESULT CALLBACK WindProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { switch (msgID) { case WM_PAINT: { OnPaint(hWnd); break ; } default : break ; } return DefWindowProc(hWnd, msgID, wParam, lParam); } |
2.画刷的使用流程
(1).画刷相关
画刷:封闭图像的填充的颜色、图案;HBRUSH:画刷句柄
(2).画刷的使用
- 创建画刷:CreateSolidBrush:创建实现画刷;CreateHatchBrush:创建纹理画刷
- 将画刷应用到DC中,selectObject
- 绘图
- 将画刷从DC中取出:SelectObject
- 删除画刷:DeleteObject
(3).透明画刷
可以使用GetStockObject函数获取系统维护的画刷、画笔等,如果不使用画刷填充,需要使用NULL_BRUSH参数,获取不填充的画刷,GetStokObject返回的画刷不需要DeleteObject
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | void OnPaint( HWND hWnd) { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hWnd, &ps); HPEN hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0)); HGDIOBJ nOldPen = SelectObject(hdc, hPen); //HBRUSH hBrush = CreateSolidBrush(RGB(0, 255, 0)); //HBRUSH hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 255, 0)); HGDIOBJ hBrush = GetStockObject(NULL_BRUSH); HGDIOBJ nOldBrush = SelectObject(hdc, hBrush); OnDrawEll(hdc); //绘制圆形 SelectObject(hdc, nOldBrush); DeleteObject(hBrush); SelectObject(hdc, nOldPen); //DeleteObject(hPen); EndPaint(hWnd, &ps); } |
四、位图绘制
(1).位图相关
- 光栅图形:激励图像中每一点的颜色信息
- 矢量图形:记录图像算法、绘图指令等
- HBITMAP:位图句柄
(2).位图使用
- 在资源中添加位图资源
- 从资源中加载位图
- 创建一个与当前DC相匹配的DC(内存DC)
1 2 3 4 | HDC CreateCompatibleDC( HDC hdc //当前句柄,可以为NULL(使用屏幕DC) ); 返回创建的DC句柄 |
- 将位图放入匹配的内存DC中,SelectObject
- 成像(1:1)
1 2 3 4 5 6 7 8 9 10 11 | BOOL BitBlt( HDC hdc, //目的DC(窗口DC) int x, //目的的左上X坐标 int y, //目的的左上Y坐标 int cx, //目的宽度 int cy, //目的的高度 HDC hdcSrc, //源DC(内存DC) int x1, //源左上X坐标 int y1, //源左上Y坐标 DWORD rop //成像方法 SRCCOPY ); |
- 取出位图:SelectObject
- 释放位图:DeleteObject
- 释放匹配的DC:DeleteDC
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | void OnDrawBmp( HDC hdc) { //添加位图资源 HBITMAP hBmp = LoadBitmap(g_hIns, ( LPCWSTR )IDB_BITMAP1); //创建一个内存DC,并构建一个虚拟区域,并且内存DC在虚拟区域中绘图 HDC hMemdc = CreateCompatibleDC(hdc); //将位图数据送给内存DC,内存DC在虚拟区域中将位图绘制出来 HGDIOBJ nOldBmp = SelectObject(hMemdc, hBmp); //将虚拟区域中绘制好的图形成像到窗口中 BitBlt(hdc, 100, 100, 48, 48, hMemdc, 0, 0, SRCCOPY); //缩放成像 StretchBlt(hdc, 200, 200, 24, 24, hMemdc, 0, 0, 48, 48, SRCCOPY); SelectObject(hMemdc, nOldBmp); DeleteObject(hBmp); DeleteDC(hMemdc); } void OnPaint( HWND hWnd) { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hWnd, &ps); OnDrawBmp(hdc); EndPaint(hWnd, &ps); } |
五、文本绘制
(1).绘制简单文件
1 2 3 4 5 6 7 8 9 10 | /* TextOut():将文字绘制在指定坐标位置 int DrawText( HDC hDc,//DC句柄 LPCTSTR lpString, //字符串 int nCount, //字符数量 LPRECT lpRect, //绘制文字的矩形框 UINT uFormat //绘制方式 ); */ |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | void onDrawText( HDC hdc) { TCHAR szText[] = TEXT( "Hello Text " ); TextOut(hdc, 100, 100, szText, _tcslen(szText)); RECT rc; rc.left = 100; rc.top = 150; rc.right = 200; rc.bottom = 200; Rectangle(hdc, 100, 150, 200, 200); //DT_VCENTER /DT_BOTTOM只是用于DT_SINGLELINE, 它们和DT_WORDBREAK冲突 DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP); } void OnPaint( HWND hWnd) { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hWnd, &ps); onDrawText(hdc); EndPaint(hWnd, &ps); } |
(2).文件颜色和背景
- 文字颜色:SetTextColor
- 文字背景颜色:SetBkColor
- 文字背景模式:SetBkMode(OPAQUE/TRANSPARENT)
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | void onDrawText( HDC hdc) { TCHAR szText[] = TEXT( "Hello Text " ); TextOut(hdc, 100, 100, szText, _tcslen(szText)); RECT rc; rc.left = 100; rc.top = 150; rc.right = 200; rc.bottom = 200; DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP); } void OnPaint( HWND hWnd) { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hWnd, &ps); SetTextColor(hdc, RGB(255, 0, 0)); SetBkColor(hdc, RGB(0, 255, 0)); //只适用在OPAQUE模式下 SetBkMode(hdc, TRANSPARENT); onDrawText(hdc); EndPaint(hWnd, &ps); } |
3.字体的使用
- 字体相关:Windows常用的字体为TrueType格式的字体文件,字体名:标识字体类型;HFONT:字体句柄
- 应用字体到DC:SelectObject
- 绘制文字:DrawText/TextOut
- 取出字体:SelectObject
- 删除字体:DeleteObject
字体的使用函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | CreateFont( _In_ int cHeight, //字体高度 _In_ int cWidth, //字体宽度 _In_ int cEscapement, //字符串倾斜角度 _In_ int cOrientation, //字符旋转角度 _In_ int cWeight, //字体的粗细 _In_ DWORD bItalic, //斜体 _In_ DWORD bUnderline, //字符下划线 _In_ DWORD bStrikeOut, //删除线 _In_ DWORD iCharSet, //字符集 _In_ DWORD iOutPrecision, //输出精度 _In_ DWORD iClipPrecision, //剪切精度 _In_ DWORD iQuality, //输出质量 _In_ DWORD iPitchAndFamily, //匹配字体 _In_opt_ LPCWSTR pszFaceName //字体名称 ); |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | void onDrawText( HDC hdc) { TCHAR szText[] = TEXT( "Hello Text " ); HFONT hFont = CreateFont(30, 0, 45, 0, 900, 1, 1, 1, GB2312_CHARSET, 0, 0, 0, 0, TEXT( "黑体" )); HGDIOBJ nOldFont = SelectObject(hdc, hFont); TextOut(hdc, 100, 100, szText, _tcslen(szText)); RECT rc; rc.left = 100; rc.top = 150; rc.right = 200; rc.bottom = 200; DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP); SelectObject(hdc, nOldFont); DeleteObject(hFont); } void OnPaint( HWND hWnd) { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hWnd, &ps); SetTextColor(hdc, RGB(255, 0, 0)); SetBkColor(hdc, RGB(0, 255, 0)); //只适用在OPAQUE模式下 SetBkMode(hdc, TRANSPARENT); onDrawText(hdc); EndPaint(hWnd, &ps); } |
分类:
Windows核心编程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?