现在的位置: 首页 > 综合 > 正文

图形和 Windows 窗体

2014年02月25日 ⁄ 综合 ⁄ 共 26868字 ⁄ 字号 评论关闭

图形和 Windows 窗体

介绍 GDI+

公共语言运行库使用 Windows 图形设备接口 (GDI) 的高级版本,其名称为 GDI+。GDI+ 旨在提供良好的性能和易用性。它支持二维图形、版式和图像。

新的二维功能包括下列内容:

  • 对所有图形基元的 Alpha 混合支持
  • 消除锯齿
  • 渐变填充和纹理填充
  • 宽线
  • 基数样条
  • 可缩放区域
  • 浮点坐标
  • 复合线
  • 嵌入钢笔
  • 高质量的筛选和缩放
  • 大量的线型和笔尖选项

图像支持包括下列内容:

  • 对图像文件格式(如 .jpeg、.png、.gif、.bmp、.tiff、.exif 和 .icon)的本机支持
  • 用于编码和解码任意光栅图像格式的公共接口
  • 用于动态添加新图像文件格式的可扩展结构
  • 对通用点操作(如亮度、对比度、色彩平衡、模糊和溶解)的本机图像处理支持。对通用转换(如旋转、裁切等)的支持。

颜色管理

对 sRGB、ICM2 和 sRGB64 的支持

版式支持包括下列内容:

  • 本机 ClearType 支持
  • 纹理填充和渐变填充的文本
  • 在所有平台上对 Unicode 的完全支持
  • 对所有 Windows 2000 脚本的支持
  • Unicode 3.0 标准的更新
  • 文本行服务支持,可使文本更具可读性

GDI+ 可与 Windows 窗体和 Web 窗体一起使用。例如,Web 窗体控件可使用基于用户输入的 GDI+ 动态生成 .jpeg 文件,并从 Web 页引用它。

本节集中讨论 Windows 窗体。

GDI 和 GDI+ 之间的差异

本节的目的是帮助您了解使用 GDI+ 的基础知识。开始之前,有必要指出 GDI 和 GDI+ 之间的最大差异。GDI 具有有状态的编程模型,而 GDI+ 具有无状态的编程模型。使用 GDI,可在绘图表面上设置属性(如前景色和背景色),然后在它上面进行绘制。例如,若要绘制黑色文本字符串,代码有点类似于下面的示例。



Dim g as Graphics
g.ForeColor = Color.Black
g.BackColor = Color.White
g.Font = new Font("Times New Roman", 26)
g.DrawString("Hello, World", 0, 0)
C# VB  

 

使用 GDI+ 时,始终将要使用的属性作为绘图命令的一部分传递。上面的代码更改为如下所示。

Dim g As Graphics;
Dim foreColor As Color = Color.Black;
Dim backColor As Color = Color.White;
Dim vbFont As New Font("Times New Roman", 26);
g.FillRectangle(New SolidBrush(backColor), ClientRectangle);
g.DrawString("Hello World", vbFont, New SolidBrush(foreColor), 15, 15);
C# VB  

 

GDI+ 命名空间

GDI+ 类驻留于 System.DrawingSystem.Drawing.Drawing2DSystem.Drawing.ImagingSystem.Drawing.Text 命名空间中。这些命名空间包含在程序集 System.Drawing.DLL 中。

创建图形对象

GDI+ 绘图表面由 Graphics 类表示。为了使用 GDI+,首先需要一个对图形对象的引用。通常,在控件或窗体的 Paint 事件中或者在

可以通过为 Paint 事件创建事件处理程序来处理该事件。

Public Class GdiPlusDemo : Inherits Form

    Public Sub New()
        ' Hook the paint event of the form.
        AddHandler Me.Paint, AddressOf form1_Paint
    End Sub

    Private Sub form1_Paint(sender As Object, pe As PaintEventArgs)
        Dim g As Graphics = pe.Graphics

        ' Simply fill a rectangle with red.
        g.FillRectangle(New SolidBrush(Color.Red), 40, 40, 140, 140)
    End Sub
