基于Windows GDI+的几何线条处理

C#成魔之路<11> GDI+绘图 用户界面上的窗体和控件,需要使用颜色和图形对象。或者使用线条或者弧线进行游戏开发,或者使用很多图形来开发屏幕保护程序。在这种情况下使用窗体控件是不够的,还需要图形功能。GDI+是图形设备接口的高级版本。1、GDI+绘图基础 GDI+是GDI的后继者,它是一种构成Windows XP操作系统的子系统的应用程序编程接口(API)。 一般来说有三种基本类型的绘图界面,分别为Windows窗体控件、要发 阅读详情

基于Windows GDI+的几何线条处理

徐歆恺  梁博  葛庆平

首都师范大学信息工程学院,北京100044

摘要 介绍了GDI+对几何线条创建、应用等基本方法,并以实例的方式对其中难于理解的部分提供了示例代码,实现了原先GDI不易实现的功能,并为进一步利用GDI+进行更复杂的图形处理奠定了良好的基础。

关键词 GDI+ ;几何线条

1 引言

GDI+是原Windows GDI的扩展,增加了新功能并对原功能模块进行了优化,使编程人员更易实现多种高级功能。因GDI+的强大功能及其完美的性能,微软倡导新应用程序的开发基于GDI+进行。[1]

所谓路径,是指可以被填充的、画出轮廓或同时被画出轮廓并填充的一个或多个图形。路径的引入,大大地丰富了Windows的图形功能,使得应用程序可以方便地建立复杂区域,绘制和填充不规则图形。[2]

路径一般由以下元素组成:直线、矩形、椭圆、圆弧、多边形、三次样条和贝塞尔曲线。在GDI+中,几何线条的处理主要是通过调用图形路径(GraphicsPath)的方法来实现的。使用GraphicsPath对象可以将这些元素收集到一个单元中。以后只需调用Graphics类的DrawPath方法,就可以一次绘制出该对象收集的全部元素序列。[3]

2 编程方法与实例

2.1 准备工作

使用GDI+编程,必须包含gdiplus.h头文件,要使用Gdiplus名称空间,连接时需要Gdiplus.lib。使用GDI+绘制对象时需要获取一个设备描述表句柄,把它作为参数传递给Graphics的构造函数,这样就可以使用Graphics对象的库函数了。[4]

使用GDI+编程必须在创建GDI+对象前执行GdiplusStartup实现初始化,在程序结束时调用GdiplusShutdown关闭GDI+功能,清理占用的资源。两组函数要成对调用。[1]

示例代码如下所示:

//---------------------------在stdafx.h文件中-----------------------------------//

#include "Gdiplus.h"

using namespace Gdiplus ;

#pragma comment (lib, "Gdiplus.lib")

//----------------------在应用程序类的InitInstance函数中-----------------------//

GdiplusStartupInput     gdiplusStartupInput ;

GdiplusStartup (&m_GdiplusToken, &gdiplusStartupInput, NULL) ;

//-----------------------在应用程序类的ExitInstance函数中---------------------//

GdiplusShutdown (m_GdiplusToken) ;

注:其中变量m_GdiplusToken应该是ULONG_PTR类型的全局变量,或者是应用程序类的成员变量

2.2 路径的创建

GraphicsPath类提供了许多创建路径元素的接口:AddArc(圆弧)、AddBezier(贝塞尔曲线)、AddBeziers(贝塞尔曲线序列)、AddClosedCurve(闭合的基数样条曲线)、AddCurve(基数样条曲线)、AddEllipse(椭圆)、AddLine(直线段)、AddLines(直线段序列)、AddPie(扇形)、AddPolygon(多边形)、AddRectangle(矩形)、AddRectangles(矩形序列)和AddString(字符串轮廓路径)。

图1 MSDN中提供的路径的例子

2.3 子路径的添加和提取

GraphicsPath还可以包含多个图形,其中每一个图形被称为子路径(figures)。如果在GraphicsPath对象中使用了StartFigure或CloseFigure函数,在这两个之后对路径所添加的线条都将构成一个的子路径。[5]这两个函数的区别是,StartFigure方法不闭合当前图形即开始一个新图形,而CloseFigure方法闭合当前图形并开始新的图形。

下面两段示例代码在路径中添加了两个条路径,前一条子路径由两条直线段组成,后一条子路径是一个圆形。两段代码不同的地方仅仅在于StartFigure和CloseFigure函数的使用,因而它们的效果也不相同,如图2和图3所示。


//示例代码1----使用StartFigure

GraphicsPath path;

path.AddLine(100,100,100,150);

path.AddLine(100,150,150,150);

