gdi+绘图是怎样做才能让gdi图形程序设计 pdf不会因分辨率不同而变化

基于VC.NET的GDI+图像处理
生活已是百般艰难,为何不努力一点。下面图老师就给大家分享基于VC.NET的GDI+图像处理,希望可以让热爱学习的朋友们体会到设计的小小的乐趣。
  本问介绍了GDI+支持的大多数图像文件格式,以及GDI+提供的处理图像的文件的两个类:Image和Bitmap  & 我们知道,在以往的图像处理中,常常要根据不同图像文件的格式及其数据结构在不同格式中进行转换。某个图像文件的显示也是依靠对文件数据结构的剖析,然后读取相关图像数据而实现的。现在,GDI+提供了Image和Bitmap类使我们能轻松容易地处理图像。  概述  GDI+支持大多数流行的图像文件格式,如BMP、GIF、JPEG、TIFF和PNG等。下面先来介绍这些图像文件,然后再说明Image和Bitmap类支持的特性。  1.图像文件格式简介  图像文件是描绘一幅图像的计算机磁盘文件,其文件格式不下数十种。这里仅介绍BMP、GIF、JPEG、TIFF和PNG等图像文件格式。   BMP文件格式  BMP图像文件格式是Microsoft为其Windows环境设置的标准图像格式。一个Windows的BMP位图实际上是一些和显示像素相对应的位阵列,它有两种类型:一种称之为GDI位图,另一种是DIB位图(Device-Independent Bitmap)。GDI位图包含了一种和Windows的GDI模块有关的Windows数据结构,该数据结构是与设备有关的,故此位图又称为DDB位图(Device-Dependent Bitmap)。当用户的程序取得位图数据信息时,其位图显示方式视显示卡而定。由于GDI位图的这种设备依赖性,当位图通过传送到另一台PC,很可能就会出现问题。  DIB比GDI位图有很多编程优势,例如它自带信息,从而使调色板管理更加容易。且任何运行Windows的机器都可以处理DIB,并通常以后缀为.BMP的文件形式被保存在磁盘中或作为资源存在于程序的EXE或DLL文件中。   GIF文件格式  图形交换格式(GIF--Graphics Interchange Format)最早由CompuServe公司于日制定的标准,主要用于CompuServe网络图形数据的在线传输、存储。GIF提供了足够的信息并很好地组织了这些信息,使得许多不同的输入输出设备能够方便地交换图像,它支持24位彩色,由一个最多256种颜色的调色板实现,图像的大小最多是64K x 64K个像点。GIF的特点是LZW压缩、多图像和交错屏幕绘图。   JPEG文件格式  国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合成立的"联合专家组"JPEG(Joint Photographic Experts Group)经过五年艰苦细致工作后,于1991年3月提出了ISO CD 10918号建议草案:"多灰度静止图像的数字压缩编码"(通常简称为JPEG标准)。这是一个适用于彩色和单色多灰度或连续色调静止数字图像的压缩标准。它包括无损压缩和基于离散余弦变换和Huffman编码的有损压缩两个部分。前者不会产生失真,但压缩比很小;后一种算法进行图像压缩时,信息虽有损失但压缩比可以很大。例如压缩20~40倍时,人眼基本上看不出失真。  JPEG图像文件也是一种像素格式的文件格式,但它比BMP等图像文件要复杂许多。所幸的是,GDI+的Image提供了对JPEG文件格式的支持,使得我们不需要对JPEG格式有太多的了解就能处理该格式的图像。   TIFF文件格式  TIFF(Tagged Image Format File,标志图像文件格式)最早由Aldus公司于1986年推出的,它能对从单色到24位真彩的任何图像都有很好的支持,而且在不同的平台之间的修改和转换是十分容易的。与其它图像文件格式不同的是,TIFF文件中有一个标记信息区用来定义文件存储的图像数据类型、颜色和压缩方法。   PNG文件格式  PNG(Portable Network Graphic,可移植的网络图像)文件格式是由Thomas Boutell、Tom Lane等人提出并设计的,它是为了适应网络数据传输而设计的一种图像文件格式,用于取代格式较为简单、限制严格的GIF图像文件格式。而且,这种图像文件格式在某种程度上甚至还可以取代格式比较复杂的TIFF图像文件格式。它的特点主要有:压缩效率通常比GIF要高、提供Alpha通道控制图像的透明度、支持Gamma校正机制用来调整图像的亮度等。  需要说明的是,PNG文件格式支持三种主要的图像类型:真彩色图像、灰度级图像以及颜色索引数据图像。JPEG只支持前两种图像类型,而GIF虽然可以利用灰度调色板补偿图像的灰度级别,但原则上它仅仅支持第三种图像类型。  mage和Bitmap类概述  GDI+的Image类封装了对BMP、GIF、JPEG、PNG、TIFF、WMF(Windows元文件)和EMF(增强WMF)图像文件的调入、格式转换以及简单处理的功能。而Bitmap是从Image类继承的一个图像类,它封装了Windows位图操作的常用功能。例如,Bitmap::SetPixel和Bitmap::GetPixel分别用来对位图进行读写像素操作,从而可以为图像的柔化和锐化处理提供一种可能。  3.DrawImage方法  DrawImage是GDI+的Graphics类显示图像的核心方法,它的重载函数有许多个。常用的一般重载函数有: Status DrawImage( Image* image, INT x, INT y); Status DrawImage( Image* image, const Rect& rect); Status DrawImage( Image* image, const Point* destPoints, INT count); Status DrawImage( Image* image, INT x, INT y, INT srcx, INT srcy, INT srcwidth, INT srcheight, Unit srcUnit);   其中,(x,y)用来指定图像image显示的位置,这个位置和image图像的左上角点相对应。rect用来指定被图像填充的矩形区域, destPoints和count分别用来指定一个多边形的顶点和顶点个数。若count为3时,则表示该多边形是一个平行四边形,另一个顶点由系统自动给出。此时,destPoints中的数据依次对应于源图像的左上角、右上角和左下角的顶点坐标。srcx、srcy、srcwidth 和srcheight用来指定要显示的源图像的位置和大小,srcUnit用来指定所使用的单位,默认时使用PageUnitPixel,即用像素作为度量单位。   调用和显示图像文件  在GDI+中调用和显示图像文件是非常容易的,一般先通过Image或Bitmap调入一个图像文件构造一个对象,然后调用Graphics::DrawImage方法在指置处显示全部或部分图像。例如下面的代码:void CEx_GDIPlusView::OnDraw(CDC* pDC) {  CEx_GDIPlusDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  using namespace G  Graphics graphics( pDC-m_hDC );  Image image(L"sunflower.jpg");  graphics.DrawImage(&image, 10,10);  Rect rect(130, 10, image.GetWidth(), image.GetHeight());  graphics.DrawImage(&image, rect); }   结果如图7.17所示,从图中我们可以看出,两次DrawImage的结果是不同的,按理应该相同,这是怎么一回事?原来,DrawImage在不指定显示区域大小时会自动根据设备进行缩放,从而造成显示结果的不同。  当然,也可以使用Bitmap类来调入图像文件来构造一个Bitmap对象,其结果也是一样的。例如,上述代码可改为:Bitmap bmp(L"sunflower.jpg"); graphics.DrawImage(&bmp, 10,10); Rect rect(130, 10, bmp.GetWidth(), bmp.GetHeight()); graphics.DrawImage(&bmp, rect);   需要说明的是,Image还提供GetThumbnailImage的方法用来获得一个缩略图的指针,调用DrawImage后可将该缩略图显示,这在图像预览时极其有用。例如下面的代码:Graphics graphics( pDC-m_hDC ); Image image(L"sunflower.jpg"); Image* pThumbnail = image.GetThumbnailImage(50, 50, NULL, NULL); // 显示缩略图 graphics.DrawImage(pThumbnail, 20, 20); // 使用后,不要忘记删除该缩略图指针 delete pT & 图像旋转和拉伸  图像的旋转和拉伸通常是通过在DrawImage中指定destPoints参数来实现,destPoints包含对新的坐标系定义的点的数据。图7.18说明了坐标系定义的方法。  从图中可以看出,destPoints中的第一个点是用来定义坐标原点的,第二点用来定义X轴的方法和图像X方向的大小,第三个是用来定义Y轴的方法和图像Y方向的大小。若destPoints定义的新坐标系中两轴方向不垂直,就能达到图像拉伸的效果。  下面的代码就是图像旋转和拉伸的一个示例,其结果如图7.19所示。Image image(L"sunflower.jpg"); graphics.DrawImage(&image, 10,10); Point points[] = { Point(0, 0), Point(image.GetWidth(), 0),& Point(0, image.GetHeight())}; Matrix matrix(1,0,0,1,230,10); // 定义一个单位矩阵,坐标原点在(230,10) matrix.Rotate(30); // 顺时针旋转30度 matrix.Scale(0.63,0.6); // X 和 Y 方向分别乘以0.63和0.6比例因子 matrix.TransformPoints(points, 3); // 用该矩阵转换points graphics.DrawImage(&image, points, 3);& Point newpoints[] = {Point(450, 10), Point(510, 60), Point(350, 80)}; graphics.DrawImage(&image, newpoints, 3);   当然,对于图像旋转还可直接使用Graphics::RotateTransform来进行,例如下面的代码。但这样设置后,以后所有的绘图结果均会旋转,有时可能感觉不方便。Image image(L"sunflower.jpg"); graphics.TranslateTransform(230,10); // 将原点移动到(230,10) graphics.RotateTransform(30); // 顺时针旋转30度 graphics.DrawImage(&image, 0,0);   调整插补算法的质量  当图像进行缩放时,需要对图像像素进行插补,不同的插补算法其效果是不一样的。Graphics:: SetInterpolationMode可以让我们根据自己的需要使用不同质量效果的插补算法。当然,质量越高,其渲染时间越长。下面的代码就是使用不同质量效果的插补算法模式,其结果如图7.20所示。 Graphics graphics( pDC-m_hDC ); Image image(L"log.gif"); UINT width = image.GetWidth(); UINT height = image.GetHeight(); // 不进行缩放 graphics.DrawImage( &image,10,10);& // 使用低质量的插补算法 graphics.SetInterpolationMode(InterpolationModeNearestNeighbor); graphics.DrawImage( &image, Rect(170, 30, (INT)(0.6*width), (INT)(0.6*height))); // 使用中等质量的插补算法 graphics.SetInterpolationMode(InterpolationModeHighQualityBilinear); graphics.DrawImage( &image, Rect(270, 30, (INT)(0.6*width), (INT)(0.6*height))); // 使用高质量的插补算法 graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic); graphics.DrawImage( &image, Rect(370, 30, (INT)(0.6*width), (INT)(0.6*height)));   事实上,Image功能还不止这些,例如还有不同格式文件之间的转换等。但这些功能和MFC的新类CImage功能基本一样,但CImage更符合MFC程序员的编程习惯,因此下一节中我们来重点介绍CImage的使用方法和技巧。 & 搜索“图老师”或者“tulaoshi_com”加关注,每天最新的美食、、、美妆、、手工DIY等教程让你一手全掌握。推荐关注!【扫描下图可直接关注】
