MFC开发:图形的绘制

文章目录

    • 一、获取指定窗口的设备上下文
    • 二、画笔的介绍和使用
    • 三、绘制直线
    • 四、画刷的介绍和使用
    • 五、绘制扇形
    • 六、绘制圆形
    • 七、绘制文本

一、获取指定窗口的设备上下文

1.GetDC()函数的作用
GetDC() 是 Windows API 中的一个函数,它用于获取指定窗口的设备上下文(Device Context,简称 DC)。设备上下文是 GDI(图形设备接口)用于绘图的关键对象,它封装了与设备(如屏幕或打印机)相关的绘图信息。

函数原型:

HDC GetDC(HWND hWnd);

参数:

  • hWnd:指定窗口的句柄。如果 hWnd 为 NULL,则返回整个屏幕的设备上下文(相当于桌面)。否则,返回指定窗口的设备上下文。

返回值:

  • 成功:返回指定窗口的设备上下文句柄(HDC)。
  • 否则,返回指定窗口的设备上下文。

用法:
GetDC() 主要用于获取窗口的 DC,以便进行绘图操作。一般用于:

  • 在窗口客户区绘图(不包括标题栏、菜单栏等)。
  • 获取屏幕 DC 进行全屏截图等操作。

2.获取屏幕DC进行截图
在窗口客户区绘图:

#include <windows.h>LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {switch (message) {case WM_PAINT: {PAINTSTRUCT ps;HDC hdc = BeginPaint(hWnd, &ps); // 获取DCTextOut(hdc, 50, 50, L"Hello, Windows!", 15); // 绘制文本EndPaint(hWnd, &ps); // 释放DCbreak;}case WM_LBUTTONDOWN: {HDC hdc = GetDC(hWnd); // 获取窗口DCTextOut(hdc, 100, 100, L"Mouse Click!", 12); // 绘制文本ReleaseDC(hWnd, hdc); // 释放DCbreak;}case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}

说明:

  • GetDC(hWnd) 直接获取窗口的 DC,不用 BeginPaint(),适用于即时绘图(如鼠标点击)。
  • 用完 DC 后,必须调用 ReleaseDC(hWnd, hdc); 释放它,否则会导致资源泄露。

获取屏幕 DC 进行截图:

HDC hScreenDC = GetDC(NULL); // 获取整个屏幕的DC
HDC hMemDC = CreateCompatibleDC(hScreenDC);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, 1920, 1080);
SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, 1920, 1080, hScreenDC, 0, 0, SRCCOPY);
ReleaseDC(NULL, hScreenDC);
DeleteDC(hMemDC);

说明:

  • GetDC(NULL) 获取整个屏幕的 DC。
  • BitBlt() 将屏幕内容拷贝到 hMemDC 进行截图。
  • 使用完 DC 后,需要调用 ReleaseDC() 释放它。

注意事项:

  • GetDC() 只适用于客户区绘图,如果要绘制整个窗口(包括非客户区,如标题栏),请用 GetWindowDC()。
  • 必须调用 ReleaseDC() 释放 DC,GetDC() 分配的 DC 需要 ReleaseDC() 释放,否则会导致资源泄露。
  • 与 BeginPaint() 的区别:GetDC() 适用于即时绘图,适合响应鼠标事件等。BeginPaint() 仅在 WM_PAINT 处理时使用,并会自动更新无效区域,适用于窗口重绘。

二、画笔的介绍和使用

CPen 是 MFC(Microsoft Foundation Class) 提供的一个 GDI(图形设备接口)对象,用于在 Windows 应用程序中创建和管理画笔(Pen)。画笔用于绘制直线、边框、曲线 等图形元素。

1. CPen 类的基本介绍
CPen 继承自 CGdiObject,用于定义画笔的颜色、线条样式和宽度,并可以与 CDC(设备上下文)一起使用进行绘图。

2. CPen 的构造函数

CPen(int nPenStyle, int nWidth, COLORREF crColor);

参数说明:

  • nPenStyle:线条样式,如 实线、虚线、点线 等(见下表)。
  • nWidth:线条宽度(像素)。
  • crColor:颜色,使用 RGB(r, g, b) 指定。

3. 线条样式 (nPenStyle)
在这里插入图片描述
4. CPen 的使用
(1)创建和使用画笔