End Class
C# VB  

 

更常用的是,可以创建 OnPaint 方法的子类并重写该方法。

Public Class GdiPlusDemo : Inherits Form

   Public Sub New()
   End Sub

   Protected Overrides Sub OnPaint(pe As PaintEventArgs)
        Dim g As Graphics = pe.Graphics
        g.FillRectangle(New SolidBrush(Color.Red), 40, 40, 140, 140)
   End Sub
End Class
C# VB  

 

还可以从 Image 的任何派生类创建 Graphics 对象实例。

Dim newBitmap As Bitmap = New Bitmap(600,400,PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(newBitmap)
g.FillRectangle(New SolidBrush(Color.Red), 40, 40, 140, 140)
newBitmap.Save("c:/temp/TestImage.jpg", ImageFormat.Jpeg)
C# VB  

 

创建 Graphics 对象后,可以使用它绘制线、填充形状、绘制文本等。与 Graphics 对象一起使用的主要对象如下所示。

Brush

用于使用图案、颜色或位图填充封闭表面。

Pen

用于绘制线和多边形,包括矩形、弧线和扇形。

Font

用于描述用来呈现文本的字体。

Color

用于描述用来呈现特定对象的颜色。在 GDI+ 中,颜色可以是 Alpha 混合效果的。

Alpha 混合

颜色可以是 Alpha 混合的,这使得易于创建基于颜色叠加的效果。例如,下面的示例绘制一个红色矩形,然后在不遮掩底层的红色矩形的情况下叠加一个黄色矩形。

 

Dim g As Graphics = pe.Graphics
g.FillRectangle(new SolidBrush(Color.Red), 600, 350, 100, 100)
g.FillRectangle(new SolidBrush(Color.FromArgb(180, Color.Yellow)), 650, _
                               400, 100, 100)
C# VB  

 

使用画笔

使用画笔填充形状和路径的内部。例如,若要创建红色矩形,请参见下面的示例。

 

Dim g As Graphics = pe.Graphics
g.FillRectangle(new SolidBrush(Color.Red), 600, 350, 100, 100)
C# VB  

 

画笔可以是纯色的、带阴影的、带纹理的或渐变的。阴影画笔只不过是使用图案进行绘画的画笔。

Dim g As Graphics = pe.Graphics
HatchBrush hb = new HatchBrush(HatchStyle.ForwardDiagonal, Color.Green, _
                               Color.FromArgb(100, Color.Yellow))
g.FillEllipse(hb, 250, 10, 100, 100)
C# VB  

 

带纹理的画笔使用位图绘画。例如,下面的代码使用纹理画笔绘制窗体的背景,然后对它应用白色"冲洗"以冲淡位图中颜色的色调。

Dim g As Graphics = pe.Graphics
Dim colorbars As Image = new Bitmap("colorbars.jpg")
Dim backgroundBrush As Brush = new TextureBrush(colorbars)
g.FillRectangle(backgroundBrush, ClientRectangle)
g.FillRectangle(new SolidBrush(Color.FromArgb(180, Color.White)), ClientRectangle)
C# VB  

 

LinearGradientBrush 使用两种颜色绘画。它根据在画笔上设置的属性填充给定的形状,逐渐从一种颜色过渡到另一种颜色。例如,可以用下面所示代码创建下列填充效果。

Dim r As Rectangle = new Rectangle(500, 300, 100, 100);
Dim lb As LinearGradientBrush = new LinearGradientBrush(r, Color.Red, Color.Yellow, _
                                                       LinearGradientMode.BackwardDiagonal);
e.Graphics.FillRectangle(lb, r);
C# VB  

 

PathGradient 画笔允许创建更复杂的效果,如下列形状。

它是用下面的代码创建的。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(backgroundBrush, ClientRectangle)
    e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(180, Color.White)), ClientRectangle)

    Dim path As New GraphicsPath(New Point() { _
        New Point(40, 140), _
        New Point(275, 200), _
        New Point(105, 225), _
        new Point(190, 300), _
        new Point(50, 350), _
        new Point(20, 180), _
        }, New Byte() { _
            CType(PathPointType.Start, Byte), _
            CType(PathPointType.Bezier, Byte), _
            CType(PathPointType.Bezier, Byte), _
            CType(PathPointType.Bezier, Byte), _
            CType(PathPointType.Line, Byte), _
            CType(PathPointType.Line, Byte), _
            })

    Dim pgb As New PathGradientBrush(path)
    pgb.SurroundColors = new Color() { _
        Color.Green, _
        Color.Yellow, _
        Color.Red, _
        Color.Blue, _
        Color.Orange, _
        Color.White, _
    }

    e.Graphics.FillPath(pgb, path)