来源:/n/1641.html
点击查看更多与《》相关的文章>>
下面请跟着图老师小编一起来了解下VB图像处理之二次线性插值的应用,精心挑选的内容希望大家喜欢,不要忘记点个赞哦!
体验PS CS2增强的图像处理能力,体验PS CS2增强的图像处理能力
C#中关于GDI+输出的问题,C#中关于GDI+输出的问题
想要天天向上,就要懂得享受学习。图老师为大家推荐Photoshop把杂乱的人像图片简化处理,精彩的内容需要你们用心的阅读。还在等什么快点来看看吧!
体验Photoshop CS2增强的图像处理能力,体验Photoshop CS2增强的图像处理能力
给自己一点时间接受自己,爱自己,趁着下午茶的时间来学习图老师推荐的VB图像处理之几个常用滤镜的实现,过去的都会过去,迎接崭新的开始,释放更美好的自己。
热门搜索:
如何设置电脑定时关机方法
IE主页被恶意篡改该怎么还原
无法使用双击打开电脑里的内存盘
如何解决电脑时间更改不了的问题
现在很多人都非常喜欢饲养狗狗,而且饲养金毛狗狗的人可以说是非常多的,毕竟金毛狗狗非常的可爱,而且性格非常温顺。所以饲养的人当然很多。那么喂养金毛狗时要注意什么?一起来看看吧。
现在很多人都非常喜欢饲养狗狗,而且饲养金毛狗狗的人可以说是非常多的,毕竟金毛狗狗非常的可爱,而且性格非常温顺。所以饲养的人当然很多。那么金毛狗狗不能吃哪些东西?一起来看看吧。
现在很多人都非常喜欢饲养狗狗,而且饲养金毛狗狗的人可以说是非常多的,毕竟金毛狗狗非常的可爱,而且性格非常温顺。所以饲养的人当然很多。那么饲养金毛犬时要注意什么?一起来看看吧。
助跑器是田径运动必备的器材之一,类直三角形状,注意助跑器脚蹬立体感,让助跑器简笔画更具特色。接下来我们就通过助跑器儿童简笔画教学步骤图解来学如何画助跑器儿童简笔画。
怎么利用Photoshop给电商模特照片精修磨皮?很多朋友在工作中经常会遇到要求精修模特的情况,特别是做化妆品行业的电商设计师,所以总结了一下我的模特修图方法和技巧与大家分享,喜欢的朋友让我们一起来学习吧。
磨皮是我们ps照片最基本的技能,Photoshop人物磨皮是我们必须掌握的,如今不少国人对Photoshop修图的三大酷炫神技双曲线、中性灰与高低频几近痴迷,抓耳挠腮想学会它,下面一起看看教程吧。
掌握一点Photoshop教程对你是非常有用的,这篇教程是给大家分享PS简单快速创建眼睛彩虹美瞳效果方法,教程最终创建出来的效果非常漂亮,而且难度并不是很大,很值得大家学习,一起来学习吧。
2017年最受欢迎的生活服务APP!!生活服务类App的出现为日常生活带来极大便利,我们可以通过手机客户端预约各种家政服务,足不出户就能够享受实惠、便捷的生活服务,那么接下来我为大家推荐一些生活中必备生活app。
由于现在抢红包大热起来,很多app都开始支持发红包抢红包了,因此也出现了微信抢红包神器,可以自动抢微信红包,肯定比认为手动操作快,有消息就会自动打开,然后打开红包。今天就给大家分享2017微信自动抢红包神器大全。
2017手机赚钱软件排行榜!!很多朋友都在苦恼每天的钱不够话,空闲时间不知道怎么打发,总想寻找一种简单的赚钱方式,我们的手机app就有很多,下面具体给大家介绍手机赚钱软件有哪些,总有一款你中意的。
经常玩微信的朋友都知道,微信小程序已经全面上线了,对于小程序的出现是否会引发App变革众说纷纭,但不可否认的是小程序能够带给用户及产商一定的便利,那么今天为大家汇总目前上线的一些实用小程序。
男女交往一直都是人们比较关注的一个问题,都说相爱容易,相处不易,交往过的朋友应该都能深刻的体会到,女生常常抱怨着让男生理解自己,但男生也希望多体谅一下他们。尤其不要老是问一些无法回答的问题来考验他们。
很多朋友都信风水一说,对于自己家里房屋客厅的装修也是有一定要求的,因为客厅的风水关系着整个家居的运势,更关系着主人的财运与健康,因而客厅里的风水禁忌是需要我们谨慎注意的,那么风水学中客厅风水禁忌有哪些呢?
春天已经来临了,夏天也不远了,新的一才刚刚开始,时尚爱美的美眉们最关注的就是春夏服装设计的流行趋势了,早早的把握住时尚趋势走在流行的最尖端,今天就给大家整理分享2017春夏女装设计流行趋势 ,你绝对不能错过的亮点。查看: 7736|回复: 2
如何实现EXCEL表格在不同分辨率都能全屏显示
阅读权限20
在线时间 小时
在电脑分辨率为,制作一EXCEL表格模板,但用在别的不同分辨率电脑上,打开表格不是表格宽了显示不全,就是右边多出一部分空白,感觉不是美观,请教各位老师如何解决?加入VBA代码能自动调整显示为满屏?
阅读权限100
在线时间 小时
参考:vb界面自适应不同分辨率
vb界面自适应不同分辨率
现在宽屏,大屏幕显示器越来越普遍,原来在800*600下设计的软件界面,在大屏幕显示器()上界面总是缩到一角,非常难看,要将老程序的界面按照不同的分辨率在重新进行设计编程,整个过程比较复杂而且实用性不大,如果原来程序比较大且界面比较多的话那么工作量也将是巨大的,而且还可能出现其他错误,有没有一种重要增加少许代码就能将所有的界面自动适应不同的分辨率呢,在网上搜索了一下有很多现成的方法,但或多或少都有些问题,总之没有完美的解决方案,我经过研究找到了一种方法基本可以解决所有问题,与大家共享,当然该代码中所考虑的控件不完全,有些控件还需要特别处理,这个我在后面的常见问题说明里会提到,具体的代码需要你自己去添加。
代码如下:
1、新建一个模块(general.bas),在上面添加两个函数;
Public Type CONTROLRECT
& & Left As Single
& & Top As Single
& & Width As Single
& & Height As Single
Public Const HORZRES = 8
Public Const VERTRES = 10
Public Declare Function GetDesktopWindow Lib &user32& () As Long
Public Declare Function GetWindowDC Lib &user32& (ByVal hwnd As Long) As Long
Public Declare Function ReleaseDC Lib &user32& (ByVal hwnd As Long, ByVal hdc As Long) As Long
Public Declare Function GetDeviceCaps Lib &gdi32& (ByVal hdc As Long, ByVal nIndex As Long) As Long
'取得界面原始控件的位置及大小,并保存到数组里
Public Sub GetSourcePos(this As Object, rc() As CONTROLRECT, Optional bigFont As Boolean = True)
Dim tempX As Integer, tempY As Integer
tempX = this.ScaleWidth& &'1024
tempY = this.ScaleHeight&&'768
'此处原来如果在分辨率下显示正常的话,就可以直接赋值
Dim temp As Control
Dim nSum As Integer
For Each temp In this
&&'此处要注意,有些控件没有width,height等属性,在此要做出判断
&&If TypeOf temp Is ComboBox Then
& &With rc(nSum)
& & .Left = temp.Left / tempX
& & .Width = temp.Width / tempX
& & .Top = temp.Top / tempY
& &End With
'&&ElseIf TypeOf temp Is MSComm Then
'&&ElseIf TypeOf temp Is StatusBar Then
& & With rc(nSum)
& & .Left = temp.Left / tempX
& & .Width = temp.Width / tempX
& & .Top = temp.Top / tempY
& & .Height = temp.Height / tempY
& &End With
&&nSum = nSum + 1
'根据比例调整控件的大小
Public Sub SetNewPos(this As Object, rc() As CONTROLRECT)
& & Dim tempX As Integer, tempY As Integer
& & tempX = this.ScaleWidth&&'1024
& & tempY = this.ScaleHeight&&'768
'& & '如果初始界面显示始终是以最大化的方式显示的话,此处就可以调用系统分辨率进行设置tempx,tempy
'& & hwnd = GetDesktopWindow()
'& & ' Get the device context for the desktop
'& & hdc = GetWindowDC(hwnd)
'& & If hdc Then
'& && &&&Dim a As Long, b As Long
'& && &&&a = GetDeviceCaps(hdc, HORZRES)
'& && &&&b = GetDeviceCaps(hdc, VERTRES)
'& && &&&tempX = a
'& && &&&tempY = b
'& & End If
'& & ReleaseDC hwnd, hdc
& &&&Dim temp As Control&&'//用于取各种控件
& &&&Dim nSum As Integer
& &&&nSum = 0
& &&&For Each temp In this
& && &'此处要注意,有些控件没有width,height等属性,在此要做出判断
& && &If TypeOf temp Is ComboBox Then
& && &&&temp.Left = rc(nSum).Left * tempX
& && &&&temp.Width = rc(nSum).Width * tempX
& && &&&temp.Top = rc(nSum).Top * tempY
& & '&&ElseIf TypeOf temp Is MSComm Then
& & '& &'none
& & '&&ElseIf TypeOf temp Is StatusBar Then
& & '& &'none
& && &Else
& && &&&temp.Left = rc(nSum).Left * tempX
& && &&&temp.Width = rc(nSum).Width * tempX
& && &&&temp.Top = rc(nSum).Top * tempY
& && &&&temp.Height = rc(nSum).Height * tempY
& && &End If
& && & nSum = nSum + 1
2、在form窗体中定义如下变量
Dim oldpos() As CONTROLRECT
Private Sub Form_Load()
ReDim oldpos(Me.Controls.Count)
GetSourcePos Me, oldpos
Private Sub Form_Resize()
SetNewPos Me, oldpos
常见问题及解决:
(1)& &以上代码单纯的form窗体,根据窗口大小自动调整窗体控件时没有任何问题的,但是如果该窗体是mdi子窗体的话这种办法就会失灵,请看问题2;
(2)& &如果form是mdi子窗体的话怎么解决呢,将各个窗体的初始窗体啊全都设置为最大化窗体,然后根据分辨率的大小来调整窗体(上面代码中注释的部分,以固定比例来修改控件大小)。但是这样就缺少灵活性,不能随窗口的大小的改变而自动改变大小,大多数mdi程序,其子窗体都是最大化显示的,只跟系统分辨率有关;
(3)& &如果有line,shape等控件放在picture控件里,且picture控件的坐标模式在form_load期间又改变了,则这些控件在每次resize时其大小和位置也会相应的改变,这个问题的解决办法就是在每次resize之前将picture的scalemode改为pixel状态,(还有问题,改过之后定位可能不准确了);还有一个好办法,就是SetNewPos函数每次load后只调用一次。
(4)& &对于在form_load事件中就开始画图,并设置picture等控件的坐标时会出问题,设置的坐标为控件更改前的大小,而不是更改后的大小。
(5)& &发现sstab控件的兼容性有问题,修改大小后,点击sstab,隐藏界面无法显示,根据其特性(隐藏界面的控件位置left-75000)重新写函数进行处理。
阅读权限20
在线时间 小时
参考:vb界面自适应不同分辨率
求大师发一个适应任何分辨率的完整代码(一个工作薄很多张表格)
最新热点 /1
ExcelHome每周都有线上直播公开课,
国内一流讲师真身分享,高手贴身答疑,
赶不上直播还能看录像,
关键居然是免费的!
厚木哥们都已经这么努力了,
你还好意思说学不好Office。
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师c# GDI+简单绘图(一) - C#教程 - 编程入门网
c# GDI+简单绘图(一)
最近对GDI+这个东西接触的比较多,也做了些简单的实例,比如绘图板,仿QQ截图等.
最早接触这个类,是因为想做仿QQ截图的效果.巧的很,学会了如何做截图后,.NET课堂上老师也正巧要讲关于c#绘图方面的知识,并且我自己又在网上学习金老师的培训班,也是要用到这个类.在学习中有一些体会,所以准备把这些体会记下来,因为内容比较多,可能我会分几次写.
废话不多说了,我们先来认识一下这个GDI+,看看它到底长什么样.
GDI+:Graphics Device Interface Plus也就是图形设备接口,提供了各种丰富的图形图像处理功能;在C#.NET中,使用GDI+处理二维(2D)的图形和图像,使用DirectX处理三维(3D)的图形图像,图形图像处理用到的主要命名空间是System . Drawing:提供了对GDI+基本图形功能的访问,主要有Graphics类、Bitmap类、从Brush类继承的类、Font类、Icon类、Image类、Pen类、Color类等.
大概了解了什么是GDI+后,我们来看一下绘图要用到的主要工具,要画图,肯定要画板吧,在C#中画板可以通过Graphics这个类来创建,有了画板,总得弄个笔什么之类的吧,不然怎么画呀,难不成我们用手指画.笔又可以分好多种类,比如铅笔,画刷等.它们的区别主要是铅笔可以用来画线条,而画刷呢,嘿嘿,自己考虑下.在c#中我们可以用Pen,Brush类来实现类似功能.颜料则自然是用Color类了.
有了工具,我们就可以开始动手了!(所需命名空间:using System.D)
实现效果:在空白窗体中画基本图形
首先准备一个画板:
创建一个画板主要有3种方式:
A: 在窗体或控件的Paint事件中直接引用Graphics对象
B: 利用窗体或某个控件的CreateGraphics方法
C: 从继承自图像的任何对象创建Graphics对象
这次我们就先以A为例说明问题:
private void Form1_Paint(object sender, PaintEventArgs e)
      Graphics g = e.G //创建画板,这里的画板是由Form提供的.
