《Windows API每日一练》4.4 绘制填充区域

本节讲述如何填充由线条构建的封闭区域。当我们初始化一个窗口类时,往往已经指定了窗口的背景色画刷(WHITE_BRUSH),即默认的填充封闭区域背景的画刷。如果我们想更换背景颜色,需要选入其他系统预定义的画刷(BLACK_BRUSH、GRAY_BRUSH、NULL_BRUSH)。我们也可以选择创建并选入自定义的画刷。此外,我们还需要关注与填充背景相关的背景模式(透明模式和非透明模式)、填充模式(ALTERNATE模式和WINDING模式)和绘图模式。

本节必须掌握的知识点:

        多边形填充模式

        第26练:绘制填充区域

        画刷

4.4.1 多边形填充模式

Windows使用当前被选入设备环境的画笔来绘制图形的边框线。边框线使用当前的背 景模式、背景颜色和绘图模式,这与Windows绘制线条一样。我们所学的关于线条的所有 知识都适用于这些图形的边框线。下表列出了 Windows用于绘制带有边框的填充区域的7个函数。

函数名称

图形

Rectangle

直角矩形

Ellipse

椭圆

RoundRect

圆角矩形

Chord

弓形,由椭圆圆周上的弧和一根弦组成

Pie

椭圆上的一个扇形

Polygon

多边形

PolyPolygon

多个多边形

表4-2 带有边框的填充区域函数

Windows使用当前选入设备环境的画刷来填充图形。在默认情况下,使用的是备用对象WHITE_BRUSH,这就意味着使用白色来绘制图形内部。

Windows定义了 6种备用画刷: WHITE_BRUSH、LTGRAY_BRUSH、GRAY_BRUSH、DKGRAY_BRUSH、BLACK_BRUSH 和NULL_BRUSH(又称为HOLLOW_BRUSH)。和选择备用画笔一样,可以将任何一种备用画刷选入设备环境。Windows定义画刷的句柄为HBRUSH类型,所以要先定义一个画 刷句柄变量:

HBRUSH hBrush;

获取GRAY_BRUSH句柄可以通过调用如下的GetStockObject函数实现:

hBrush = GetStockObject (GRAY_BRUSH);

然后通过调用SelectObject函数将它选进设备环境:

SelectObject (hdc, hBrush);

现在,当绘制上表中的任意图形时,内部都会变成灰色。

如果要绘制一个不含边框线的图形,则要把NULL_PEN画笔选入设备环境:

SelectObject (hdc, GetStockObject (NULL_PEN));

如果只想绘制图形的边框线,而不想填充图形的内部,可以将NULL_BRUSH选入设备环境:

SelectObject (hdc, GetStockobject (NULL_BRUSH);

也可以建立自定义的画刷,就像建立自定义的画笔一样。我们将在下一小节中介绍。

Polygon函数和多边形填充模式

Polygon函数用于绘制一个多边形形状。以下是Polygon函数的常见原型:

BOOL Polygon(

    HDC hdc,             // 设备上下文句柄

    const POINT* points,   // 多边形的顶点数组指针

    int count            // 顶点的数量

);

Polygon函数用于在设备上下文中绘制一个多边形形状。多边形由一系列顶点构成,通过指定顶点的坐标数组来定义。多边形的绘制遵循顺时针顺序连接顶点的规则。

举例

以下是一个示例代码,演示如何使用Polygon函数绘制一个三角形:

HDC hdc = GetDC(hwnd);  // 获取窗口的设备上下文

POINT points[3];  // 三角形的顶点数组

points[0].x = 100; points[0].y = 100;  // 第一个顶点

points[1].x = 200; points[1].y = 200;  // 第二个顶点

points[2].x = 300; points[2].y = 100;  // 第三个顶点

Polygon(hdc, points, 3);  // 绘制三角形

ReleaseDC(hwnd, hdc);  // 释放设备上下文

上述代码中,我们创建了一个包含三个顶点的POINT数组,并将顶点的坐标赋值。然后调用Polygon函数传递顶点数组和顶点数量来绘制三角形。

需要注意的是,绘制的多边形将使用当前设备上下文的绘图属性,如线条颜色、填充模式等。

PolyPolygon函数的调用形式如下:

PolyPolygon (hdc, apt, aiCounCs, iPolyCounC);

这个函数会绘制多个多边形。最后一个参数是绘制的多边形的个数。对每个多边形,数组 aiCounts给出了多边形顶点的个数。数组apt含有全部多边形的所有顶点。除了返回值外, PolyPolygon在功能上等同于下面的代码:

for (i = 0, iAccum = 0 ; i < iPolyCount ; i++)

{

       Polygon (hdc, apt + iAccum, aiCounts[i]) ;

       iAccum += aiCounts[i] ;

}

对Polygon和PolyPolygon函数,Windows都使用设备环境中的当前画刷来填充区域。 至于内部是如何填充的,要取决于多边形的填充模式,可以调用SetPolyFillMode函数来设置:

SetPolyFillMode (hdc, iMode);

在默认情况下,多边形的填充模式是ALTERNATE(交替)但是也可以将它设定为 WINDING(螺旋)。这两种方式的区别如图4-6所示。

●ALTERNATE和WINDING模式的区别

“ALTERNATE” 和 “WINDING”是用来处理复杂路径(即,路径中有交叉或重叠部分)的填充规则,本质上是决定哪些区域是需要被填充,哪些区域是应该被排除的。

1.ALTERNATE:也称为奇偶规则。该规则通过画直线从需要考虑填充的区域到区域外部,如果这个线穿过路径的交叉点次数是奇数,则算作在路径内部,该区域会被填充,如果是偶数,则不会被填充。

2.WINDING:也称为非零环绕数规则。按照这个规则,所有的路径都是有方向的。从一个区域向外画射线,路径从左到右穿过射线会加一,从右到左穿过射线会减一,如果最终的结果是非零,那么这个区域视为在路径内部,会被填充。如果结果是零,那么这个区域不会被填充。

图4-6用两种多边形填充模式绘制的图:ALTERNATE(左)和WINDING(右)

4.4.2 第26练:绘制填充区域

/*------------------------------------------------------------------

026  WIN32 API 每日一练

     第26个例子ALTWIND.C:绘制填充区域

     SetPolyFillMode函数

     Polygon函数

(c) www.bcdaren.com, 2020

----------------------------------------------------------------*/

#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 ("AltWind.C") ;

    (略)

     return msg.wParam ;

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

     static POINT apt[10];

     //多边形顶点坐标数组

     static POINT aptFigure[10] = { {10,70}, 50,70, 50,10, 90,10, 90,50,

      30,50, 30,90, 70,90, 70,30, 10,30 };

     static int cxClient,cyClient;

     HDC hdc ;

     PAINTSTRUCT ps

     switch (message)

     {

     case WM_SIZE:

          cxClient = LOWORD(lParam);

          cyClient = HIWORD(lParam);

          return 0 ;

     case WM_PAINT :

          hdc = BeginPaint(hwnd,&ps);

          SelectObject(hdc,GetStockObject(GRAY_BRUSH));

          //设置顶点坐标---左图

          for (int i = 0;i < 10;i++)

          {

               apt[i].x = cxClient *aptFigure[i].x/200;

               apt[i].y = cyClient *aptFigure[i].y/200;

          }

          //设置ALTERNATE填充模式

          //选择交替模式(填充每条扫描线上奇数和偶数多边形边之间的区域)

          SetPolyFillMode(hdc,ALTERNATE);

          Polygon(hdc,apt,10);//绘制多边形

          //重置顶点坐标---左图

          for (int i = 0;i < 10;i++)

          {

               apt[i].x += cxClient/2;

          }

          //设置WINDING填充模式

          //选择缠绕模式(用非零缠绕值填充任何区域)

          SetPolyFillMode(hdc,WINDING);

          Polygon(hdc,apt,10);//绘制多边形

          EndPaint(hwnd,&ps);

          return 0;

     case WM_DESTROY:

          PostQuitMessage(0);

          return 0;

     }

     return DefWindowProc(hwnd, message, wParam, lParam);

}