End Sub
C# VB  

 

VB 画笔示例

[运行示例] | [查看源代码]

使用钢笔

使用钢笔绘制直线和曲线。可以设置属性,如 PenTypeDashStyleWidthColorEndCap,以控制 Pen 如何进行绘制。

下面的代码绘制一条曲线。

Dim g As Graphics
' Create a pen 20 pixels wide that is and purple and partially transparent.
Dim penExample As New Pen(Color.FromArgb(150, Color.Purple), 20)
' Make it a dashed pen.
Dim penExample.DashStyle As Pen = DashStyle.Dash
' Make the ends round.
Dim penExample.StartCap As Pen = LineCap.Round
Dim penExample.EndCap As Pen= LineCap.Round

' Now draw a curve using the pen
g.DrawCurve(penExample, New Point() { _
            New Point(200, 140), _
            New Point(700, 240), _
            New Point(500, 340), _
            New Point(140, 140), _
            New Point(40, 340), _
})
C# VB  

 

还可以使用带纹理的画笔将纹理用作钢笔的填充效果。

Dim g As Graphics
Dim textureBrush As New TextureBrush(New Bitmap("Boiling Point.jpg"))
Dim penExample As New Pen(textureBrush, 25)
penExample.DashStyle = DashStyle.DashDotDot
penExample.StartCap = LineCap.Triangle
penExample.EndCap = LineCap.Round
g.DrawLine(penExample, 10,450,550,400)
C# VB  

 

VB 笔示例

[运行示例] | [查看源代码]

绘制文本

Graphics 对象的 DrawString 方法在绘图表面上呈现文本。将要使用的字体和颜色传递给 DrawString 方法。例如,下面的代码使用窗体的字体和黑色画笔显示文本"Hello World"。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    Dim g As Graphics = e.Graphics
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)
    g.DrawString("Hello World", Me.Font, New SolidBrush(Color.Black), 10,10)
End Sub
C# VB  

 

因为 DrawString 采用画笔,所以可以使用任何画笔呈现文本。其中包括纹理画笔。例如,下面的代码呈现具有大理石效果和背景阴影的文本。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    Dim titleBrush As New TextureBrush(New Bitmap("marble.jpg"))
    Dim backgroundBrush As New TextureBrush(New Bitmap("colorbars.jpg"))
    Dim titleShadowBrush As New SolidBrush(Color.FromArgb(70, Color.Black))
    Dim titleFont As New Font("Lucida Sans Unicode", 60)
    Dim titleText As String = "Graphics  Samples"

    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(backgroundBrush, ClientRectangle)
    e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(180, Color.White)), ClientRectangle)

    e.Graphics.DrawString(titleText, titleFont, titleShadowBrush, 15, 15)
    e.Graphics.DrawString(titleText, titleFont, titleBrush, 10, 10)

End Sub
C# VB  

 