然后,我们要只笔:
private void Form1_Paint(object sender, PaintEventArgs e)
      Graphics g = e.G //创建画板,这里的画板是由Form提供的.
      Pen p = new Pen(Color.Blue, 2);//定义了一个蓝色,宽度为的画笔
接下来我们就可以来画画了.
private void Form1_Paint(object sender, PaintEventArgs e)
      Graphics g = e.G //创建画板,这里的画板是由Form提供的.
      Pen p = new Pen(Color.Blue, 2);//定义了一个蓝色,宽度为的画笔
      g.DrawLine(p, 10, 10, 100, 100);//在画板上画直线,起始坐标为(10,10),终点坐标为(100,100)
      g.DrawRectangle(p, 10, 10, 100, 100);//在画板上画矩形,起始坐标为(10,10),宽为,高为
      g.DrawEllipse(p, 10, 10, 100, 100);//在画板上画椭圆,起始坐标为(10,10),外接矩形的宽为,高为
效果图如下:GDI+参考_文档资料库
GDI+ SDK 参考(翻译版本)序言 ............................................................................................................................................. - 4 目标...................................................................................................................................... - 4 适用范围.............................................................................................................................. - 4 适用读者.............................................................................................................................. - 4 运行环境.............................................................................................................................. - 4 文档组织.............................................................................................................................. - 4 相关主题.............................................................................................................................. - 4 GDI+的安全考虑 ........................................................................................................................ - 6 检验构造函数调用成功与否.............................................................................................. - 6 分配缓冲区.......................................................................................................................... - 6 错误校验.............................................................................................................................. - 7 线程同步.............................................................................................................................. - 9 相关主题............................................................................................................................ - 10 关于GDI+ .................................................................................................................................. - 11 GDI+ 介绍 ........................................................................................................................ - 11 GDI+ 概览 .............................................................................................................. - 11 GDI+ 的三个组成部分........................................................................................... - 11 基于类的接口架构.................................................................................................... - 12 GDI+提供了哪些新东西? .............................................................................................. - 12 新特征........................................................................................................................ - 12 编程模式的改变........................................................................................................ - 15 线条、曲线和图形............................................................................................................ - 19 矢量图概览................................................................................................................ - 19 钢笔、线条和矩形.................................................................................................... - 20 椭圆和弧.................................................................................................................... - 22 多边形........................................................................................................................ - 22 基数样条.................................................................................................................... - 23 贝塞尔样条................................................................................................................ - 24 路径............................................................................................................................ - 25 画刷和填充图形........................................................................................................ - 27 开放与闭合曲线........................................................................................................ - 29 区域............................................................................................................................ - 30 裁剪............................................................................................................................ - 31 路径平直化................................................................................................................ - 32 线条和曲线的抗锯齿功能........................................................................................ - 32 图象、位图和图元文件.................................................................................................... - 33 位图类型.................................................................................................................... - 34 图元文件.................................................................................................................... - 37 绘制、定位和复制图片............................................................................................ - 39 裁剪和缩放图象........................................................................................................ - 40 坐标系统和转换................................................................................................................ - 42 坐标系统类型............................................................................................................ - 42 -1- 以矩阵来表示转换.................................................................................................... - 44 全局和局部转换........................................................................................................ - 48 图形容器............................................................................................................................ - 51 使用GDI+ .................................................................................................................................. - 56 使用入门............................................................................................................................ - 56 绘制线条.................................................................................................................... - 56 绘制字符串................................................................................................................ - 58 使用钢笔绘制线条和形状................................................................................................ - 59 使用钢笔绘制线条和矩形........................................................................................ - 59 设置钢笔的宽度和对齐方式.................................................................................... - 60 绘制具有线帽的线条................................................................................................ - 61 联接线条.................................................................................................................... - 62 绘制自定义虚线........................................................................................................ - 62 绘制用纹理填充的线条............................................................................................ - 63 使用画笔填充形状............................................................................................................ - 63 用纯色填充形状........................................................................................................ - 64 用阴影图案填充形状................................................................................................ - 64 用图像纹理填充形状................................................................................................ - 64 在形状中平铺图像.................................................................................................... - 65 用渐变色填充形状.................................................................................................... - 68 使用图像、位图和图元文件............................................................................................ - 68 加载和显示位图........................................................................................................ - 68 加载和显示图元文件................................................................................................ - 69 记录图元文件............................................................................................................ - 69 剪裁和缩放图像........................................................................................................ - 71 旋转、反射和扭曲图像............................................................................................ - 72 缩放时使用插值模式控制图像质量........................................................................ - 73 创建缩略图像............................................................................................................ - 75 采用高速缓存位图来提高性能................................................................................ - 76 通过避免自动缩放改善性能.................................................................................... - 76 读取图像元数据........................................................................................................ - 77 使用图像编码器和解码器................................................................................................ - 83 列出已安装的编码器................................................................................................ - 83 列出已安装的解码器................................................................................................ - 84 获取解码器的类标识符............................................................................................ - 86 获取编码器的参数列表............................................................................................ - 88 将BMP图像转换为PNG图像................................................................................. - 100 设定JPEG的压缩等级............................................................................................ - 101 对JPEG图像进行无损变换 .................................................................................... - 102 创建和保存多帧图像.............................................................................................. - 105 从多帧图像中复制单帧.......................................................................................... - 107 Alpha 混合线条和填充 .................................................................................................. - 109 绘制不透明和半透明的线条.................................................................................. - 109 用不透明和半透明的画笔绘制.............................................................................. - 110 --2- 使用复合模式控制 Alpha 混合........................................................................... - 111 使用颜色矩阵设置图像中的 Alpha 值............................................................... - 112 设置单个象素的alpha值....................................................................................... - 114 使用字体和文本.............................................................................................................. - 115 构造字体系列和字体.............................................................................................. - 115 绘制文本.................................................................................................................. - 116 格式化文本.............................................................................................................. - 117 枚举已安装的字体.................................................................................................. - 120 创建专用的字体集合.............................................................................................. - 122 获取字体规格.......................................................................................................... - 126 对文本使用消除锯齿效果...................................................................................... - 130 构造并绘制曲线.............................................................................................................. - 131 绘制基数样条曲线.................................................................................................. - 131 绘制贝塞尔样条...................................................................................................... - 133 用渐变画刷填充形状...................................................................................................... - 134 创建线性渐变.......................................................................................................... - 134 创建路径渐变.......................................................................................................... - 137 将 Gamma 校正应用于渐变 .............................................................................. - 144 构造并绘制路径.............................................................................................................. - 145 使用线条、曲线和形状创建图形.......................................................................... - 145 填充开放式图形...................................................................................................... - 147 使用图形容器.................................................................................................................. - 147 管理 Graphics 对象的状态 ................................................................................ - 148 使用嵌套的 Graphics 容器 ................................................................................ - 151 变换.................................................................................................................................. - 154 使用世界变换.......................................................................................................... - 154 为什么变换顺序非常重要...................................................................................... - 155 使用区域.......................................................................................................................... - 156 对区域使用点击检测.............................................................................................. - 156 对区域使用剪辑...................................................................................................... - 157 对图像重新着色.............................................................................................................. - 158 使用颜色矩阵对单色进行变换.............................................................................. - 158 转换图像颜色.......................................................................................................... - 160 缩放颜色.................................................................................................................. - 161 旋转颜色.................................................................................................................. - 164 剪取颜色.................................................................................................................. - 166 使用颜色重映射表.................................................................................................. - 168 打印.................................................................................................................................. - 169 将GDI+输出至打印机........................................................................................... - 169 显示一个打印对话框.............................................................................................. - 172 通过提供打印机句柄优化打印.............................................................................. - 173 附录:GDI+ 参考 .................................................................................................................. - 176 --3- 序言目标 Microsoft Windows GDI+是为 C/C++开发者提供的一个基于类的应用程序编程接口(API)。它 使得程序可以同时在视频显示器和打印机上使用图形和格式化文本。 基于 Microsoft Win32 的应用程序不 能直接访问图形硬件,而是通过 GDI+来协调设备驱动和程序动作的交互。GDI+同样支持 Microsoft Win64。 适用范围 GDI 适用于所有的 Window 应用程序。GDI+是包含于 Windows XP 和 Windows Server 2003 中的一项新技术。运行于 Microsoft Windows NT 4.0 SP6、Windows 2000、Windows 98 和 Windows Me 操作系统的应用程序在分发的时候需要包含 GDI+。 适用读者 GDI+ C++ 基类接口是为 C/C++开发者所设计。需要精通 Windows 图形用户接口和消息驱动机 制。 运行环境 Gdiplus.dll包含在Windows XP中。某些特定的类和方法可能需要特定操作系统的支持,请参阅文 档中相应的类和方法。GDI+可以在Windows NT 4.0 SP6、 Windows 2000、 Windows 98 以及 Windows Me操作系统中重新分发部署。下载最新的可重新分发安装包,参见: /msdownload/platformsdk/sdkupdate/psdkredist.htm .注意:如果您将 GDI+分发到低版本系统平台或者该平台本身不包含该版本的 GDI+,则将 Gdiplus.dll 安装到您的应用程序目录下。这样将它放到了您自己的地址空间下,但是您应该使用/BASE 连接器选项重 构基地址,避免地址空间冲突。 文档组织 GDI+参考文档采用下面表格所示进行组织: 关于 GDI+的概要信息。 使用 GDI+的任务和例子。 GDI+ C++基类 API 参考文档。概览 用法 参考 相关主题Windows GDI DirectX-4- Windows Image Acquisition OpenGL Windows Multimedia-5- GDI+的安全考虑本主题提供关于采用 Microsoft Windows GDI+进行开发的安全考虑。本主题没有提供所有您想了 解的安全性相关主题DD取而代之,我们将它作为本技术领域的出发点和基准。 检验构造函数调用成功与否 很多 GDI+类提供一个 Image::GetLastStatus 方法,您可以调用它检测某个对象的方法调用是否 成功。您也可以调用 GetLastStatus 来判断构造函数是否成功调用。 下面的例子展示了如何构造一个 Image 对象并且调用 GetLastStatus 方法来判断构造成功与否。 返回值 OK 和 InvalidParameter 是 Status 枚举的成员。 Image myImage(L&Climber.jpg&); Status st = myImage.GetLastStatus();if(Ok == st) // The constructor was successful. Use myImage. else if(InvalidParameter == st) // The constructor failed because of an invalid parameter. else // Compare st to other elements of the Status // enumeration or do general error processing. 分配缓冲区 有几个 GDI+方法采用调用者分配的缓冲区来返回数字或者字符数据。 其中每个方法都有一个关联方 法来提供所需缓冲区的大小。例如,GraphicsPath::GetPathPoints 方法返回一个 Point 对象数组。在 您调用 GetPathPoints 之前, 您必须分配足够大的缓冲区来容纳这个数组。 而您可以调用 GraphicsPath 对象的 GetPointCount 方法来计算所需缓冲区的大小。 下面的例子展示了如何判断一个 GraphicsPath 对象的点数, 并分配足够大的缓冲区来容纳这些点, 然后调用 GetPathPoints 方法来填充该缓冲区。在调用 GetPathPoints 的代码之前,需要检测缓冲 区分配是否成功,方法是看缓冲区指针是否不等于 NULL。 GraphicsP path.AddEllipse(10, 10, 200, 100);INT count = path.GetPointCount(); Point* pointArray = new Point[count];// get the size // allocate the bufferif(pointArray) {// Check for successful allocation.-6- path.GetPathPoints(pointArray, count); ... delete[] pointA pointArray = NULL; }// get the data// use pointArray // release the buffer前面的例子采用 New 操作符分配缓冲区。采用 New 操作符非常方便,因为缓冲区是由明确类型的 Point 对象所构成。有些时候,GDI+写入比 GDI+对象数组更多的信息到缓冲区。有时缓冲区在填入 GDI+对象数组的同时还通过这些对象的成员来指向额外的数据信息。例如,Image:: GetAllPropertyItems 方法返回一个 PropertyItem 对象数组,每个属性项目(一段元数据)都存储在图 象中。 但是 GetAllPropertyItems 返回的信息不止这些对象数组; 它还为这些数组追加了额外的数据。 在您调用 GetAllPropertyItems 之前,您必须为对象数组以及这些附加数据分配足够大的空间。 您可以调用 Image 对象的 GetPropertySize 方法来判断所需缓冲区的总大小。 下面的例子展示了如何创建一个 Image 对象, 然后调用该对象的 GetAllPropertyItems 方法来 获取所有存储于图象中的属性项目(元数据)。该代码采用 GetPropertySize 方法返回的大小值来分配 缓冲区。GetPropertySize 同时返回一个数值,表示该 Image 中的属性项目的数量。需要注意的是, 这里没有采用 count*sizeof(PropertyItem)来计算缓冲器大小。显然,采用这种方法计算出来的值太小 了。 UINT count = 0; UINT size = 0; Image myImage(L&FakePhoto.jpg&); myImage.GetPropertySize(&size, &count);// GetAllPropertyItems returns an array of PropertyItem objects // along with additional data. Allocate a buffer large enough to // receive the array and the additional data. PropertyItem* propBuffer =(PropertyItem*)malloc(size);if(propBuffer) { myImage.GetAllPropertyItems(size, count, propBuffer); ... free(propBuffer); propBuffer = NULL; } 错误校验 GDI+参考中的大部分例子代码都没有进行错误校验。因为完整的错误校验将会使得示例代码变得更 大,使得例子本身想要阐述的要点变得模糊。您不应该直接把文档中的例子代码粘贴到您的产品代码中使 用;您应该适当的加入您自己的错误校验代码来增强该代码。-7- 下面的代码展示了实现 GDI+错误校验的方法。每次一旦某个 GDI+对象被构造,代码都将检查该构 造函数是否成功。该检查对于 Image 的构造函数而言尤其重要,因为它依赖于对一个文件的读取。如果 所有四个 GDI+对象(Graphics, GraphicsPath, Image, and TextureBrush)均成功构造,代码才 可以调用这些对象的方法。每个方法调用也要检测是否成功,一旦发生错误,剩下的方法调用将被略过。 Status GdipExample(HDC hdc) { Status status = GenericE INT count = 0; Point* points = NULL;Graphics graphics(hdc); status = graphics.GetLastStatus(); if(Ok != status)GraphicsP status = path.GetLastStatus(); if(Ok != status)Image image(L&MyTexture.bmp&); status = image.GetLastStatus(); if(Ok != status)TextureBrush brush(&image); status = brush.GetLastStatus(); if(Ok != status)status = path.AddEllipse(10, 10, 200, 100);if(Ok == status) { status = path.AddBezier(40, 130, 200, 130, 200, 200, 60, 200); }if(Ok == status) { count = path.GetPointCount(); status = path.GetLastStatus(); }if(Ok == status) -8- { points = new Point[count];if(NULL == points) status = OutOfM }if(Ok == status) { status = path.GetPathPoints(points, count); }if(Ok == status) { status = graphics.FillPath(&brush, &path); } if(Ok == status) { for(int j = 0; j & ++j) { status = graphics.FillEllipse( &brush, points[j].X - 5, points[j].Y - 5, 10, 10); } }if(points) { delete[] points = NULL; } } 线程同步 有可能采用超过一个线程来访问同一 GDI+对象。然而,GDI+对象并不具备自动同步的机制。因此 如果您的应用程序中有 2 个线程具有指向同一个 GDI+对象的指针的话,同步存取该对象就是您自己的责 任了。 如果一个线程试图调用某对象的一个方法,而此时另一个线程正在同一个对象上执行一个方法,此时 有些 GDI+方法会返回 ObjectBusy。不要在返回 ObjectBusy 值的时候试图同步访问。可行的是,每 次您访问该对象的某个成员或者调用它的某个方法的时候,将这些调用放到某个临界区段中,或者采用其 他的标准同步技术。 -9- 相关主题 MSDN Library Security Home Page Security How-To Resources TechNet Security Resources- 10 - 关于 GDI+Microsoft Windows GDI+是 Windows XP 操作系统或者 Windows 2003 操作系统的一部分,它 提供二维矢量图形、图象和排版。GDI+由 Windows 图象设备接口(GDI,包含于较早版本的 Windows 中的图形设备接口)演化而来,加入了新的特性的同时优化了现有特性。以下主题提供了有关采用 C++开发语言进行 GDI+应用程序开发接口(API)的信息。 GDI+ 介绍 Microsoft Windows GDI+是一个图形设备接口,它允许开发者创建设备无关的应用程序。GDI+ 服务通过一组的 C++类实现。 GDI+ 概览 Microsoft Windows GDI+ 是 Windows XP 和 Windows Server 2003 操作系统的子系统,它负 责在屏幕和打印机上显示信息。GDI+是一个应用程序编程接口(API),它由一组 C++类实现。 顾名思义,GDI+是对于 GDI 的继承,后者包含于早期的 Windows 版本中。Windows XP 或者 Windows Server 2003 支持 GDI 以保持对现有程序的兼容性, 但是编写新程序的开发者应该使用 GDI+ 来实现他们所有的图形需求,因为 GDI+不仅优化了大部分 GDI 性能而且提供了更多特性。 一个图形设备接口,比如 GDI+,允许应用程序开发者将信息显示在显示器或者打印机上,而无需考 虑该显示设备的详细情况。应用程序开发者调用 GDI+类所提供的方法,而这些方法又依次适当的调用特 定设备驱动程序。GDI+使得应用程序和图形硬件隔离开来,得益于此,开发者因而可以创建设备无关的 应用程序。 GDI+ 的三个组成部分 Microsoft Windows GDI+服务分为以下 3 个主要部分:?二维矢量图形 矢量图形由图元(比如线条、曲线和图形)组成,它们由一系列坐标系统的点集组成。例如,一条直线可以由它的两个端点所确定,一个矩形可以通过给出它的左上角点的位置加上它的宽度、高度来确定。 一个简单的路径可以由一个由直线连接而成的点数组来描述。一条贝塞尔样条是一个由 4 个控制点所描述 的高级曲线。 GDI+提供了用于存储这些图元本身信息的类、如何绘制这些图元信息的类以及实际绘制这些图元的 类。例如,Rect 类存储一个矩形的尺寸位置;Pen 类存储线条颜色、线条宽度以及线条样式等信息;而 Graphics 类则提供绘制线条、矩形、路径和其他图形的方法。同时,有几个 Brush 类还用于存储有关闭 合图形和路径内部填充颜色和图案的信息。- 11 - ?图象 某些图片很难或者不可能采用矢量图形技术来显示。比如,工具栏按钮图片和图标就很难通过一系列线条和曲线来描述。一张拥挤的棒球馆的高分辨率的数码照片更难采用矢量技术来创建。这种类型的图象 采用位图进行存储,即由表示屏幕上独立点的颜色的数字型数组所组成。用于存储位图信息的数据结构往 往比矢量图形要复杂的多,因此出于此种原因 GDI+中提供了好几种类。类似的类比如 CachedBitmap, 用于存储一张内存图片,供快速存取和显示用。?排版 排版关系到多种字体、尺寸和样式文字的显示。GDI+提供给人深刻印象数量的对这项复杂的任务的支持。新的特性中包括了子象素抗锯齿功能,它使得在液晶显示屏上可以显示更加平滑的显示文本。 基于类的接口架构 Microsoft Windows GDI+包含大约 40 个类、50 个枚举和 6 个结构体。同时也有少数几个函数不 属于任何类。Graphics 类是整个 GDI+接口的核心;它是实际进行线条、曲线、图形、图象和文本绘制 的类。 多数类和 Graphics 类配合使用。 例如, Graphics::DrawLine 方法接受一个点传给一个 Pen 对象, 该对象保存了即将绘制的线条的属性(颜色、宽度、虚线类型及其他)。Graphics::FillRectangle 方法 接受一个点传给 LinearGradientBrush 对象,该对象协同 Graphics 对象实现矩形的渐变色填充。Font 和 StringFormat 对象影响到 Graphics 对象绘制文本的方式。Matrix 对象用于存储和生成一个 Graphics 对象的世界变换矩阵,用于旋转、缩放和翻转图象。 有些类是主要用作数据类型结构体。这些类中大多数(例如 Rect、Point 和 Size 类)用于普通目的。 其他的则用于特殊目的,被看作是辅助类。例如,BitmapData 类是 Bitmap 类的辅助类,PathData 类 是 GraphicsPath 类的辅助类。GDI+同时定义了少数几个结构体用于组织数据。例如,ColorMap 结构 体存储一对颜色对象,构成了一个颜色转换表的入口项目。 GDI+定义了数个枚举常量,它们是相关常数的集合。例如,LineJoin 枚举包含了 LineJoinBevel, LineJoinMiter 和 LineJoinRound 几个元素,表示两根线条的连接方式。 GDI+提供了少数几个不属于任何类的函数。 其中的 2 个是 GdiplusStartup 和 GdiplusShutdown。 您必须在进行任何 GDI+调用之前调用 GdiplusStartup,在您结束 GDI+调用的时候调用 GdiplusShutdown。 GDI+提供了哪些新东西? Microsoft Windows GDI+ 不同于 GDI 体现在 2 个方面。第一,GDI+通过提供新的功能扩展了 GDI 的特性,比如渐变画刷和半透明混合。第二,编程模型的改进使得图形开发更加简单和灵活。 新特征 下面将阐述 Microsoft Windows GDI+的几个新特征:- 12 - ?渐变画刷 GDI+扩展了 GDI 提供线性渐变和路径渐变画刷,用于填充图形、路径和区域。渐变画刷也可用于绘制线条、曲线和路径。当您采用线性渐变画刷填充图形的时候,颜色将在穿越该图形时逐渐改变。例如, 假设您创建了一个水平渐变画刷,同时指定左边缘为蓝色、右边缘为绿色。当您采用水平渐变画刷填充图 形时,颜色将从它的左边到右边逐渐由蓝色过渡到绿色。同样地,一个垂直渐变画刷填充的图形的颜色将 自上而下渐变。下面两幅插图显示了一个水平渐变画刷填充的椭圆和一个对角渐变画刷填充的区域。如果您采用路径渐变画刷填充图形,您可以有许多选择来指定颜色从图形的一个区域到另一个区域的 如何过渡。一种选择就是设置一个中心颜色和边界颜色,这样图形由内向外象素颜色将逐渐改变。下图显 示的是一个由路径渐变画刷填充的路径(由一对贝塞尔样条所创建)。?基数样条 GDI+支持基数样条, GDI 不支持。 而 基数样条是一组单个曲线按照一定的顺序连接而成的一条较大曲线。样条由一系列点指定,并通过每一个指定的点。由于基数样条平滑地穿过组中的每一个点(不出现 尖角),因而它比用直线连接创建的路径更精确。下面是分别使用两种方法创建的图形,一个使用基数样 条,一个使用直线。- 13 - ?独立的路径对象 在 GDI 中,一条路径是属于一个设备场景的,在绘制完成后就被销毁了。在 GDI+中,绘图工作由Graphics 对象来完成,您可以创建和保留几个与 Graphics 独立的 GraphicsPath 对象。绘图操作时GraphicsPath 对象不被破环,这样您就可以多次使用同一个 GraphicsPath 对象画路径了。?变形和矩阵对象 GDI+提供了矩阵对象,一个非常强大的工具,使得图形变换(旋转、平移等)变得轻松灵活。一个矩阵对象总是和一个图形变换相联系起来。比方说,GraphicsPath 对象有一个 Transform 方法,它的一 个参数能够接受 Matrix 对象的地址。单个 3×3 矩阵可以存储一个变形或者一系列变形。下图是一个图形 变换前后的例子,变换按照先缩放后旋转完成。?可伸缩区域 GDI+ 在对区域的支持上对 GDI 进行了很大的改进。在 GDI 中,区域存储在设备坐标中,唯一可进行的图形变换的操作是平移。而 GDI+用世界坐标存储区域,允许对区域进行任何图形变换(例如缩放), 图形变换以变换矩阵存储。下图显示的是经过连续 3 个变换前后的一个区域(缩放、旋转、平移):?alpha 混合 请注意上图中,您可以通过变换后的区域(阴影填充)看到变换前的区域(红色填充)。这种效果可以通过 GDI+支持的α混合来实现。利用α混合,您可以指定填充颜色的透明度。透明色将与背景色混合- 14 - ― 填充色越透明,背景色显示越清晰。下图所示的四个椭圆被填充了同样的颜色(红色),但由于拥有不同的透明度而呈现不同的显示效果。?多种图像格式支持 GDI+提供了 Image、Bitmap 和 Metafile 类,用于载入、保存和处理多种格式的图形。以下格式均支持: BMP Graphics Interchange Format (GIF) JPEG Exif PNG TIFF ICON WMF EMF 编程模式的改变 下面将阐述采用 GDI+编程与 GDI 的几个方面的不同之处:?设备场景、句柄和 Graphics 对象 如果您曾经使用过GDI编写过 应用程序,您肯定对设备场景(DC)的概念非常熟悉。设备场景是Windows使用的一个 数据结构,用于存储具体设备性能和与如何在设备上绘制项目的相关信息。而且视 频显示器的设备场景还与显示器上的特定窗口有关。首先您必须获得一个设备场景句柄(HDC),然后在 图形绘制时您把这个句柄作为一个参数传递给GDI函数。当然您也可以把它传递给获得或设置设备场景有 关属性的函数。 您在使用 GDI+的时候, 您不必像在 GDI 中那样关心设备场景句柄。 您只需简单地创建一个 Graphics 对象,然后以您熟悉的面向对象的方式(比如 myGraphicsObject.DrawLine(parameters))调用它的 方法即可。Graphics 对象是 GDI+的核心,正如设备场景是 GDI 的核心一样。设备场景(DC)和图形 对象(Graphics)在不同的环境下扮演着同样的角色,发挥着类似的作用,但是两者也存在着本质的不同。 前者使用基于句柄的编程模型而后者使用面向对象的编程模型。- 15 - Graphics 对象和设备场景一样,与屏幕上的特定窗体有关,它包含着图形绘制的有关属性信息(比 如,平滑模式和隐式文本渲染)。然而,Graphics 对象并没有像 GDI 那样与 Pen、Path、Image 或者 Font 等搅在一起。比如,在 GDI 中,您必须先调用 SelectObject 将一个 Pen 对象与设备场景关联,然 后您才能使用设备场景绘制一条线。这被称为将画笔选入设备场景。您在设备场景中绘制的所有线条都将 采用这个画笔直到您选择另一个画笔为止。 GDI+中, 在 您只需将一个 Pen 对象作为参数传递给 Graphics 类的 DrawLine 方法即可。 您可以在一连串的 DrawLine 调用中传入不同的 Pen 对象, 而不必将给定的 Pen 对象与 Graphics 对象关联。?画线的 2 种方法 下面两个例子都是从位置(20, 10)到位置(200,100)绘制一条宽度为 3 的红色线条。前一个例子采用 GDI 调用,第二个例子通过 C++类接口调用 GDI+。o Drawing a line with GDI采用 GDI 画线, 您需要 2 个对象: 设备场景和画笔。 您通过调用 CreatePen 获取一个句柄。 紧接着, 您调用 SelectObject 将画笔选入设备场景。然后调用 MoveToEx 将画笔位置设为(20,10),然后调用 绘制一条直线到位置(200,100)。注意 MoveToEx 和 LineTo 均需要一个 hdc 作为参数。 HDCPAINTSTRUCT HPEN HPEN hP hPenOhdc = BeginPaint(hWnd, &ps); hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); hPenOld = (HPEN)SelectObject(hdc, hPen); MoveToEx(hdc, 20, 10, NULL); LineTo(hdc, 200, 100); SelectObject(hdc, hPenOld); DeleteObject(hPen); EndPaint(hWnd, &ps);o 采用 GDI+和 C++类接口画线通过 GDI+和 C++类接口画线,您需要一个 Graphics 对象和一个 Pen 对象。注意您不需要向这 些对象提供窗体句柄。 相反, 您只需要构造一个 Graphics 类 (一个 Graphics 对象) 和一个 Pen 类 (一 个 Pen 对象)即可。画线涉及 Graphics 类的 Graphics::DrawLine 方法。Graphics::DrawLine 方法的第一个参数是一个 Pen 对象的指针。较之前面将 Pen 选入设备场景的 GDI 例子,这种方案更加更 加简单灵活。 HDCPAINTSTRUCT Pen* Graphics* myP myGhdc = BeginPaint(hWnd, &ps); myPen = new Pen(Color(255, 255, 0, 0), 3); - 16 - myGraphics = new Graphics(hdc); myGraphics-&DrawLine(myPen, 20, 10, 200, 100); delete myG delete myP EndPaint(hWnd, &ps);?钢笔、画刷、路径、图形和字体作为参数 前面的例子说明了 Pen 对象可以独立于 Graphics 对象被创建和保留,该对象提供具体绘图方式。同样地,画刷、图形路径、图象和字体对象可以独立于 Graphics 对象被创建和保留。Graphics 类提供 的许多绘图方法都接受 Brush、GrpahicsPath、Image 或者 Font 对象作为参数之一。例如,一个 Brush 对象的地址作为参数传递给 FillRectangle 方法,而一个 GraphicsPath 对象的地址作为参数传 递给 DrawPath 方法。类似地,Image 和 Font 对象的地址传递给 DrawImage 和 DrawString 方法。 这与 GDI 中需要先选入一个画刷、路径、图象或者字体到指定设备场景,然后再将设备句柄作为参数传递 给绘图函数的方法相比形成了强烈对比。?方法重载 许多 GDI+方法被重载了;也就是说,存在不同的方法,它们拥有相同的函数名和不同的参数列表。例如,Graphics 类的 DrawLine 方法有以下几种形式: Status DrawLine(IN const Pen* pen, IN REAL x1, IN REAL y1, IN REAL x2, IN REAL y2); Status DrawLine(IN const Pen* pen, IN const PointF& pt1, IN const PointF& pt2); Status DrawLine(IN const Pen* pen, IN INT x1, IN INT y1, IN INT x2, IN INT y2); Status DrawLine(IN const Pen* pen, IN const Point& pt1, IN const Point& pt2); 所有上面 DrawLine 方法的四种变体都接受一个 Pen 对象指针、起点坐标和终点坐标。前两个方 法接受浮点数字型的坐标参数,而后面两个方法接受整数类型的坐标参数。第一个和第三个方法接受由数 字分隔开的坐标;第二个和第四个方法接受由一对 Point(或者 PointF)对象表示的坐标。?不再有当前位置- 17 - 注意,前面显示的 DrawLine 方法同时提供了线段的起点和终点作为参数。不同的是,在 GDI 中您 必须先设置当前位置然后才能绘制一个起于(x1, y1)终于(x2, y2)的线段。GDI+中已经完全摒弃了当前 位置的概念。?绘图与填充方法分离 在绘制图形比如矩形的边框和填充其内部区域方面,GDI+比 GDI 更加灵活。GDI 有个 Rectangle函数可以一步实现绘制矩形和填充其内部区域。边框采用当前选入的画笔绘制,内部区域采用当前选入的 笔刷填充。 hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 0, 255)); hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); SelectObject(hdc, hBrush); SelectObject(hdc, hPen); Rectangle(hdc, 100, 50, 200, 80); 在 GDI+中,绘制矩形边框和填充其内部区域的方法是独立开来的。Graphics 类的 DrawRectangle 方法有一个参数,用于传入 Pen 对象的地址。而 FillRectangle 方法有一个参数,用 于传入 Brush 对象的地址。 HatchBrush* myHatchBrush = new HatchBrush( HatchStyleCross, Color(255, 0, 255, 0), Color(255, 0, 0, 255)); Pen* myPen = new Pen(Color(255, 255, 0, 0), 3); myGraphics.FillRectangle(myHatchBrush, 100, 50, 100, 30); myGraphics.DrawRectangle(myPen, 100, 50, 100, 30); 注意,GDI+中 FillRectangle 和 DrawRectangle 方法的参数指定矩形的左、上、宽度和高度。 相对地,在 GDI 的 Rectangle 函数中,参数指定的是矩形的左、右、上、下。同时还要注意,GDI+中 的 Color 类的构造函数有 4 个参数。后面的 3 个参数就是通常的红、绿、蓝的值;第一个参数指定的是α 半透明值,它表示该颜色与背景色混合的程度。?构造区域 GDI 提供了几个函数可以创建区域: CreateRectRgn、 CreateEllpticRgn、 CreateRoundRectRgn、CreatePolygonRgn 和 CreatePolyPolygonRgn。您可能也期望 GDI+中的 Region 类提供类似的构造 函数,传入矩形、椭圆、圆角矩形和多边形作为参数,但是情况并非如此。在 GDI+中,Region 类提供 一个传入 Rect 对象引用的构造函数,和另一个传入 GraphicsPath 对象地址的构造函数。如果您想创 建一个基于椭圆、圆角矩形或者多边形的区域,您可以很容易地通过创建一个 GraphicsPath 对象(包 含椭圆等),然后将 GraphicsPath 对象的地址传递给 Region 构造函数即可。 在 GDI+中可以很简单地通过图形和路径的组合创建一个复杂的区域。Region 类有 Union 和 Intersect 方法,用于加入一个路径或者另一个区域到一个已有区域中。GDI+中一个很好的特性是,当一 个 GraphicsPath 对象作为 Region 构造函数的参数传入的时候,它本身并不会被销毁。而在 GDI 中,- 18 - 您可以通过 PathToRegion 函数将一个路径转换为一个区域,但是同时路径也被销毁了。同样地, GraphicsPath 对象在其地址作为 Union(合并)和 Intersect(相交)方法的参数传入时本身也不 会被销毁,因此您可以将一个指定的路径作为一个组成部分来创建几个独立的区域。下面例子中,假设 onePath 是一个 GraphicsPath 对象(简单抑或复杂)的指针并且已经被初始化: Region region1(rect1); Region region2(rect2); region1.Union(onePath); region2.Intersect(onePath); 线条、曲线和图形 GDI+的矢量图部分用于绘制线条、绘制曲线,绘制和填充图形。 矢量图概览 Microsoft Windows GDI+在一个坐标系统中绘制线条、矩形和其他图形。您可以选择各种不同的 坐标系统,但是默认的坐标系统规定其左上角位置为起点,X 轴指向右边、Y 轴之指向下边。默认坐标系 统的度量单位是象素(Pixel)。电脑显示器在一个矩形点阵上创建其显示画面,这些点称为图片要素或者象素。不同的显示器其在屏 幕上显示的点数不尽相同,并且通常一个独立显示器其显示的象素总数可以由用户进行调节。在您采用 GDI+绘制线条、矩形和曲线的时候,您需要提供一些关于绘制对象的关键性信息。例如, 您可以通过 2 点确定一条线段,您可以通过一个点、高度和宽度确定一个矩形。GDI+与显示器驱动程序- 19 - 协同工作,来判断哪个象素应该开启用于显示线条、矩形和曲线。下面所示,显示一条从点(4, 2)到点(12, 8)的线条的象素情况。总的来说,某些基本的构成块已经证明是最对建立二维图形非常有用。这些基本构成块,GDI+均支 持,包括:o Lines (线条) o Rectangles (矩形) o Ellipses (椭圆) o Arcs (弧形) o Polygons (多边形) o Cardinal splines (基数样条) o Bézier splines (贝塞尔样条)GDI+中的 Graphics 类提供这些方法来绘制前面列表中的对象:DrawLine、DrawRectangle、 DrawEllipse、DrawPolygon、DrawArc、DrawCurve (用于基数样条)和 DrawBezier。每个方法都已 被重载;也就是说,每种方法都以不同参数列表的变体出现。例如,DrawLine 方法的一个变体接受一个 Pen 对象的地址和四个整型值,而它的另一个变体则接受一个 Pen 对象地址和两个 Point 对象引用。 绘制线条、矩形和贝塞尔样条的方法都有其复数形式的伴随方法,这些方法在一次调用中绘制多个项 目:DrawLines、DrawRectangles 和 DrawBeziers。同样地,DrawCurve 方法也有一个伴随方法 DrawClosedCurve,该函数通过连接曲线的起点和终点创建一个闭合图形。 所有的 Graphics 类的方法都得配合 Pen 对象使用。因此,为了绘制任何东西,您必须至少创建 2 个对象:一个 Graphics 对象和一个 Pen 对象。Pen 对象存储诸如线条宽度、颜色等绘图属性。Pen 对象的地址将作为一个参数传递给绘图方法。 例如, 一个 DrawRectangle 方法的变体需要传入一个 Pen 对象地址和 4 各整数值作为参数,该方法绘制一个左上角为(20,10)、宽度为 100、高度为 50 的矩形。 myGraphics.DrawRectangle(&myPen, 20, 10, 100, 50); 钢笔、线条和矩形 采用 GDI+绘制线条需要一个 Graphics 对象和一个 Pen 对象。 Graphics 对象提供实际的绘图方法, 而 Pen 对象存储线条属性, 例如颜色、 宽度和样式等。 绘制线条只需要简单调用 Graphics 对象的 DrawLine 方法即可。Pen 对象的地址作为参数之一传递给 DrawLine 方法。下面的例子是绘制一条从点(4, 2)到点 (12, 6)的线段。- 20 - myGraphics.DrawLine(&myPen, 4, 2, 12, 6); DrawLin 是一个在 Graphics 类中被重载的方法,因此您可以提供几种不同的参数。例如,您可以构 造 2 个 Point 对象,然后将这 2 个 Point 对象的引用作为参数传递给 DrawLine 方法。 Point myStartPoint(4, 2); Point myEndPoint(12, 6); myGraphics.DrawLine(&myPen, myStartPoint, myEndPoint); 您也可以在构造 Pen 对象时给它的属性赋值。例如,有个 Pen 的构造函数允许您指定颜色和宽度。 下面的例子是从点(0, 0)到点(60, 30)绘制一条宽度为 2 的蓝色线段。 Pen myPen(Color(255, 0, 0, 255), 2); myGraphics.DrawLine(&myPen, 0, 0, 60, 30); Pen 对象同样有自己的属性,例如虚线样式,您可以用来指定线条特征。例如,下面的例子用于绘制 一条从点(100, 50)到点(300, 80)的虚线。 myPen.SetDashStyle(DashStyleDash); myGraphics.DrawLine(&myPen, 100, 50, 300, 80); 您可以使用 Pen 对象的多种方法来设置更多的线条属性。SetStartCap 和 SetEndCap 方法指定线 条末端的表现形式;线帽可以为扁平、方块、圆角、三角或者用户定义形状。SetLineJoin 方法允许您设 置线条间的联接方式是斜接(有明显边角)、斜切、圆或者裁剪。下图显示的是具有不同的端点类型和连 接方式的线条。绘制矩形的方法和画线的方法相似。绘制一个矩形,您需要一个 Graphics 对象和一个 Pen 对象。 Graphics 对象提供一个 DrawRectangle 方法,而 Pen 对象存储输入线条宽度和颜色等属性。Pen 对象 的地址作为参数之一传递给 DrawRectangle 方法。下面的例子是绘制一个左上角为(100,50)、宽度为 80、高度为 40 的矩形。 myGraphics.DrawRectangle(&myPen, 100, 50, 80, 40); DrawRectangle 是一个在 Graphics 类中被重载的方法,因此也有几种不同传递参数的方式。例如, 您可以先构造一个 Rect 对象然后将 Rect 对象的引用作为参数之一传递给 DrawRectangle 方法。 Rect myRect(100, 50, 80, 40); myGraphics.DrawRectangle(&myPen, myRect);- 21 - Rect 对象的某些方法可以控制和收集矩形的有关信息。例如,Inflate 和 Offset 方法可以改变矩形 的尺寸和位置。IntersectsWith 方法告诉您一个矩形是否和另一个矩形交叉了,Contains 方法则告诉您 指定的点是否在一个矩形内部。 椭圆和弧 一个椭圆由它的外接矩形来描述。下图显示了一个椭圆和它的外接矩形。绘制一个椭圆,您需要一个 Graphics 对象和一个 Pen 对象。Graphics 对象提供 DrawEllipse 方法,Pen 对象存储诸如线条宽度和颜色等信息。Pen 对象的地址作为参数之一传递给 DrawEllipse 方 法。传递给 DrawEllipse 方法其余的参数指定其外接矩形。下面的例子将绘制一个椭圆;其外接矩形宽 度为 160、高度为 80,左上角位置为(100,50)。 myGraphics.DrawEllipse(&myPen, 100, 50, 160, 80); DrawEllipse 是一个在 Graphics 类中被重载的方法,因此也有几种不同传递参数的方式。例如, 您可以先构造一个 Rect 对象然后将 Rect 对象的引用作为参数之一传递给 DrawEllipse 方法。 Rect myRect(100, 50, 160, 80); myGraphics.DrawEllipse(&myPen, myRect); 弧是椭圆的一部分。绘制弧形,您需要调用 Graphics 类的 DrawArc 方法。DrawArc 方法的参数 和 DrawEllipse 方法的参数一样,除此之外还需要提供起始角和扫描角。下面的例子绘制一条弧形,其 起始角为 30 度,扫描角为 180 度。 myGraphics.DrawArc(&myPen, 100, 50, 160, 80, 30, 180); 下图同时显示了弧形、椭圆与外接矩形。多边形 多边形是由 3 个或 3 个以上的直边所组成的闭合图形。例如,三角形就是 3 条边所组成,矩形由 4 条边组成,五角星由 5 条边所组成。下图显示了几种不同的多边形。- 22 - 绘制多边形,您需要一个 Graphics 对象,一个 Pen 对象,以及一个 Point(或者 PointF)对象 数组。Graphics 对象提供 DrawPolygon 方法,Pen 对象存储多边形的线条宽度和颜色等信息,Point 对象数组则存储相连直线的点集。Pen 对象的地址和 Point 对象数组作为参数传递给 DrawPolygon 方法。下面的例子将绘制一个 3 条边的多边形。 注意在 myPointArray 中只有 3 个点:(0, 0)、 (50, 30) 和 (30, 60)。DrawPolygon 方法自动绘制从(30, 60)返回点(0, 0)的线条使该多边形闭合。 Point myPointArray[] = {Point(0, 0), Point(50, 30), Point(30, 60)}; myGraphics.DrawPolygon(&myPen, myPointArray, 3); 下图显示了该多边形。基数样条 基数样条是一组单个曲线按照一定的顺序连接而成的一条较大曲线。样条由一个点数组和一个张力参 数描述。由于基数样条平滑地穿过数组中的每一个点;在曲线的密度上不会不出现锐角和突变。下图显示 一组点和穿过它们每个点的基数样条。物理样条是一小片木头或者其他柔性材质做成的。在数学样条诞生之前,设计人员采用物理样条来绘 制曲线。它们将样条置于纸上然后定位一系列锚点,然后用铅笔沿着样条绘制曲线。给出的一系列点可能 产生不同的曲线,这取决于物理样条的性质。例如,与一个极其易弯曲的样条相比,有较高的抗弯能力的 一个样条将生产一条不同的曲线。 数学样条的公式基于柔性杆的特性, 因此数学样条生产的曲线类似于曾经由物理样条生产的曲线。 正如物理样条通过给定的一组点时在不同的张力下的将生成一条不同的曲线一样, 数学样条在张力参数不 同的时候也将生成不同的曲线。下图显示了通过相同一组点集的 4 条基数样条。每条样条都标注了它的张- 23 - 力参数。注意张力系数为 0 的情况下相当于无限的物理张力,迫使曲线走点之间的最短路径(直线)。张力 系数为 1 表示没有物理张力,此时样条采用最小弯程。如果张力系数大于 1,此时的样条看起来就像被压 扁的弹簧,被迫经过更长的路径。需要注意的是,以上 4 条样条在顶点处都拥有相同的切线。切线表示从一个起始点沿曲线指向下一个 点间的直线。同样的,终点共享的切线表示从终点开始的沿曲线曲线指向前一个点。 绘制一条基数样条,您需要一个 Graphics 对象,一个 Pen 对象和一个 Point 对象数组。Graphics 对象提供 DrawCurve 方法用于绘制基数样条, Pen 对象存储诸如线条宽度和颜色等信息, Point 对象数 组存储曲线经过的点集。下面的例子将绘制一条基数样条,它穿过 myPointArray 点集。第三个参数是张力 参数。 myGraphics.DrawCurve(&myPen, myPointArray, 3, 1.5f); 贝塞尔样条 贝塞尔样条是由 4 个点所确定的曲线:2 个端点(p1 和 p2)和 2 个控制点(c1 和 c2)。曲线始于 p1 终于 p2。曲线并不经过控制点,但是控制点扮演了磁铁的角色,将曲线往某个方向拉从而影响了曲线的走 向。下图显示了贝塞尔样条和它的顶点以及控制点。注意,曲线从 p1 开始向控制点 c1 移动。P1 位置的切线是从 p1 到 c1。同时请注意,终点 p2 处的 切线是从 c2 到 p2 的。 绘制贝塞尔样条,您需要一个 Graphics 对象和一个 Pen 对象。Graphics 对象提供 DrawBezier 方 法,而 Pen 对象存储诸如线条宽度和颜色等信息。Pen 对象的地址作为参数之一传递给 DrawBezier 方 法。DrawBezier 方法余下的参数传入顶点和控制点。下面的例子将绘制一条贝塞尔样条,它的起点为 (0,0),控制点为(40,20)和(80,150),终点为(100,10)。 myGraphics.DrawBezier(&myPen, 0, 0, 40, 20, 80, 150, 100, 10);- 24 - 下图显示该曲线、控制点和两条切线。贝塞尔样条最初由 Pierre Bézier 在汽车工业设计中发明。它被证明对于多种类型的计算机辅助设计 非常有用,同时还用于定义字体轮廓。贝塞尔样条可以产生多种形状,下图罗列了其中一些:路径 路径由线条、矩形以及简单曲线等组合而成。回顾矢量图形概念部分,以下基本构成块被证明对于绘 制图象非常有用。 Lines (线条) Rectangles (矩形) Ellipses (椭圆) Arcs (弧线) Polygons (多边形) Cardinal splines (基数样条) Bézier splines (贝塞尔样条) 在 GDI+中, GraphicsPath 对象允许您将这些基本组成部分组合成一个单独的单位。 整个一组线条、 矩形、多边形和曲线可以通过 Graphcis 类的 DrawPath 方法一次性绘制。下图显示的是一条有线条、弧 线、贝塞尔样条以及基数样条所组成的路径。- 25 - GraphicsPath 类提供如下方法用于创建一系列对象:AddLine、AddRectangle、AddEllipse、 AddArc、AddPolygon、AddCurve (用于基数样条)以及 AddBezier。它们中的每个方法都已被重载; 也就是说,您可以传入不同的参数列表。例如,AddLine 方法的变体之一需要传入 4 个整形值,而另外一 个变体则需要传入 2 个 Point 对象。 添加线条、矩形和贝塞尔样条的方法都有其复数形式的伴随方法,这些方法在一次调用中添加多个项 目:AddLines、AddRectangles 和 AddBeziers。同样地,AddCurve 方法也有一个伴随方法 AddClosedCurve,该函数通过连接曲线的起点和终点添加一个闭合曲线。 绘制一条路径, 您需要一个 Graphcis 对象, 一个 Pen 对象和一个 GraphicsPath 对象。 Graphics 对象提供方法。Pen 对象存储诸如线条宽度和颜色等信息。GraphicsPath 对象存储线条、矩形和曲线 序列用以构成一条路径。Pend 对象和 GracphisPath 对象的地址作为参数传给 DrawPath 方法。下面的 例子将绘制一条路径,它由一根线条、一个椭圆和一条贝塞尔样条组成。 myGraphicsPath.AddLine(0, 0, 30, 20); myGraphicsPath.AddEllipse(20, 20, 20, 40); myGraphicsPath.AddBezier(30, 60, 70, 60, 50, 30, 100, 10); myGraphics.DrawPath(&myPen, &myGraphicsPath); 下图所示为该路径:除了添加线条、矩形和曲线到路径外,您还可以添加路径到路径。这允许您将已有路径组合为更大更 复杂的路径。下面的代码将 graphicsPath1 和 graphicsPath2 加入到 myG

我要回帖

更多关于 gdi图形程序设计 pdf 的文章

 

随机推荐