/******************************************************************************

SetPolyFillMode函数:设置填补多边形多边形填充模式。

int SetPolyFillMode(

  HDC hdc,

  int mode     //ALTERNATE:选择替代模式,只有该射线穿越奇数条边框线时,封闭区域才会被填充。

               //WINDING:选择绕线模式,穿过奇数条边框线或相同方向偶数条边时封闭区域才会被填充。

);

*******************************************************************************

Polygon函数:

绘制由以直线连接两个或更多个顶点的多边形。

使用当前的笔勾勒出多边形的轮廓,并使用当前的笔刷和多边形填充模式填充多边形。

BOOL Polygon(

  HDC         hdc,

  const POINT *apt, //指向POINT结构数组的指针,该数组以逻辑坐标形式指定多边形的顶点。

  int         cpt   //数组中的顶点数。该值必须大于或等于2。

);

*/

运行结果:

图4-7 填充模式

       总结

       上述实例非常简单,窗口过程中处理WM_PAINT消息时,先调用SelectObject函数选入一个灰色背景画刷,然后使用一个for循环语句初始化一个多边形顶点坐标数组,接着调用SetPolyFillMode函数和SetPolyFillMode函数设置填充模式并绘制多边形。

4.4.3 画刷

       在4.3节中我们讲述了如何创建新的自定义画笔。同样的道理,我们也可以创建新的自定义画刷。

Windows允许使用5种函数来建立逻辑画刷。调用SelectObject函数将画刷选入设备 环境。逻辑画刷也是GDI对象,这和逻辑画笔一样。所以所有你建立的画刷都必须最终被删除,但是如果它当前被选入了设备环境中,则不要删除它。

建立逻辑画刷的第一个函数

hBrush = CreateSolidBrush (crColor);

这个函数中的Solid(中文含义为实心)并不意味着画刷为纯色。将该画刷选入设备环境后, Windows可能会建立一个抖动位图,并且使用它作为画刷。

建立逻辑画刷的第二个函数

可以使用由水平、垂直或者对角线组成的“阴影线标记”(hatchmark)来建立一个画刷。这种样式的画刷对着色条形图的内部和在绘图机上绘图最常用。建立阴影线画刷的函数如下:

hBrush = CreateHatchBrush (iHatchSCyle, crColor);

参数iHatchStyle表示阴影线标记的外观。图4-8显示了 6种可用的明影线样式及其外观。

                                          图4-8 6种阴影线固刷样式

                           

CreateHatchBrush函数中的参数crClolor表示阴影线的颜色。把画刷选入设备环境后, Windows把这种颜色转换为显示器上可用的最近的纯色。阴影线之间的区域会使用设备环 境中定义的背景模式和背景颜色来着色。如果背景模式是OPAQUE,则背景颜色(也被转换 为纯色)用来填充线与线之间的空隙。如果背景的模式是TRANSPARENT,则Windows只画出阴影线,不填充它们之间的空隙。

建立逻辑画刷的第三和第四个函数

可以通过函数CreatePatternBrush和CreateDIBPatternBrushPt来建立自己的位图画刷。我们将在第十四章位图详细讲解。

建立逻辑画刷的第五个函数

建立逻辑画刷的第5个函数包含其他4个函数的所有功能:

hBrush = CreateBrushlndirect (&logbrush);

变量logbrush是一个类型为LOGBRUSH( “逻辑画刷”)的结构。这个结构有三个字段,lbStyle字段的值决定着Windows如何解释其他的两个字段。

LOGBRUSH结构体(三个字段,lbStyle 字段的值决定Windows如何解释其他两个字段)

lbStyle(UINT)

lbColor(COLORREF)

lbHatch(LONG)

BS_SOLID

画刷的颜色

被忽略

BS_HOLLOW

被忽略

被忽略

BS_HATCHED

阴影线的颜色

阴影线画刷的样式

BS_PATTERN

被忽略

位图的句柄

BS_DIBPATTERNPT

被忽略

指向DIB的指针

选入画刷和删除画刷

画刷作为GDI对象,同样必须遵循GDI对象三原则。在前面我们调用SelectObject函数将逻辑画笔选入设备环境,调用DeleteObject函数来 删除这个逻辑画笔,调用GetObject函数来获取逻辑画笔的信息。对于画刷,同样可以使用 这三个函数。一旦拥有一个画刷句柄,就可以调用SelectObject函数将其选入设备环境:

SelectObject (hdc, hBrush);

然后,调用DeleteObject函数删除已建立的画刷:

DeleteObject (hBrush);

但是不要删除当前被选入设备环境的画刷。

如果需要获取画刷的信息,可以调用GetObject函数:

GetObject (hBrush, sizeof (logbrush), (LPVOID) slogbrush);

其中,logbrush是一个类型为LOGBRUSH的结构。

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

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

相关文章

LLVM 中 的 pass 及其管理机制

概述 LLVM 编译器框架的核心概念是任务调用和执行 编译器开发者将IR分解为不同的处理对象&#xff0c;并将其处理过程实现为单独的pass类型。在编译器初始化&#xff0c;pass被实例化&#xff0c;并被添加到pass管理中 pass 管理器(pass manager) 以流水线的方式将各个独立的…

【安装笔记-20240616-Linux-为 OpenWrt 自动挂载 Windows 主机共享目录】

安装笔记-系列文章目录 安装笔记-20240616-Linux-为 OpenWrt 自动挂载 Windows 主机共享目录 文章目录 安装笔记-系列文章目录安装笔记-20240616-Linux-为 OpenWrt 自动挂载 Windows 主机共享目录 前言一、软件介绍名称&#xff1a;cifsutils主页官方介绍特点 二、安装步骤测试…

基于JSP技术的个人网站系统

开头语&#xff1a; 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP JavaBeans Servlet 工具&#xff1a;Eclipse、MySQL Workbench、…

.net8 blazor auto模式很爽(五)读取sqlite并显示(2)

在BlazorApp1增加文件夹data&#xff0c;里面增加类dbcont using SharedLibrary.Models; using System.Collections.Generic; using Microsoft.EntityFrameworkCore;namespace BlazorApp1.data {public class dbcont : DbContext{public dbcont(DbContextOptions<dbcont>…

Java高频面试题整理(几万字)

&#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我不迷路 ❤️《java面试核心知识》突击系列&#xff0c;持续更新… &#x1f490; 面试必知必会学习路线&#xff1a;Java技术栈面试系列SpringCloud项目实战学习路线 &#x1f4dd;再小的收获x365天…

ctfshow-web入门-命令执行(web43-web52)关于黑洞“ >/dev/null 2>1“的处理与绕过

目录 1、web43 2、web44 3、web45 4、web46 5、web47 6、web48 7、web49 8、web50 9、web51 10、web52 1、web43 在上一题 ‘黑洞’ 的基础上新增过滤&#xff1a; preg_match("/\;|cat/i", $c) 问题不大&#xff0c;我们不用分号和 cat 就行&#xff1a;…

ABI和API的区别

ABI和API的区别 ABI&#xff08;Application Binary Interface&#xff09;&#xff1a; ABI是一种定义了二进制接口规范的概念&#xff0c;用于描述不同模块之间如何进行二进制交互。它定义了函数调用约定、参数传递方式、寄存器使用、内存布局等底层细节。ABI的目标是确保不…

自监督分类网络:创新的端到端学习方法

现代人工智能的快速发展中&#xff0c;分类任务的高效解决方案一直备受关注。今天&#xff0c;我们向大家介绍一种名为Self-Classifier的全新自监督端到端分类学习方法。由Elad Amrani、Leonid Karlinsky和Alex Bronstein团队开发&#xff0c;Self-Classifier通过优化同一样本的…

express+vue在线im实现【二】

expressvue在线im实现【一】 在线体验 本期完成了&#xff1a; 1、心跳检测 2、支持发送表情与图片【这个目前还需要优化下&#xff0c;当图片上传后会被默认选中&#xff0c;需要点击一下旁边&#xff0c;使之失去选中效果&#xff0c;才能正常&#xff0c;留待下期优化吧】…

桂电人工智能学院大数据实验,使用 Docker 搭建 hadoop 集群

桂电人工智能学院大数据实验&#xff0c;使用 Docker 搭建 hadoop 集群 第一步 安装 Docker, Windows 上可以使用 Docker Desktop 下载地址&#xff1a;https://www.docker.com/products/docker-desktop/ 安装过程自行谷歌 安装好的标志&#xff1a;打开终端 运行docker p…