path.StartFigure();

path.AddEllipse(75,75,50,50);

Graphics g(hdc);

g.DrawPath(&Pen(Color::Black,1),&path);

//示例代码2----使用CloseFigure

GraphicsPath path;

path.AddLine(100,100,100,150);

path.AddLine(100,150,150,150);

path.CloseFigure();

path.AddEllipse(75,75,50,50);

Graphics g(hdc);

g.DrawPath(&Pen(Color::Black,1),&path);


                        

图2 StartFigure效果          图3 CloseFigure效果

GDI+的GraphicsPathIterator类完成了对路径的一个或多个子路径的描述、管理、测试等功能。GraphicsPathIterator能够从给定的路径中进行多种与子路径相关的操作。[5]

表1 GraphicsPathIterator类常用成员函数

常用成员函数

功能描述

HasCurve

指示与此GraphicsPathIterator对象关联的路径是否包含曲线

NextSubpath

将此子路径移到指定的GraphicsPath对象中的下一子路径

Rewind

将此GraphicsPathIterator对象重绕到其关联路径的起始处

GetSubpathCount

获取路径中子路径的数目

2.4 路径的几何变形

GDI+提供的Matrix类封装表示几何变形的3×3仿射矩阵。通过设置Matrix对象,可以旋转、缩放、错切或平移GraphicsPath对象。

表2 Matrix类常用成员函数

常用成员函数

功能描述

Rotate

相对于原点顺时针旋转指定角度

Scale

缩放操作

Shear

错切变换操作

Translate

平移操作

Reset

重置此Matrix对象,使其成为单位矩阵

以矩形为例,路径变形的示例代码如下:

Graphics g(hdc);

GraphicsPath path;

path.AddRectangle(Rect(40, 10, 200, 50));

g.DrawPath(&Pen(Color(255, 0, 0, 0),1), &path);     // 在应用变形矩阵之前绘制矩形

// 路径变形

Matrix matrix;

matrix.Rotate(30.0f);   //旋转顺时针30度

matrix.Scale(0.5f,0.5f);//缩小一半

path.Transform(&matrix);//应用变形

g.DrawPath(&Pen(Color(255, 0, 0,  0),3), &path);    // 以3象素宽的粗线绘制变换后的矩形

图4 矩形的旋转与缩放

类似的,用GraphicsPath类的Warp方法,可以对路径应用由一个矩形和一个平行四边形定义的扭曲变形。

2.5 路径的存储与读取

GraphicsPath 对象存储一系列直线和贝塞尔样条。尽管可以将若干种类型的曲线(椭圆、弧形和基数样条)添至路径,但在存储到路径中之前,各种曲线都会自动转化为贝塞尔样条。直线可以由起点和终点来构成,而贝塞尔样条曲线是由起点、终点和控制点定义。所以,对于一个路径的描述,可以通过对路径点信息的处理来实现。[4]

2.5.1 存储路径

在GraphicsPath对象的存储过程中,有三个函数非常重要,那就是GetPointCount、GetPathPoints和GetPathTypes,利用这3个函数,可以获得路径中路径点的数目、坐标和类型。具体代码如下:

INT count = path.GetPointCount();          // 获得路径点数目

ar<<count;                                 // 存储路径点数目

dataPoints = new Point[count];       

path.GetPathPoints(dataPoints, count);     // 获得路径点坐标

pTypes = new BYTE[count];

path.GetPathTypes(pTypes, count);          // 获得路径点类型

//开始存储

for(INT i=0;i<count;i++){

ar<<dataPoints[i].X<<dataPoints[i].Y;     // 存储路径点坐标

ar<<pTypes[i];                            // 存储路径点类型

}

……………………

delete dataPoints;                         // 回收内存

delete pTypes;

2.5.2 读取路径

由于GraphicsPath类中只有构造函数才能由路径点创建,读取路径的方法就要复杂一些了。具体代码如下:

path.Reset();                              // 重置路径

INT count;

ar>>count;                                 // 读取路径点数目

dataPoints = new Point[count];             // 定义路径点坐标

pTypes = new BYTE[count];                  // 定义路径点类型

//开始读取

for(INT i=0;i<count;i++){

ar>>dataPoints[i].X>>dataPoints[i].Y;     // 读取路径点坐标

ar>>pTypes[i];                            // 读取路径点类型

}

GraphicsPath pa(dataPoints,pTypes,count);  // 由路径点创建临时路径pa

path.AddPath(&pa,false);                   // 将临时路径pa添加到路径path中

……………………

delete dataPoints;                         // 回收内存

delete pTypes;

2.6 路径的线段逼近

