分享

一些关于GDI+的文字——编程模式的变化

 shaolong007 2005-11-22
标  题: 一些关于GDI+的文字——编程模式的变化
发信站: 浙江大学海纳百川站 (Tue Oct 26 11:54:19 2004), 转信

设备上下文、句柄和图形对象

如果您使用过 GDI(Windows 的以前版本中包括的图形设备接口)编写程序,就会熟悉
设备上下文的知识。设备上下文是 Windows 使用的一种结构,用于存储与特殊显示设备
的功能和指定如何在该设备上绘制项目的属性相关的信息。用于视频显示的设备上下文
还与显示的特定窗口关联。首先,您获得一个设备上下文的句柄 (HDC),然后将该句柄
作为参数传递至实际进行绘制的 GDI 函数。您还可将此句柄作为参数传递给获取或设置
设备上下文属性的 GDI 函数。

使用 GDI+,您不需要再使用句柄或设备上下文,而是只需创建一个 Graphics 对象,然
后在您熟悉的面向对象样式 myGraphicsObject.DrawLine(参数)中调用其方法。正如
设备上下文位于 GDI 的核心,Graphics 对象也位于 GDI+ 的核心。设备上下文和 Gra
phics 对象的作用相似,但在使用设备上下文 (GDI) 的、基于句柄的编程模式和使用G
raphics 对象 (GDI+) 的、面向对象的编程模型之间存在一些基本的差异。
Graphics 对象(像设备上下文一样)与屏幕上的特定窗口关联,并具有指定如何绘制项
目的属性(例如,SmoothingMode 和 TextRenderingHint)。但是,Graphics 对象不受
钢笔、画笔、路径、图像或字体的约束,这与设备上下文不同。例如,使用设备上下文
绘制线条之前,必须先调用 SelectObject 以使钢笔对象和设备上下文关联。这是指将
钢笔选入设备上下文中。在设备上下文中绘制的所有线条均使用该钢笔,直到您选择另
一支不同的钢笔为止。在 GDI+ 中,将 Pen 对象作为参数传递给 Graphics 类的 Draw
Line 方法。您可以在一系列 DrawLine 调用的每个调用中使用不同的 Pen 对象,而不
必使给定的 Pen 对象与 Graphics 对象关联。

绘制线条的两种方法

下面每个示例都在位置 (20, 10) 和位置 (200, 100) 之间绘制了一条宽为 3 的红色线
条。第一个示例调用 GDI,第二个示例通过托管类接口调用 GDI+。
使用 GDI 绘制线条

要使用 GDI 绘制线条,需要两个对象:设备上下文和钢笔。先获得设备上下文句柄;通
过调用CreatePen,则可以获得 直示浔O乱 步,调用 SelectObject 以将钢笔选入设
备上下文。调用MoveToEx,将钢笔位置设在 (20, 10),然后调用 LineTo,在钢笔位置
与位置 (200, 100) 之间绘制一条线条。请注意,MoveToEx 和 LineTo 均将 hdc(设备
上下文的句柄)作为参数接收。

使用 GDI+ 和托管类接口绘制线条

下面的示例是用 C++ 编写的,但用任何能产生托管代码的语言都可以编写这些示例。要
使用 GDI+ 和托管类接口绘制线条,您需要 Graphics 对象和 Pen 对象。获取 Graphi
cs 对象引用的一种方法是通过窗体的 OnPaint 方法。OnPaint 方法的一个参数是类型
PaintEventArgs 的结构,它将 Graphics 对象作为其成员。
绘制线条涉及调用 Graphics 类的 DrawLine 方法。DrawLine 方法的第一个参数是 Pe
n 对象。与前面 GDI 示例中显示的技术(将钢笔选入设备上下文)相比,这是一个更加
简单而灵活的方案。

      Pen* myPen = new Pen(Color(255, 0xff, 0, 0), 3);
      Graphics myGraphics(hDC);
      myGraphics.DrawLine(myPen, 20, 10, 200, 100);

作为参数的钢笔、画笔、路径、图像和字体