如果提供带有 RectangleDrawString,则文本将换行以适合该矩形。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)

    Dim textFont As New Font("Lucida Sans Unicode", 12)
    Dim rectangle As New RectangleF(100, 100, 250, 350)
    e.Graphics.FillRectangle(New SolidBrush(Color.Gainsboro), rectangle)
    Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
        & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
        & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
        & "language runtime." & ControlChars.CrLf _
        & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
        & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
        & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
        & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
        & "written in Windows Forms." & ControlChars.CrLf _
        & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
        & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
        & "control and container classes. This significantly reduces" & ControlChars.CrLf _
        & "control-container interoperability issues." & ControlChars.CrLf
    e.Graphics.DrawString(flowedText, textFont, New SolidBrush(Color.Blue), rectangle)
End Sub
C# VB  

 

可以使用 StringFormat 对象控制如何绘制文本。例如,下面的代码使您得以绘制在特定区域内居中的文本。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)

    Dim textFont As New Font("Lucida Sans Unicode", 8)
    Dim rectangle As New RectangleF(100, 100, 250, 350)
    e.Graphics.FillRectangle(new SolidBrush(Color.Gainsboro), rectangle)
    Dim format As New StringFormat()
    format.Alignment = StringAlignment.Center
    Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
        & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
        & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
        & "language runtime." & ControlChars.CrLf _
        & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
        & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
        & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
        & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
        & "written in Windows Forms." & ControlChars.CrLf _
        & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
        & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
        & "control and container classes. This significantly reduces" & ControlChars.CrLf _
        & "control-container interoperability issues." & ControlChars.CrLf
    e.Graphics.DrawString(flowedText, textFont, New SolidBrush(Color.Blue), rectangle,format)
End Sub
C# VB  

 

如果要在绘制字符串时确定该字符串的长度,可使用 MeasureString。例如,若要将某个字符串在窗体上居中显示,请使用下面的代码。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(new SolidBrush(Color.White), ClientRectangle)

    Dim textToDraw As String ="Hello Symetrical World"

    Dim textFont As New Font("Lucida Sans Unicode", 8)
    Dim windowCenter As Double = this.DisplayRectangle.Width/2
    Dim stringSize As SizeF = e.Graphics.MeasureString(textToDraw, textFont)
    Dim startPos As Double = windowCenter-(stringSize.Width/2)

    e.Graphics.DrawString(textToDraw, textFont, new SolidBrush(Color.Blue), startPos, 40)
End Sub
C# VB  

 

MeasureString 还可用于确定呈现多少行和多少个字符。例如,我们可以确定在上一个讨论过的文本示例中呈现多少行和多少个字符。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(new SolidBrush(Color.White), ClientRectangle)

    Dim textFont As New Font("Lucida Sans Unicode", 12)
    Dim rectangle As New RectangleF(100, 100, 250, 350)
    Dim lines As Integer
    Dim characters As Integer
    Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
        & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
        & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
        & "language runtime." & ControlChars.CrLf _
        & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
        & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
        & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
        & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
        & "written in Windows Forms." & ControlChars.CrLf _
        & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
        & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
        & "control and container classes. This significantly reduces" & ControlChars.CrLf _
        & "control-container interoperability issues." & ControlChars.CrLf
    Dim whatRenderedText As String

    e.Graphics.FillRectangle(New SolidBrush(Color.Gainsboro), rectangle)

    e.Graphics.MeasureString(flowedText, textFont, rectangle.Size, _
                    new StringFormat(), characters, lines)
    whatRenderedText = "We printed " & characters & " characters and " & lines & " lines"

    e.Graphics.DrawString(flowedText, textFont, New SolidBrush(Color.Blue), rectangle)

    e.Graphics.DrawString(whatRenderedText, Me.Font, New SolidBrush(Color.Black), 10,10)
End Sub
C# VB  

 