调用GraphicsPath对象的Flatten方法,可以将路径中的曲线全部转换成多段相连的直线段,如图5所示,这种方法也被称为“拉平”或“展平”。Flatten方法接收拉平参数,该参数指定拉平的路径和原始路径之间的最大距离。

图5 原始曲线路径与拉平后的路径(这里拉平参数为8.0)

将路径拉平后,使用直线段长度累加的方法,可以轻易地计算出路径曲线的长度和其他信息,并可以通过降低拉平参数值的方法来提高计算的精度。由于路径点的坐标是以浮点数的形式保存的,因而用这种方式得到的曲线长度的精度还是相当高的。

3 结束语

GraphicsPath还有很多种用法,比如可以使用IsVisible方法判断坐标点是否落在路径上,使用IsOutlineVisible方法指示当使用指定的Pen对象绘制此GraphicsPath 对象时,指定点是否包含在后者的轮廓内。

从开发的实践过程来看,使用GDI+进行图形编程,比原先的GDI编程过程要容易很多,而且最终的图形功能也更强大。

参考文献

1、朱平军,庞雄奇,周海燕.基于GDI+的VC图形的填充[J].计算机时代,2003年,(11):38-39.

2、周鸣扬.Visual C++界面编程技术[M].北京:北京希望电子出版社,2003.242-256.

3、李博轩.Visual C++.NET多媒体应用开发技术[M].北京:国防工业出版社,2002.31-41.

4、史晓峰,赵耀红.基本图像处理功能在GDI+中的实现方法[J].长春工程学院学报(自然科学版),2003,4(3):67-69.

5、周鸣扬.GDI+程序设计实例[M].北京:中国水利水电出版社,2004.189-233.

掌握Windows图形绘制:gdi32.dll类库详解 GDI(Graphics Device Interface)是Windows操作系统中用于处理图形输出的底层API。它允许应用程序在屏幕、打印机或其他图形输出设备上绘制图形和文本。GDI通过抽象设备环境(Device Contexts,DCs)来实现与具体硬件无关的绘图操作,这种抽象层提供了一种统一的方式来处理各种不同的输出设备。GDI的主要功能包括:基本图形绘制:线条、矩形、椭圆、多边形等文本输出:包括字体处理、文本的布局和格式化颜色管理:处理RGB、CMYK等颜色模型。 阅读详情

相关推荐

VC++环境下基于MFC与GDI的几何图形绘制实战

尽管Direct2D、Skia、Qt等现代渲染技术层出不穷,但GDI仍在大量企业级应用、工控软件、嵌入式系统中服役。掌握它的核心原理,不仅能帮助你维护 legacy code,更能让你理解图形系统的设计本质。“真正的高手,不是只会用最新的工具,而是能在任何环境下写出健壮的代码。” 💪当你下次面对一个频繁闪烁的窗口时,不妨问问自己:- 我有没有正确使用双缓冲?- DC和GDI对象是否及时释放?- 图形数据是不是存在成员变量里?

weixin_42527665的博客 715

GDI+ 绘制曲线方法总结

GDI+ 绘制曲线方法总结

编程猿来如此 2382

GDIPlus++:C++中的GDI+图形开发包

GDI+(Graphics Device Interface Plus)是微软提供的一套用于二维图形、图像处理的编程接口。相比旧版的GDI,GDI+支持更丰富的图形操作和图像处理功能,它包括了绘制线条、图形、图像处理、文本输出以及颜色管理等。GDI+提供的不仅仅是简单的绘图对象,例如Pen和Brush,还包括了一系列用于复杂图形的高级对象。这些对象可以用来构建自定义形状和模式,例如或。使用这些对象可以实现各种图形效果,如渐变色填充或图案填充等。使用。

weixin_42502089的博客 1357

多段Bazier(贝塞尔曲线)、BSpline(B样条曲线)的绘制与鼠标交互控制

我们的目标是类似 sketch 的曲线点编辑功能。 这是源代码: 1. 分析 如图,这是一个3个点的曲线,每个点都提供了两个控制把柄,可以拖拽其编辑曲线。 (本来想传gif动画,但太大了传不上去) 要实现该逻辑,我们有以下几个任务 定义曲线点 定义曲线 绘制曲线 绘制控制把柄 与鼠标交互,可拖拽曲线点及控制把柄 2. 曲线的绘制 绘制曲线段很容易实现,用GDI+ 的 Graphics.DrawBazier() 方法就行了。其原型是: // p1、p2 是曲线段终点,ctrl1和

Kevin Cheng's Yard 3110

QT实现多边形填充算法