void CMyView::OnDraw(CDC* pDC) {// 创建一个红色、2 像素宽的实线画笔CPen pen(PS_SOLID, 2, RGB(255, 0, 0));// 选择画笔,并保存旧画笔CPen* pOldPen = pDC->SelectObject(&pen);// 画一条直线pDC->MoveTo(50, 50);pDC->LineTo(200, 200);// 恢复旧画笔pDC->SelectObject(pOldPen);
}

说明:

  • SelectObject(&pen) 选择新画笔,并返回旧画笔指针(必须恢复)。
  • MoveTo(x, y) 移动到起点。
  • LineTo(x, y) 画一条直线。

(2)使用 CPen 变量

void CMyView::OnDraw(CDC* pDC) {CPen bluePen(PS_DOT, 3, RGB(0, 0, 255));  // 蓝色点线,3px 宽CPen* pOldPen = pDC->SelectObject(&bluePen);pDC->Ellipse(50, 50, 200, 200);  // 画一个椭圆pDC->SelectObject(pOldPen);  // 恢复原画笔
}

(3)使用 CreatePen()

void CMyView::OnDraw(CDC* pDC) {CPen pen;pen.CreatePen(PS_DASHDOT, 5, RGB(0, 255, 0)); // 绿色虚点线,5px 宽CPen* pOldPen = pDC->SelectObject(&pen);pDC->Rectangle(100, 100, 300, 300); // 画一个矩形pDC->SelectObject(pOldPen);
}

(4)创建 LOGBRUSH 自定义画笔

void CMyView::OnDraw(CDC* pDC) {LOGBRUSH lb;lb.lbStyle = BS_SOLID;  // 纯色填充lb.lbColor = RGB(255, 165, 0); // 橙色lb.lbHatch = 0;  CPen pen;pen.CreatePen(PS_SOLID | PS_ENDCAP_ROUND, 10, &lb); // 圆头 10px 画笔CPen* pOldPen = pDC->SelectObject(&pen);pDC->MoveTo(50, 50);pDC->LineTo(300, 50);pDC->SelectObject(pOldPen);
}

5. CPen 使用注意事项

  • 必须恢复旧画笔:SelectObject() 之前存储旧画笔,绘制完毕后恢复它,避免影响后续绘图。
  • 不要在 OnPaint() 中创建临时 CPen 对象:CPen 对象应在 OnDraw() 或 OnPaint() 内部创建并销毁,避免资源泄漏。
  • CPen 对象生存期要合理:如果是临时画笔,直接在 OnDraw() 里使用,不要 new 分配。若 CPen 需要在多个函数中使用,应定义为 成员变量,避免频繁创建销毁。

三、绘制直线

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 画线// 获得设备上下文CDC* pDC = GetDC();// 画笔移动到起始点pDC->MoveTo(m_pOrigin);// 从起点到终点画一条直线pDC->LineTo(point);// 释放设备上下文ReleaseDC(pDC);CWnd::OnLButtonUp(nFlags, point);
}

结果展示:
在这里插入图片描述

四、画刷的介绍和使用

CBrush 是 MFC(Microsoft Foundation Classes)提供的 GDI(图形设备接口) 对象之一,用于创建和管理 画刷(Brush)。画刷主要用于填充图形的 内部区域,例如填充矩形、椭圆、圆形、区域等。

1. CBrush 类的基本介绍
CBrush 继承自 CGdiObject,用于定义画刷的 颜色、填充模式和样式,并可与 CDC(设备上下文)一起使用进行绘图。

2. CBrush 的构造函数

CBrush(COLORREF crColor);
CBrush(int nIndex, COLORREF crColor);
CBrush(int nStyle, COLORREF crColor);
CBrush(int nStyle, CBitmap* pBitmap);

参数说明:

  • crColor:画刷的颜色(使用 RGB(r, g, b) 指定)。
  • nIndex:系统颜色索引(如 COLOR_WINDOW)。
  • nStyle:画刷样式(如 HS_DIAGCROSS、HS_HORIZONTAL)。
  • pBitmap:用于创建 位图画刷 的 CBitmap 指针。

3. CBrush 画刷样式
在这里插入图片描述
4. CBrush 的使用
(1)创建纯色画刷