GDI+ 完全支持 Unicode。这意味着可以用任何语言呈现文本。例如,下面的代码用日语绘制字符串(必须安装有日语语言包)。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(new SolidBrush(Color.White), ClientRectangle)

    Try
        Dim japaneseFont As New Font("MS Mincho", 32)
        Dim japaneseText As New String(new char() {CType(31169, Char), CType(12398, Char), _
                    CType(21517, Char), CType(21069, Char), CType(12399, Char), _
                    CType(12463, Char), CType(12522, Char), CType(12473, Char), _
                    CType(12391, Char), CType(12377, Char), CType(12290, Char)})
        e.Graphics.DrawString(japaneseText, japaneseFont, new SolidBrush(Color.Blue), 20, 40)
    Catch ex As Exception
         MessageBox.Show("You need to install the Japanese language pack to run this sample")
         Application.Exit()
    End Try
End Sub
C# VB  

 

VB 文本示例

[运行示例] | [查看源代码]

使用图像

GDI+ 完全支持各种图像格式,包括 .jpeg、.png、.gif、.bmp、.tiff、.exif 和 .icon 文件。

呈现图像非常简单。例如,下面的代码呈现一个 .jpeg 图像。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)
    e.Graphics.DrawImage(New Bitmap("sample.jpg"), 29, 20, 283, 212)
End Sub
C# VB  

 

使用位图作为呈现图面也非常简单。下面的代码将一些文本和线呈现到位图上,然后将该位图作为 .png 文件保存到磁盘中。

Dim newBitmap As New Bitmap(800,600,PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(newBitmap)
g.FillRectangle(New SolidBrush(Color.White), new Rectangle(0,0,800,600))

Dim textFont As New Font("Lucida Sans Unicode", 12)
Dim rectangle As New RectangleF(100, 100, 250, 350)
Dim Lines As Integer
Dim Characters As Integer
Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
    & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
    & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
    & "language runtime." & ControlChars.CrLf _
    & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
    & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
    & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
    & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
    & "written in Windows Forms." & ControlChars.CrLf _
    & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
    & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
    & "control and container classes. This significantly reduces" & ControlChars.CrLf _
    & "control-container interoperability issues." & ControlChars.CrLf

g.FillRectangle(new SolidBrush(Color.Gainsboro), rectangle)
g.DrawString(flowedText, textFont, new SolidBrush(Color.Blue), rectangle)
Dim penExample As New Pen(Color.FromArgb(150, Color.Purple), 20)
penExample.DashStyle = DashStyle.Dash
penExample.StartCap = LineCap.Round
penExample.EndCap = LineCap.Round
g.DrawCurve(penExample, new Point() { _
            new Point(200, 140), _
            new Point(700, 240), _
            new Point(500, 340), _
            new Point(140, 140), _
            new Point(40, 340), _
})

newBitmap.Save("TestImage.png", ImageFormat.Png)
C# VB  

 

VB 图像示例

[运行示例] | [查看源代码]

其他信息
标准钢笔和画笔

PenBrush 类包括一组用于所有已知颜色的标准纯色钢笔和画笔。

消除锯齿

Graphics.SmoothingMode 设置为 SmoothingMode.AntiAlias 将导致更锐化的文本和图形。

图形对象的范围

Paint 事件的参数 (PaintEventArgs) 中包含的图形对象根据 Paint 事件处理程序的返回结果进行处置。因此,不应保持对范围超出 Paint 事件之外的此 Graphics 对象的引用。尝试在 Paint 事件之外使用此 Graphics 对象将出现不可预知的结果。

处理调整大小

默认情况下,当调整控件或窗体大小时不引发 Paint 事件。如果希望在调整窗体大小时引发 Paint 事件,则需要相应地设置控件样式。

Public Sub MyForm()
    SetStyle(ControlStyles.ResizeRedraw,True)
End Sub
C# VB  

 

转自 http://www.gotdotnet.com/

PrintDocumentPrintPage 事件中获取对图形对象的引用。

抱歉!评论已关闭.