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

专栏导航

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

回到目录

下一篇:无

本专栏课件

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

参考课节: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 章节 :椭圆教学插图绘制程序

回到目录

下一篇:无

相关推荐
是隼人1 小时前
buuctf-pwn PWN4(双引号的转义缺陷)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
码行山野赴时序归途1 小时前
C 语言文件操作完全指南:从打开到关闭
c语言·开发语言
Existence_Time1 小时前
CSP 考前复习
c++
zerwave1 小时前
从零实现简化 DDS 完整技术文档(含模块作用与详细注释)
linux·c++·机器人
Dream Cosmos1 小时前
C++ 多态下篇:虚函数表、动态绑定与多态底层原理
开发语言·c++
CS_Zero12 小时前
C语言sizeof是函数吗?
c语言·开发语言
_Twink1e15 小时前
openJiuwen 实训营 Day 1 · WorkSwarm 入门教程
开发语言·c++·openjiuwen
公子小六15 小时前
基于.NET的Windows窗体编程之WinForms滑块与上下控件
windows·microsoft·c#·.net·winforms
Navigator_Z15 小时前
LeetCode //C - 1224. Maximum Equal Frequency
c语言·算法·leetcode