void CMyView::OnDraw(CDC* pDC) {CBrush brush(RGB(255, 0, 0)); // 创建红色画刷CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(50, 50, 200, 200); // 画填充矩形pDC->SelectObject(pOldBrush); // 恢复旧画刷
}

说明:

  • SelectObject(&brush) 选择画刷,并返回原来的画刷(后续需要恢复)。
  • Rectangle(x1, y1, x2, y2) 使用画刷填充矩形。

(2)创建带有样式的画刷

void CMyView::OnDraw(CDC* pDC) {CBrush brush(HS_CROSS, RGB(0, 255, 0)); // 绿色十字交叉填充CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Ellipse(50, 50, 200, 200); // 画填充椭圆pDC->SelectObject(pOldBrush);
}

常见 HS_ 样式:
在这里插入图片描述
(3)创建 CreateSolidBrush()

void CMyView::OnDraw(CDC* pDC) {CBrush brush;brush.CreateSolidBrush(RGB(0, 0, 255)); // 创建蓝色画刷CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(100, 100, 300, 300); // 填充矩形pDC->SelectObject(pOldBrush);
}

说明:

  • CreateSolidBrush(RGB(0,0,255)) 以指定颜色创建画刷。
  • 适用于动态创建 画刷的情况。

(4)创建位图填充画刷

void CMyView::OnDraw(CDC* pDC) {CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP1); // 加载资源中的位图CBrush brush;brush.CreatePatternBrush(&bitmap); // 创建位图画刷CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(50, 50, 250, 250); // 用位图填充矩形pDC->SelectObject(pOldBrush);
}

说明:

  • CreatePatternBrush(&bitmap) 使用位图创建画刷,适用于 纹理填充。
  • LoadBitmap(IDB_BITMAP1) 加载 资源位图,IDB_BITMAP1 需要在 资源管理器 中定义。

(5)结合 CPen 和 CBrush 使用

void CMyView::OnDraw(CDC* pDC) {CPen pen(PS_SOLID, 2, RGB(0, 0, 255));  // 蓝色边框CBrush brush(RGB(255, 255, 0));         // 黄色填充CPen* pOldPen = pDC->SelectObject(&pen);CBrush* pOldBrush = pDC->SelectObject(&brush);pDC->Rectangle(50, 50, 200, 200); // 画填充的矩形pDC->SelectObject(pOldPen);pDC->SelectObject(pOldBrush);
}

说明:

  • CPen 负责边框颜色,CBrush 负责填充颜色。
  • Rectangle(x1, y1, x2, y2) 画出填充的矩形。

5. CBrush 使用注意事项

  • 必须恢复旧画刷:SelectObject() 返回旧画刷,需要在绘制完成后恢复它,避免影响后续绘图。
  • 不要在 OnPaint() 中创建临时 CBrush:CBrush 应该在 OnDraw() 或 OnPaint() 内部创建并销毁,以避免资源泄露。
  • 使用 CreateSolidBrush() 动态创建画刷:如果 CBrush 需要在多个函数中使用,推荐 使用成员变量 避免重复创建。

五、绘制扇形

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;m_bDraw = true;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{m_bDraw = false;CWnd::OnLButtonUp(nFlags, point);
}void CChildView::OnMouseMove(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (m_bDraw) {CClientDC dc(this);dc.MoveTo(m_pOrigin);dc.LineTo(point);m_pOrigin = point;}CWnd::OnMouseMove(nFlags, point);
}

在这里插入图片描述

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;m_bDraw = true;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{m_bDraw = false;CWnd::OnLButtonUp(nFlags, point);
}void CChildView::OnMouseMove(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (m_bDraw) {CClientDC dc(this);CPen pen(PS_SOLID, 1, RGB(0, 255, 255));CPen* pOldPen = dc.SelectObject(&pen);dc.MoveTo(m_pOrigin);dc.LineTo(point);dc.SelectObject(pOldPen);}CWnd::OnMouseMove(nFlags, point);
}

在这里插入图片描述