前面的示例显示:创建和维护 Pen 对象可以与提供绘制方法的 Graphics 对象分开。创
建和维护 Brush、GraphicsPath、Image 和 Font 对象也可以与 Graphics 对象分开。
Graphics 类提供的许多绘制方法都将 Brush、GraphicsPath、Image 或 Font 对象作为
参数接收。例如,Brush 对象作为参数传递至 FillRectangle 方法,GraphicPath 对象
作为参数传递至 DrawPath 方法。同样,Image 和 Font 对象传递至 DrawImage 和 Dr
awString 方法。这与 GDI 不同,在 GDI 中,需要将画笔、路径、图像或字体选入设备
上下文,然后将设备上下文的句柄作为参数传递至绘制函数。

无当前位置

请注意,前面所述的 DrawLine 方法中显示:线条的起点和终点均被作为参数接收。这
与 GDI 方案不同,在 GDI 中,调用 MoveToEx(hdc, x1, y1, NULL) 来设置当前钢笔位
置之后,再调用 LineTo(hdc, x2, y2) 以绘制一条从 (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(
        HatchStyleHorizontal,
        Color(255, 0, 255, 0),
        Color(255, 0, 0, 255));
     Pen* myPen = new Pen(Color.FromArgb(255, 255, 0, 0), 3);
     myGraphics.FillRectangle(myHatchBrush, 100, 50, 100, 30);
     myGraphics.DrawRectangle(myPen, 100, 50, 100, 30);

请注意,GDI+ 中的 FillRectangle 和 DrawRectangle 方法接收指定矩形左边缘、上边
缘、宽和高的参数。这与 GDI 的 Rectangle 函数不同,Rectangle 函数接收指定矩形
左边缘、右边缘、上边缘和下边缘的参数。另请注意,GDI+ 中 Color 类的 FromArgb
方法有四个参数。后三个参数是常见的红色、绿色和蓝色值。第一个参数是 alpha 值,
它指定所绘制颜色与背景颜色的混合程度。

构造区域

GDI 提供几种用于创建区域的函数:CreateRectRgn、CreateEllpticRgn、CreateRound
RectRgn、CreatePolygonRgn 和 CreatePolyPolygonRgn。您或许希望 GDI+ 中的 Regi
on 类也有类似的构造函数,将矩形、椭圆、圆角矩形和多边形作为参数接收,但事实并
非如此。GDI+ 中的 Region 类提供一个接收 Rectangle 对象的构造函数和另一个接收
GraphicsPath 对象的构造函数。如果您想基于椭圆、圆角矩形或多边形构造区域,可
以通过创建一个 GraphicsPath 对象(例如包含椭圆的对象),然后将其传递至 Regio
n 构造函数来轻松实现。

GDI+ 通过组合图形和路径,使得构成复杂区域十分简单。Region 类具有 Union 和 In
tersect 方法,可用于扩展具有路径的现有区域或其他区域。GDI+ 方案一个很好的功能
就是 GraphicsPath 对象在作为参数传递至 Region 构造函数时不会被破坏(在 GDI 中
,可以使用 PathToRegion 函数将路径转换为区域,但在此过程中,路径将被破坏)。
另外,GraphicsPath 对象在作为参数传递给 Union 或 Intersect 方法时也不会被破坏
,因此,在一些单独的区域中,您可以将给定的路径作为构造块使用。该过程如下例所
示。假定 onePath 是一个已初始化的 GraphicsPath 对象(简单或复杂)。

     Region* region1 = new Region(rect1);
     Region* region2 = new Region(rect2);
     region1->Union(onePath);
     region2->Intersect(onePath);

--
        ■■■■■■■■■■■■■■■■■■■■■■■■ 
          这个世界只有10种人,懂二进制的和不懂二进制的
        ■■■■■■■■■■■■■■■■■■■■■■■■
                jackyang@cs.zju since 2001

※ 来源:·浙江大学海纳百川站 bbs.zju.edu.cn·[FROM: jackyang]

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多