利用QT实现多边形的填充算法,在网格下坐标系下,双击两下鼠标显示起点,之后点击依次连线,一共七条线,首尾要在同一个坐标才能实现功能。

GDIplus贴图上画线

GDI+ 贴图 背景 mfc c++ 画图,贴了一张图,在图上可以画画,用GDI+实现的,调试通过。以后改善继续更新。

笔记9:GraphicsPath对象

01 GraphicsPath对象    它由一系列相互连接的直线、曲线连接起来组成的开放(非闭合)图形。    创建路径时就会隐式创建一个新图形(由上面的直线、曲线等组成)。也可以                  显示地声明StartFigure。               图形具有方向,其先后顺序加入的直线、曲线等就表明了次序。    一般图形路径是开放的,由起点,到最

白话魔法师 2万+

美团mtgsig 3.1.0算法还原:从加密入口到d1生成的完整链路拆解

本文详细拆解了美团mtgsig 3.1.0签名算法的完整逆向过程。通过定位加密入口函数eH,理清a6、a5、a8到d1的生成依赖链,并运用插桩技术,在JSVMP混淆环境下逐步还原了核心参数的生成逻辑,为逆向工程实践提供了清晰的纯算还原方法论。

oo7890的博客 778

GDI+ 路径 - IsVisible、IsOutlineVisible

GDI+ 路径 - IsVisible、IsOutlineVisible   代码文件:unit Unit1; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs; type  TForm1 = class(TForm)  ...

java开发指南博客 【转载】 440

私彩视频开奖动画直播源码内部核心技术解析及修改可增加后台操控-持续更新文章!

其实在此很感谢能做出H5开奖系统的码农们,而我本人也喜欢分解此类的东西。 因为特殊原因,该东西本人就不做图片展示,以防他人商业化。 借用开奖摇奖代码首先分解首页index文件。代码如下:(后面持续在原有的作品上添加后台操作) 代码里写的//.....是我的注明代码的所需。 ​ &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;...

yugua3837的博客 5996

海康Visionmaster-全局脚本:VM 加载方案后自动执行 的方法,如何让VM在方案加载后自动执行流程?

海康Visionmaster-全局脚本:VM 加载方案后自动执行 的方法,如何让VM在方案加载后自动执行流程?

视觉人机器视觉的博客 2038

GDI+ 中的基数样条,基数样条曲线的Demo

[MSDN]GDI+ 中的基数样条 基数样条是一连串单独的曲线,这些曲线连接起来形成一条较大的曲线。样条由点的数组和张力参数指定。基数样条平滑地经过数组中的每个点;曲线的陡度上没有尖角和突然的变化。下面的插图显示了一组点和经过这一组点中每一点的基数样条。 物理和数学样条 物理样条是一块薄木片或其他有弹性的物质。在数学样条出现之前,设计者利用物理样条绘制曲线。设计者把样条放置在一张纸上并锚定到一组给定的点上。然后,设计者就可以用钢笔沿样条绘制出一条曲线。一组给定的点可以产生各种各样的曲线,这取决于物

stevekk的专栏 2647

基于Simulink的光储系统黑启动能力仿真

本文基于Simulink平台构建了光储系统黑启动仿真模型,详细阐述了储能VF控制、光伏孤岛MPPT和同步并网等核心控制策略。通过分阶段协调控制(储能启动→关键负载→光伏接入→非关键负载→同步并网),实现了60秒内恢复供电、母线电压波动<5%的性能指标。仿真结果表明,协调控制策略相比无序启动可显著提升系统稳定性,避免电压崩溃和负载跳闸。文章还提供了完整的建模步骤、核心代码及进阶优化方向,为微电网应急供电设计提供了实用参考。该模型适用于光伏储能系统的黑启动能力验证和优化研究。

amy_mhd的博客 106

gdi+ 资料保存

GDI+如何填充任意封区域?就像windows画笔中的油漆桶那样的功能? http://zhidao.baidu.com/question/89862558.html http://hbhuo2008.blog.163.com/blog/static/21051202010726102924359/ 基于Windows GDI+的几何线条处理 http://www.ye...

weixin_30535043的博客 73

Qt C++ 电子海图与作战叠加(Overlay)系统

lab_pos->setText(QString("坐标: X%1 Y%2").arg(p.x(),0,'f',0).arg(p.y(),0,'f',0));lab_distance->setText(QString("距离: %1 海里").arg(dist,0,'f',1));lab_bearing->setText(QString("方位: %1°").arg(bear,0,'f',1));// 绘制S-57海图基底。scene->addText("封锁线").setPos(450,180);

寒寒豆豆软件公司的博客 496

游戏引擎揭秘:大厂为何死磕自研?