六、绘制圆形

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值// 保存起点位置到成员变量中m_pOrigin = point;m_bDraw = true;CWnd::OnLButtonDown(nFlags, point);
}void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{m_bDraw = false;CClientDC dc(this);CPen pen(PS_DASH, 1, RGB(0, 0, 255));CPen* pOldpen = dc.SelectObject(&pen);// 画椭圆//dc.Ellipse(CRect(m_pOrigin, point));// 计算两点之间x坐标的差值long len = point.x - m_pOrigin.x;dc.Ellipse(m_pOrigin.x, m_pOrigin.y, m_pOrigin.x + len, m_pOrigin.y + len);dc.SelectObject(pOldpen);CWnd::OnLButtonUp(nFlags, point);
}

在这里插入图片描述

七、绘制文本

void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{CString str(_T("你好我好大家好!"));CClientDC dc(this);CFont font;// 设置字体font.CreatePointFont(200, _T("宋体"));CFont* pOldFont = dc.SelectObject(&font);// 设置文字颜色dc.SetTextColor(RGB(125, 0, 127));// 输出字符串dc.TextOutW(point.x, point.y, str);dc.SelectObject(pOldFont);CWnd::OnLButtonUp(nFlags, point);
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/35701.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SPI 总线协议

1、协议介绍 SPI&#xff0c;是英语 Serial Peripheral interface 的缩写&#xff0c;顾名思义就是串行外围设备接口。是 Motorola 首先在其 MC68HCXX 系列处理器上定义的。 SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线。主节点或子节点的数据在…

Qt msvc程序运行

第一个Qt msvc程序 我们一般用qt msvc来编译程序&#xff0c;就是用webview。 第一个Qt msvc webview程序实现如下&#xff1a; 运行结果&#xff1a; 标注&#xff1a; QT版本大于6.0的时候才能用<Webview>模块。 QT版本在大于5.2版本&#xff0c;引入了Webengine模…

Java设计模式建模语言面向对象设计原则

设计模式 设计模式的概念 设计模式最初用于建筑领域的设计中。 软件的设计模式&#xff0c;又称设计模式&#xff0c;是一套被反复使用&#xff0c;多数人知道的&#xff0c;经过分类编目的&#xff0c;代码设计经验的总结。 它描述了在软件设计过程中的一些不断重复发生的…

搜广推校招面经五十四

美团推荐算法 一、手撕Transformer的位置编码 1.1. 位置编码的作用 Transformer 模型没有显式的序列信息&#xff08;如 RNN 的循环结构&#xff09;&#xff0c;因此需要通过位置编码&#xff08;Positional Encoding&#xff09;为输入序列中的每个位置添加位置信息。位置…

深入解析 SQL 事务:确保数据一致性的关键

SQL 事务 什么是 SQL 事务&#xff1f;事务的 ACID 特性原子性&#xff08;Atomicity&#xff09;:示例&#xff1a; 一致性&#xff08;Consistency&#xff09;:示例&#xff1a; 隔离性&#xff08;Isolation&#xff09;:持久性&#xff08;Durability&#xff09;:示例&am…

【软考-架构】11.3、设计模式-新

✨资料&文章更新✨ GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目录 项目中的应用设计模式创建型设计模式结构型设计模式行为型设计模式 &#x1f4af;考试真题题外话 项目中的应用 在实际项目中&#xff0c;我应用过多种设计模式来解决不同…

观察者模式详解:用 Qt 信号与槽机制深入理解

引言 你是否曾遇到这样的需求&#xff1a;一个对象的状态发生变化后&#xff0c;希望通知其他对象进行相应的更新&#xff1f;比如&#xff1a; 新闻订阅系统&#xff1a;当新闻发布后&#xff0c;所有订阅者都会收到通知。股票行情推送&#xff1a;股价变化时&#xff0c;所…

流量分析实践

下载附件使用wireshark打开&#xff0c;发现数据包非常多&#xff0c;一共有1万多条数据&#xff0c;我们点击分析来看一下协议分级 然后我们再来看一下会话&#xff0c;看有哪些ip地址&#xff0c; 我们通过会话结合大部分的流量发现&#xff0c;172.17.0.1一直在请求172.17.0…

新手村:混淆矩阵

新手村&#xff1a;混淆矩阵 一、前置条件 知识点要求学习资源分类模型基础理解分类任务&#xff08;如二分类、多分类&#xff09;和常见分类算法&#xff08;如逻辑回归、决策树&#xff09;。《Hands-On Machine Learning with Scikit-Learn》Python基础熟悉变量、循环、函…

MYSQL库的操作

目录 一、创建数据库 二、字符集和校验规则 1、查看系统默认字符集以及校验规则 2、查看系统支持的所有字符集以及字符集校验规则 3、指定字符集以及校验规则来创建数据库 4、校验规则对数据库的影响 三、操纵数据库 1、查看数据库 2、修改数据库 3、删除数据库 4、数…

Next App Router(下)

五、loading 新增 app/loading.tsx 页面 const Loading () > {return <div>Loading...</div>; }; export default Loading;修改 app/page.tsx页面 /** 假设为一个获取数字的api */ const fetch_getNumber async (): Promise<number> > {return ne…

【JAVA】】深入浅出了解cookie、session、jwt

文章目录 前言一、首先了解http的cookie是什么&#xff1f;Cookie 属性及其含义1. NameValue2. Expires3. Max-Age4. Domain5. Path6. Secure7. HttpOnly8. SameSite示例 Cookie 分类1. Session Cookies2. Persistent Cookies3. First-Party Cookies4. Third-Party Cookies 二、…

【css酷炫效果】纯CSS实现粒子旋转动画

【css酷炫效果】纯CSS实现粒子旋转动画 缘创作背景html结构css样式完整代码效果图 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;https://download.csdn.net/download/u011561335/90492008 缘 创作随缘&#xff0c;不定时更新。 创作背景 刚看到csdn出活动了&…

C++Lambda表达式

Lambda表达式 什么是Lambda表达式 ​ C11的颁布让C丰富了起来&#xff0c;任何一本介绍C11的书籍&#xff0c;都不可能跳过这一个点——Lambda表达式。人们经常称Lambda表达式是一个语法糖&#xff0c;说明这是一个”没有没事&#xff0c;有了更好“的一种语法表达&#xff0…

每天五分钟深度学习框架pytorch:基于pytorch搭建循环神经网络RNN

本文重点 我们前面介绍了循环神经网络RNN,主要分析了它的维度信息,其实它的维度信息是最重要的,一旦我们把维度弄清楚了,一起就很简单了,本文我们正式的来学习一下,如何使用pytorch搭建循环神经网络RNN。 RNN的搭建 在pytorch中我们使用nn.RNN()就可以创建出RNN神经网络…

el-table树形表格合并相同的值

el-table树形表格合并相同的值 el-table树形表格合并相同的值让Ai进行优化后的代码 el-table树形表格合并相同的值 <style lang"scss" scoped> .tableBox {/deep/ &.el-table th:first-child,/deep/ &.el-table td:first-child {padding-left: 0;} } …

2025年3月19日 十二生肖 今日运势

小运播报&#xff1a;2025年3月19日&#xff0c;星期三&#xff0c;农历二月二十 &#xff08;乙巳年己卯月丁亥日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;兔、虎、羊 需要注意&#xff1a;猪、猴、蛇 喜神方位&#xff1a;正南方 财神方位&#xff1a;…

Git——分布式版本控制工具使用教程

本文主要介绍两种版本控制工具——SVN和Git的概念&#xff0c;接着会讲到Git的安装&#xff0c;Git常用的命令&#xff0c;以及怎么在Vscode中使用Git。帮助新手小白快速上手Git。 1. SVN和Git介绍 1.1 SVN 集中式版本控制工具&#xff0c;版本库是集中存放在中央服务器的&am…

QT5.15.2加载pdf为QGraphicsScene的背景

5.15.2使用pdf 必须要安装QT源码&#xff0c;可以看到编译器lib目录已经有pdf相关的lib文件&#xff0c;d是debug 1.找到源码目录&#xff1a;D:\soft\QT\5.15.2\Src\qtwebengine\include 复制这两个文件夹到编译器的包含目录中:D:\soft\QT\5.15.2\msvc2019_64\include 2.找…

【H2O2 | 软件开发】前端深拷贝的实现

目录 前言 开篇语 准备工作 正文 概述 JSON方法 递归 其他 结束语 前言 开篇语 本系列为短篇&#xff0c;每次讲述少量知识点&#xff0c;无需一次性灌输太多的新知识点。该主题文章主要是围绕前端、全栈开发相关面试常见问题撰写的&#xff0c;希望对诸位有所帮助。…