windows11子系统Ubuntu 22.04.4子安装图形化界面

1、windows11家庭版本设置 打开虚拟机安装许可 2、Microsoft Store下载安装ubuntu 我使用的是22.04.4 LTS版本 3、 打开ubuntu 命令窗口 1、打开win11的命令行&#xff0c;在下拉三角下标&#xff0c;打开&#xff0c;可以看到有Ubuntu 的选项&#xff0c;点击即可进入linux命…

鸿蒙应用开发

学习视频&#xff1a; 00.课程介绍_哔哩哔哩_bilibili 官网&#xff1a;开发者文档中心 | 华为开发者联盟 (huawei.com) 开发工具 &#xff1a;DevEcoStudio &#xff0c; 类似Jetbrains 全家桶 ArkTS开发语言 &#xff1a;&#xff08;基于TS,集成了前端语言&#xf…

MySQL日志(二):MySQL抖动

一条SQL语句&#xff0c; 正常执行的时候特别快&#xff0c; 但是有时也不知道怎么回事&#xff0c; 它就会变得特别慢&#xff0c; 并且这样的场景很难复现&#xff0c; 它不只随机&#xff0c; 而且持续时间还很短。 看上去&#xff0c; 这就像是数据库“抖”了一下。 今天&…

c++编程(18)——deque的模拟实现(2)容器篇

欢迎来到博主的专栏——c编程 博主ID&#xff1a;代码小豪 文章目录 deque的数据结构deque的构造默认构造填充构造 deque的其他操作deque的插入、删除push_back和push_frontpop_back和pop_frontclear、erase和insert操作 传送门 在上一篇中&#xff0c;我们已经实现了deque最核…

数据仓库和数据库有什么区别?

一、什么是数据仓库二、什么是数据库三、数据仓库和数据库有什么区别 一、什么是数据仓库 数据仓库&#xff08;Data Warehouse&#xff09;是一种专门用于存储和管理大量结构化数据的信息系统。它通过整合来自不同来源的数据&#xff0c;为企业提供统一、一致的数据视图&…

【最新鸿蒙应用开发】——鸿蒙中的“Slot插槽”?@BuilderParam

构建函数-BuilderParam 传递 UI 1. 引言 BuilderParam 该装饰器用于声明任意UI描述的一个元素&#xff0c;类似slot占位符。 简而言之&#xff1a;就是自定义组件允许外部传递 UI Entry Component struct Index {build() {Column({ space: 15 }) {SonCom() {// 直接传递进来…

论文阅读:RAM++ | Open-Set Image Tagging with Multi-Grained Text Supervision

发表时间&#xff1a;2023年11月16 论文地址&#xff1a;https://arxiv.org/pdf/2310.15200 项目地址&#xff1a;https://github.com/xinyu1205/recognize-anything Recognize Anything Plus Model&#xff08;RAM&#xff09;&#xff0c;这是一种有效利用多粒度文本监督的开…

博通加速向Nvidia发起进攻 为何连iPhone 15都不能用“苹果智能”?

博通加速向Nvidia发起进攻 博通强调的一项优势是其 XPU 的能效。其功耗不到 600 瓦&#xff0c;是业内功耗最低的 AI 加速器之一。 Nvidia 的许多竞争对手都想抢占其市场主导地位。其中一个不断出现的名字是 Broadcom。仔细观察就会知道原因。其 XPU 功耗不到 600 瓦&#xff…

GPT-4并非世界模型,LeCun双手赞同!ACL力证LLM无法模拟真实世界

一直以来&#xff0c;支持LLM的观点之一是模型可以集成海量事实知识&#xff0c;作为通往「世界模拟器」的基础。虽然也有不少反对意见&#xff0c;但缺乏实证依据。那么&#xff0c;LLM能否作为世界模拟器&#xff1f; 最近&#xff0c;亚利桑那大学、微软、霍普金斯大学等机构…

飞腾银河麒麟V10安装Todesk

下载安装包 下载地址 https://www.todesk.com/linux.html 安装 yum makecache yum install libappindicator-gtk3-devel.aarch64 rpm -ivh 下载的安装包文件后台启动 service todeskd start修改配置 编辑 /opt/todesk/config/config.ini 移除自动更新临时密码 passupda…