游戏引擎本质与商业价值解析 游戏引擎是集成了渲染、物理、动画等核心功能的开发工具包,其价值在于让开发者免于重复编写底层代码,专注于游戏内容创作。商业引擎(如Unity/Unreal)虽降低了开发门槛,但头部厂商仍坚持自研引擎,主要基于以下考量: 经济性:长期项目分摊自研成本后,比商业引擎分成更划算; 可控性:完全掌握底层代码,能针对性优化核心玩法需求; 技术壁垒:专属引擎成为厂商的竞争优势,如米哈游的跨平台渲染技术; 项目适配:超大型游戏(开放世界/MMO)需要深度定制解决方案。 这种"短期高投入

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 263

C# GDI+绘图基础

01 GDI+概述GDI+指的是 .NET Framework 4.0 中提供二维图形、图像处理等功能,是构成 Windows 操作系统的 一个子系统,它提供了图形图像操作的应用程序编程接...

zls365365的博客 2781

Zookeeper+Hadoop+Spark+Flink+Kafka+Hbase+Hive 完全分布式高可用集群搭建(保姆级超详细含图文) 附安装包网盘下载

Hadoop+Spark+Flink+Zookeeper+Kafka+Hbase+Hive完全分布式高可用集群搭建 Hadoop高可用集群搭建 Spark高可用集群搭建 Flink高可用集群搭建 Zookeeper高可用集群搭建 Kafka高可用集群搭建 Hbase高可用集群搭建 Hive高可用集群搭建 mysql搭建 jdk部署 大数据集群环境搭建

Mr.L-OAM的博客 2万+

GDI功能介绍:图形绘制与图像处理

GDI功能介绍:图形绘制与图像处理 目录: 1. 引言 2. C#中的GDI(Graphics Device Interface) - 什么是GDI? - GDI的作用和优势 3. GDI功能分类 - 基本绘图功能 - 文本处理 - 图像处理 4. 示例代码 - 绘制简单图形 - 绘制文本 - 加载和显示图像 5. 总结

没有黑科技 833

微信公众号网页H5跳转小程序实战指南(开放标签wx-open-launch-weapp)微信H5跳转小程序、wx-open-launch-weapp、小程序跳转按钮、微信开放标签、H5打开小程序

跳转小程序(wx-open-launch-weapp)唤起App显示支付按钮等等……而我们这次要用的,就是跳转小程序的标签。场景是否支持服务号网页✅ 支持小程序静态网页托管✅ 支持订阅号❌ 不支持微信外部浏览器❌ 不支持这个“开放标签”功能其实很强大,除了跳转小程序,还有唤起APP、跳支付、调用客服等能力。但可惜资料零散,很多坑等着你亲自踩一遍。这篇文章我整理的流程基本涵盖了从“能不能跳”到“怎么跳”的完整路径,希望你能像我一样省下几个小时的踩坑时间。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1163

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

MFC 之 GDI

Windows GDI 专门用途的设备描述表类 类名 描述 CPaintDC 用于在窗口客户区画图(仅限于处理OnPaint消息) CClinetDC 用于在客户区画图(除OnPaint外任何处理程序) CWindowDC 用于在窗口内任意地方绘图,包括非客户区 CMetaFileDC 用于向GDI元文件绘图 常见的GDI函数//设置窗口背景色 virtual C

657

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Windows 2D 绘图技术演进:从 GDI 到 Direct2D 的实战对比

本文系统梳理了Windows平台2D绘图技术的演进历程,从经典的GDI、面向对象的GDI+,到现代GPU加速的Direct2D。通过实战代码对比,深入分析了三者在性能、渲染质量、编程模型上的核心差异,并提供了基于应用场景的技术选型指南与迁移策略,帮助开发者构建高性能、高质量的图形界面应用。

weixin_29196891的博客 289

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

GDI+编程基础1

本文参考:《精通GDI+编程》 一、GDI是什么 GDI+是Windows操作系统的图像引擎,负责在屏幕和打印机上显示和打印消息。           是一个应用编程接口,通过一组C++类来提供接口的功能。           是早期图形设备接口GDI的继任者。 二、GDI体系 GDI+的工作原理及其在操作系统中所扮演的角色,如下图 GDI+所包含的内容: 1、二位几何图形的处

s110600824s的专栏 842

[学习笔记] Windows编程——GDI——(十三)路径

学习笔记,随时更新。如有谬误,欢迎指正。说明:红色字体。

cxsydzn的博客 911
上一篇: VC实现BMP位图文件结构及平滑缩放
下一篇: Test
点滴皆收获
博客等级 码龄24年 0粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值