news 2026/9/7 21:11:07

第5章,[Win32 章节] :圆角矩形教学插图绘制程序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第5章,[Win32 章节] :圆角矩形教学插图绘制程序

专栏导航

上一篇:第5章,[Win32 章节] :椭圆教学插图绘制程序

回到目录

下一篇:第5章,[Win32 章节] :Arc、Chord 和 Pie 教学插图

本专栏课件

关于本专栏课件的获取方法,请参考下述课节。

参考课节:MFC笔记:本专栏课件

本节前言

对于本节所讲解的知识,有可能,你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点,请你自行查阅。

我呢,也会提到一部分的参考课节。但是呢,你不应该依赖于我的主动提及。最好呢,你自己能够多去了解和查看本专栏目录。

本节,我们继续来做小的练习题。

本节的代码依然不难。

不过呢,鉴于本节的程序有点长,所以呢,我会将代码放进 Gitee 课件代码仓库里面的。

一. 插图介绍

之前的有一个课节,里面用到了如下的插图。

图1

这个插图出现在下述课节中。

参考课节:第5章,[Win32 章节] :边框绘制函数(五)

这个插图呢,它主要的部分,是一个圆角矩形。

不过呢,它还有两个辅助部分,一个辅助部分,就是圆角矩形所在的矩形。圆角矩形,我们用实线、蓝色线条风格的画笔来绘制。

这个矩形,我们在绘制的时候,我要用虚线来绘制。那就是需要用自定义画笔,并且将这个画笔设置为 PS_DASH 风格。颜色的话,不一定要与图1 一致,你可以自己选定一个颜色。我设定的颜色是 RGB(255, 0, 255) 。

第二个辅助部分,就是四个圆角所在的椭圆了。它们呢,需要用虚线来绘制。我在自己的程序里,我是创建了一个自定义画笔,并将画笔设置为 PS_DASH、红色线条风格。

那么,在具体绘制的时候,我呢,首先是绘制矩形,然后是绘制四个辅助椭圆,最后是绘制圆角矩形。

有一个问题,如果你直接这么按次序来绘制的话,那么,在程序绘制完圆角矩形的时候,内部的四个小椭圆就会消失了。那是因为,默认地,我们会用白色画刷来填充圆角矩形的内部。就在这个填充的过程中,之前绘制的四个小椭圆,它的大部分的线条,就被白色画刷给涂抹掉了。

为了避免默认的白色画刷将四个小椭圆给涂抹掉,我们呢,需要在绘制圆角矩形之前,给设备环境选入一个 NULL_BRUSH 画刷。有了这个 NULL_BRUSH 画刷,Windows 就不会用某个画刷来填充圆角矩形的内部,而是直接沿用原来的背景颜色。

基本的绘制思路,我们就讲解完了。

接下来,我们在下一节,来展示程序代码。

二. 本节程序

代码如下。

/*------------------------------------------------------------ RoundRect 函数讲解插图 水饺编程,2026 ------------------------------------------------------------*/ #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("RoundRect_Teach"); 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("注册窗口类失败!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("RoundRect 绘图讲解图示"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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; PAINTSTRUCT ps; RECT rect; static int xLeft, xRight, yTop, yBottom; static int xCornerEllipse, yCornerEllipse; COLORREF color; HPEN hPen, hOldPen; HBRUSH hBrush, hOldBrush; switch (message) { case WM_CREATE: xLeft = 100; xRight = 600; yTop = 100; yBottom = 500; xCornerEllipse = 160; yCornerEllipse = 120; return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); color = RGB(255, 0, 255); hPen = CreatePen(PS_DASH, 0, color); hOldPen = (HPEN)SelectObject(hdc, hPen); Rectangle(hdc, xLeft, yTop, xRight, yBottom); SelectObject(hdc, hOldPen); DeleteObject(hPen); color = RGB(255, 0, 0); hPen = CreatePen(PS_DASH, 0, color); hOldPen = (HPEN)SelectObject(hdc, hPen); Ellipse(hdc, xLeft, yTop, xLeft + xCornerEllipse, yTop + yCornerEllipse); Ellipse(hdc, xRight - xCornerEllipse, yTop, xRight, yTop + yCornerEllipse); Ellipse(hdc, xLeft, yBottom - yCornerEllipse, xLeft + xCornerEllipse, yBottom); Ellipse(hdc, xRight - xCornerEllipse, yBottom - yCornerEllipse, xRight, yBottom); SelectObject(hdc, hOldPen); DeleteObject(hPen); hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); color = RGB(0, 0, 255); hPen = CreatePen(PS_SOLID, 0, color); hOldPen = (HPEN)SelectObject(hdc, hPen); RoundRect(hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse); SelectObject(hdc, hOldPen); DeleteObject(hPen); SelectObject(hdc, hOldBrush); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }

代码本身不难,不过呢,我还是得提醒两句。

第一点,对于 static ,有它在,我们才可以在 WM_CREATE 消息中初始化一些个变量,而在 WM_PAINT 消息中使用 WM_CREATE 消息中的初始化值。

不同的消息,是处在不同的窗口过程函数 WinProc 的调用之中的。要想在不同的 WinProc 函数的调用中使用同一个变量的值,则需要将相关变量设置为 static 属性。

第二点,在本程序中,画刷我们使用了一次,并且使用的是备用画刷 NULL_BRUSH 。备用画刷也好,备用画笔也好,用完了,需要将其选出设备环境,但是不能删除它。而对于自定义画笔和自定义画刷,则需要在用完以后,选出设备环境,然后再删除它。

三. 程序编译与运行

我将解决方案和项目名称,设为 RoundRect_Teach 。源文件的名称,我将其设置为 WinMain.cpp 。

关于如何编译和运行程序,请参考下述课节。

参考课节:使用 VS2010 编写 C语言程序

参考课节:用 VS2019 编写C语言程序

程序的运行结果如下。

图2

可以看到,图2 与图1 并不完全一致。区别主要在于画笔的颜色。

结束语

程序不难。

本节,依然是以让大家熟悉 GDI 对象的使用流程为目的。

同时呢,大家也可以有一种经验,对于某些个,你用 PhotoShop 和 Visio 软件不容易绘制的图,或许,你可以考虑用编程的方式来绘制它。

程序员可以用编程的方式来绘图,也可以学习 PhotoShop 来绘图。

编程有编程的方便。

专栏导航

上一篇:第5章,[Win32 章节] :椭圆教学插图绘制程序

回到目录

下一篇:第5章,[Win32 章节] :Arc、Chord 和 Pie 教学插图

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 21:07:52

高校AI应用落地实践:基于低代码平台的架构设计与经验复盘

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 21:07:03

LangChain与LangGraph实战:从入门到企业级Agent开发全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 21:05:33

SOP与储能协同优化配电网电压无功控制

1. 项目概述 在新能源占比逐渐提高的现代电网中&#xff0c;配电网的电压和无功功率控制面临前所未有的挑战。传统配电网的刚性结构难以应对分布式电源&#xff08;如光伏、风电&#xff09;的间歇性和波动性&#xff0c;而柔性开断点&#xff08;Soft Open Point, SOP&#xf…

作者头像 李华
网站建设 2026/9/7 21:05:29

Navicat 15安装破解风险解析与合法替代方案指南

1. 为什么Navicat 15的"安装破解"是最不值得碰的搜索词先说实话&#xff1a;Navicat 15确实是一款好用的数据库管理工具&#xff0c;尤其是对于同时要管MySQL、PostgreSQL、SQL Server、Oracle、SQLite的开发者来说&#xff0c;一个客户端能统一搞定所有连接、备份、…

作者头像 李华
网站建设 2026/9/7 21:03:25

从零搭建Web简易ERP进销存系统:核心规划与技术选型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华