C# GDI+ 繪制圖像


原文:http://cs.cqut.edu.cn/NetTeachPlatform/Chapter8.htm

 

8 繪制圖像

本章要求掌握用GDI+繪制直線、圓、長方形等圖形,在第七章的基礎上編寫一個類似於畫圖圖像圖形處理程序

8.1 繪圖所用到的常用控件及類

繪圖用到的PictureBoxImage, Bitmap, OpenFileDialog,SaveFileDialog等控件或類在前一章已經進行了講解。現對所用的其它控件或類進行說明。

8.1.1 顏色

在繪制圖形時需要指定使用的顏色,在GDI+中,顏色用System.Drawing.Color 結構來表示的。

1 紅綠藍(RGB)

監視器可以顯示的顏色總數非常大—— 超過160萬。其確切的數字是224次方,即16 777 216。顯然,我們需要對這些顏色進行索引,才能指定在給定的某個像素上要顯示什么顏色。

給顏色進行索引的最常見方式是把它們分為紅綠藍成分,每種成份的光分為256種不同的強度,其值在0~255之間。

2 設置顏色的方法

l         可以調用靜態函數Color.FromArgb()指定該顏色的紅綠藍值。

 其格式為

public static Color FromArgb (

       int red,

       int green,

       int blue

)

例如:

Color red = Color.FromArgb(255, 0, 0);

Color green = Color.FromArgb(0, 255, 0);

Color blue = Color.FromArgb(0, 0, 255);

l            獲取系統定義的顏色

使用FromArgb()構造顏色是一種非常靈活的技巧,因為它表示我們可以指定人眼能辨識出的任何顏色。但是,如果要得到一種簡單、標准、眾所周知的純色,例如紅色或藍色,命名想要的顏色是比較簡單的。因此Microsoft還在Color中提供了許多靜態屬性,每個屬性都返回一種命名的顏色。在下面的示例中,把窗口的背景色設置為白色時,就使用了其中一種屬性:

         this.BackColor = Color.White;

         // 與以下語句效果一樣

         // this.BackColor = Color.FromArgb(255, 255 , 255);

 

8.1.2 畫筆和鋼筆

本節介紹PenBrush,在繪制圖形時需要使用它們。Pen用於告訴graphics實例如何繪制線條。Brush如何填充區域。例如,Pen用於繪制矩形和橢圓的邊框。如果需要把這些圖形繪制為實心的,就要使用畫筆指定如何填充它們。

1畫筆

GDI+有幾種不同類型的畫筆。每種畫筆都由一個派生自抽象類System.Drawing.Brush的類實例來表示。最簡單的畫筆為System.Drawing.SolidBrush。它是單色畫筆,用於填充圖形形狀,如矩形、橢圓、扇形、多邊形和封閉路徑。

 Color customColor = Color.FromArgb(192,192,192);

    SolidBrush shadowBrush = new SolidBrush(customColor);

或者

    SolidBrush shadowBrush = new SolidBrush(Color.Gray);

2與畫筆不同,鋼筆只用一個類System.Drawing.Pen來表示。但鋼筆比畫筆復雜一些,因為它需要指定線條應有多寬(像素),對於一條比較寬的線段,還要確定如何填充該線條中的區域。

Pen solidBluePen = new Pen(Color.FromArgb(0,0,255));

Pen solidWideBluePen = new Pen(Color.Blue, 4);

8.2 繪圖所用到的結構

GDI+使用幾個類似的結構來表示坐標或區域。下面介紹幾個結構,它們都是在System.Drawing命名空間中定義的,如表8.1所示。

-1 PointSizeRectangle結構

 

   

主要的公共屬性

Point

X,Y

PointF

 

Size

Width, Height

 

SizeF

Rectangle

Left, Right , Top, Bottom, Width, Height, X, Y, Location, Size

RectangleF

   

 

8.2.1 PointPointF結構

表示圖像的一點,從概念上講,Point在這些結構中是最簡單的,在數學上,它完全等價於一個二維矢量。我們可以創建一個Point結構:

Point b = new Point(20, 10);

XY都是讀寫屬性,也可以在Point中設置這些值:

Point a = new Point();

a.X = 20;

b.Y = 10;

PointFPoint完全相同,但XY屬性的類型是float,而不是intPointF用於坐標不是整數值的情況。注意,可以把Point隱式轉換為 PointF,但要把PointF轉換為Point,必須顯式地復制值,或使用下面的3個轉換方法Round()Truncate()Ceiling()

   Point b = new Point();

   b.X = (int)abFloat.X;

   b.Y = (int)abFloat.Y;

// Point隱式轉換為 PointF

PointF bFloat1 = ab;

// PointF顯式轉換為 Point

 

   Point b1 = Point.Round(bFloat);

   Point b2 = Point.Truncate(bFloat);

   Point b3 = Point.Ceiling(bFloat);

 

8.2.2 SizeSizeF結構

PointPointF一樣,Size也有兩個屬性。Size結構用於int類型,SizeF用於float類型,除此之外,Size SizeF是完全相同的。下面主要討論Size結構。

在許多情況下,Size結構與Point結構是相同的,它也有兩個整型屬性,表示水平和垂直距離—— 主要區別是這兩個屬性的名稱不是XY,而是Width Height。前面的圖30-3可以表示為:

Size ab = new Size(20,10);

嚴格地講,Size在數學上與Point表示的含義相同;但在概念上它使用的方式略有不同。Point用於說明實體在什么地方,而Size用於說明實體有多大。

8.2.3 RectangleRectangleF結構

這兩個結構表示一個矩形區域(通常在屏幕上)。與Point Size一樣,這里只介紹Rectangle結構,RectangleFRectangle基本相同,但它的屬性類型是float,而Rectangle的屬性類型是int

Rectangle可以看作由一個Point 和一個 Size組成,其中Point表示矩形的左上角,Size表示其大小。它的一個構造函數把Point Size作為其參數

Point topLeft = new Point(0,0);

Size howBig = new Size(50,50);

Rectangle rectangleArea = new Rectangle(topLeft, howBig);

8.3繪制圖形和線條

System.Drawing.Graphics 有很多方法,利用這些方法可以繪制各種線條、空心圖形和實心圖形。表8.2所示的列表並不完整,但給出了主要的方法。本書只講解對直線、空實心矩形及橢圓進行繪制,其它圖形的繪制感興趣的同學可以查閱MSDN

8.2 繪制圖形的基本方法

   

繪制的圖形

DrawLine

鋼筆、起點和終點

一段直線

DrawRectangle

鋼筆、位置和大小

空心矩形

DrawEllipse

鋼筆、位置和大小

空心橢圓

FillRectangle

畫筆、位置和大小

實心矩形

FillEllipse

畫筆、位置和大小

實心橢圓

DrawLines

鋼筆、點數組

一組線,把數組中的每個點按順序連接起來

DrawBezier

鋼筆、4個點

通過兩個端點的一條光滑曲線,剩余的兩個點用於控制曲線的形狀

DrawCurve

鋼筆、點數組

通過點的一條光滑曲線

DrawArc

鋼筆、矩形、兩個角

由角度定義的矩形中圓的一部分

DrawClosedCurve

鋼筆、點數組

DrawCurve一樣,但還要繪制一條用以閉合曲線的直線

DrawPie

鋼筆、矩形、兩個角

矩形中的空心楔形

FillPie

畫筆、矩形、兩個角

矩形中的實心楔形

DrawPolygon

鋼筆、點數組

DrawLines 一樣,但還要連接第一點和最后一點,以閉合繪制的圖形

8.3.1 畫直線

1)繪制一條連接兩個 Point 結構的線,

public void DrawLine (

       Pen pen,

       Point start,

       Point end

)

pen,它確定線條的顏色、寬度和樣式。

startPoint 結構,它表示要連接的第一個點。

end Point 結構,它表示要連接的第二個點。

下面代碼繪制如圖8.1所示的直線,其顏色分別為黑、紅、黃及指定的RGB值,寬度分別為3,5,7,9

            Graphics g = this.CreateGraphics();

      //創建不同顏色及精細的畫筆

            Pen blackPen = new Pen(Color.Black, 3);

            Pen redPen = new Pen(Color.Red, 5);

            Pen yellowPen = new Pen(Color.Yellow, 7);

            Pen mypen = new Pen(Color.FromArgb(167, 234, 89), 9);

      //繪制黑線

           Point start1 = new Point(100, 100);

           Point end1 = new Point(200, 200);

           g.DrawLine(blackPen, start1, end1);

          //繪制紅線

           Point start2 = new Point(200, 100);

           Point end2 = new Point(300, 200);

           g.DrawLine(redPen, start2, end2);

     //繪制黃線

           Point start3 = new Point(300, 100);

           Point end3 = new Point(400, 200);

           g.DrawLine(yellowPen, start3, end3);

     //繪制RGB(167, 234, 89)的直線

           Point start4 = new Point(400, 100);

           Point end4 = new Point(500, 200);

       g.DrawLine(mypen, start4, end4);

8.1 直線

2)虛線

Pen DashStyle屬性,可以繪制虛線。

格式為

  myPen.DashStlyle= DashStyle.類型

下面的示例繪制如圖8.2所示的虛線,其虛線類型分別為:Dash, Dot, DashDot, DashDotDot

           Graphics g = this.CreateGraphics();

            Pen blackPen = new Pen(Color.Black, 3);

            Pen redPen = new Pen(Color.Red, 5);

            Pen yellowPen = new Pen(Color.Yellow, 7);

            Pen mypen = new Pen(Color.FromArgb(167, 234, 89), 9);

            blackPen.DashStyle = DashStyle.Dash;

            redPen.DashStyle = DashStyle.Dot;

            yellowPen.DashStyle = DashStyle.DashDot;

            mypen.DashStyle = DashStyle.DashDotDot;

           // Create points that define line.

           Point start1 = new Point(100, 100);

           Point end1 = new Point(200, 200);

           g.DrawLine(blackPen, start1, end1);

           Point start2 = new Point(200, 100);

           Point end2 = new Point(300, 200);

           g.DrawLine(redPen, start2, end2);

           Point start3 = new Point(300, 100);

           Point end3 = new Point(400, 200);

           g.DrawLine(yellowPen, start3, end3);

           Point start4 = new Point(400, 100);

           Point end4 = new Point(500, 200);

           g.DrawLine(mypen, start4, end4);

 

8.2 虛線

3)直線端點

以使用 Pen 對象的屬性為直線設置更多特性。StartCap 屬性和 EndCap 屬性指定直線端點的外觀;端點可以是平的、方形的、圓形的、三角形的或自定義的形狀。LineJoin 屬性用於指定連接的線相互間是斜接的(聯接時形成銳角)、斜切的、圓形的還是截斷的。

下面的代碼繪制如圖8.3所示帶端點的直線

           Graphics g = this.CreateGraphics();

            Pen blackPen = new Pen(Color.Black, 3);

            Pen redPen = new Pen(Color.Red, 5);

            Pen yellowPen = new Pen(Color.Yellow, 7);

            Pen mypen = new Pen(Color.FromArgb(167, 234, 89), 9);

            blackPen.StartCap =LineCap.Flat;

            blackPen.EndCap = LineCap.ArrowAnchor;

            redPen.StartCap = LineCap.DiamondAnchor;

            redPen.EndCap = LineCap.RoundAnchor;

            yellowPen.EndCap = LineCap.SquareAnchor;

            mypen.EndCap = LineCap.Triangle;

           // Create points that define line.

           Point start1 = new Point(100, 100);

           Point end1 = new Point(200, 200);

           g.DrawLine(blackPen, start1, end1);

           Point start2 = new Point(200, 100);

           Point end2 = new Point(300, 200);

           g.DrawLine(redPen, start2, end2);

           Point start3 = new Point(300, 100);

           Point end3 = new Point(400, 200);

           g.DrawLine(yellowPen, start3, end3);

           Point start4 = new Point(400, 100);

           Point end4 = new Point(500, 200);

           g.DrawLine(mypen, start4, end4);

8.3 帶端點的直線

8.3.2 畫空心矩形

繪制由 Rectangle 結構指定的矩形

public void DrawRectangle (

       Pen pen,

       Rectangle rect

)

pen ,Pen,它確定矩形的顏色、寬度和樣式。

rect ,表示要繪制的矩形的 Rectangle 結構。

下面代碼分別繪制如圖8.4所示的矩形,

            Graphics g = this.CreateGraphics();

            Pen blackPen = new Pen(Color.Black, 3);

            //blackPen.DashStyle = DashStyle.Dash;

            // 建立矩形.

            Rectangle rect = new Rectangle(100, 100, 200, 200);

            // 繪制黑色矩形

            g.DrawRectangle(blackPen, rect);

            Pen redPen = new Pen(Color.Red, 5);

     //設置矩形虛線的類型

            redPen.DashStyle = DashStyle.Dash;

            // 建立矩形.

            Rectangle rectred = new Rectangle(320,100, 200,200);

            // 繪制紅色矩形

            g.DrawRectangle(redPen, rectred);

 

8.4 矩形

8.3.3 畫實心矩陣

填充 Rectangle 結構指定的矩形的內部

格式:

public void FillRectangle (

       Brush brush,

       Rectangle rect

)

brush ,確定填充特性的 Brush

rect Rectangle 結構,它表示要填充的矩形。

·       下面代碼繪制如圖8.5所示的實心矩形

            Graphics g = this.CreateGraphics();

      //建立黑色畫筆

            SolidBrush blackBrush = new SolidBrush(Color.Black);

            // 構建矩形對象.

            Rectangle rect = new Rectangle(100, 100, 200, 200);

            // 畫黑實心矩形.

            g.FillRectangle(blackBrush, rect);

             //建立灰色畫筆

SolidBrush grayBrush = new SolidBrush(Color.Gray);

            Rectangle rectgray= new Rectangle(320, 100, 200, 200);

        g.FillRectangle(grayBrush,rectgray);

8.5 實形矩形

8.3.4 畫空心橢圓

格式:

public void DrawEllipse (

       Pen pen,

       Rectangle rect

)

下面代碼繪制如圖8.6所示的空心橢圓

            Graphics g = this.CreateGraphics();

            Pen blackPen = new Pen(Color.Black, 3);

            //構建矩形對象.

            Rectangle rect = new Rectangle(100, 100, 200, 100);

 

            // 畫空心空心橢圓.

            g.DrawEllipse(blackPen, rect);

            Rectangle rectgray = new Rectangle(320, 100, 200, 100);

      //建立灰色畫筆

            Pen grayPen = new Pen(Color.Gray, 5);

      //指定虛線類型

            grayPen.DashStyle = DashStyle.DashDotDot;

           //繪制虛線橢圓

            g.DrawEllipse(grayPen, rectgray);

 

8.6 空心橢圓

8.3.5 繪制弧線

弧線是橢圓的一部分。若要繪制弧線,可調用 Graphics 類的 DrawArc 方法。除了 DrawArc 需要有起始角度和仰角以外,DrawEllipse 方法的參數與 DrawArc 方法的參數相同。

public void DrawArc (

       Pen pen,

       RectangleF rect,

       float startAngle,

       float sweepAngle

)

參數

pen Pen類型 ,它確定弧線的顏色、寬度和樣式。

rect RectangleF 結構,它定義橢圓的邊界。

startAngle x 軸到弧線的起始點沿順時針方向度量的角(以度為單位)。

sweepAngle startAngle 參數到弧線的結束點沿順時針方向度量的角(以度為單位)。

下面代碼繪制如圖8.7所示的弧線

結果是部分橢圓,缺少 x 軸兩側 + 45 度和 - 45 度之間的部分。

            Graphics g = this.CreateGraphics();

            Pen blackPen = new Pen(Color.Black, 3);

            // 建立矩形

            RectangleF rect = new RectangleF(100.0F, 100.0F, 200.0F, 100.0F);

            // 指定起始角,終止角

            float startAngle =45.0F;

            float sweepAngle = 270.0F;

            // 畫黑色弧線.

            g.DrawArc(blackPen, rect, startAngle, sweepAngle);

            

            //建立灰色畫筆

Pen grayPen = new Pen(Color.Gray, 7);

//指定弧線的端點類型

            grayPen.StartCap=LineCap.DiamondAnchor;

            grayPen.EndCap = LineCap.ArrowAnchor;

            //指定虛線的類型

            grayPen.DashStyle = DashStyle.Dash;

 

            // // 建立第二橢圓的邊界矩形

            RectangleF rectgray = new RectangleF(320.0F, 100.0F, 200.0F, 100.0F);

            //指定起始角,終止角

             startAngle = -90.0F;

             sweepAngle = 135.0F;

            // 畫灰色弧線.

            g.DrawArc(grayPen, rectgray, startAngle, sweepAngle);

8.7 弧線

8.3.6 畫實心橢圓

格式:

public void FillEllipse (

       Brush brush,

       Rectangle rect

)

brush ,確定填充特性的 Brush

rect Rectangle 結構,它表示定義橢圓的邊框。

·       代碼繪制如圖8.8所示的實心橢圓

            Graphics g = this.CreateGraphics();

            SolidBrush blackBrush = new SolidBrush(Color.Black);

            // Create rectangle for ellipse.

            int x = 100;

            int y = 100;

            int width = 200;

            int height = 100;

            Rectangle rect = new Rectangle(x, y, width, height);

            // Fill ellipse on screen.

            g.FillEllipse(blackBrush, rect);

           

            SolidBrush grayBrush = new SolidBrush(Color.Gray);

            // Create rectangle for ellipse.

             x = 320;

             y = 100;

             width = 200;

             height = 100;

            Rectangle rectgray = new Rectangle(x, y, width, height);

            // Fill ellipse on screen.

            g.FillEllipse(grayBrush, rectgray);

本節介紹如果繪制的內容不適合窗口的大小,需要做哪些工作。

8.8 實心橢圓

8.3.7 繪制多邊形

多邊形是有三條或更多直邊的閉合圖形。例如,三角形是有三條邊的多邊形,矩形是有四條邊的多邊形,五邊形是有五條邊的多邊形。圖8.9的插圖顯示了幾個多邊形。

8.9多邊形

格式:

public void DrawPolygon (

        Pen pen,

        Point[] points

)

其中,points Point 結構數組,這些結構表示多邊形的頂點。

下面的代碼用於繪制如圖8.10所示的多邊形:

            Graphics g = this.CreateGraphics();

            Pen blackPen = new Pen(Color.Black, 3);         

// 建立多邊形的各頂點

            Point point1 = new Point(50, 150);

            Point point2 = new Point(100, 125);

            Point point3 = new Point(200, 115);

            Point point4 = new Point(250, 150);

            Point point5 = new Point(300, 200);

            Point point6 = new Point(350, 300);

            Point point7 = new Point(250, 350);

            Point[] curvePoints =

             {

                 point1,

                 point2,

                 point3,

                 point4,

                 point5,

                 point6,

                 point7

             };

            // 繪制多邊形

            g.DrawPolygon(blackPen, curvePoints);

8.10 繪制多邊形

繪制實多邊形

格式:

public void FillPolygon (

       Brush brush,

       Point[] points

)

brush 為確定填充特性的 Brush

PointsPoint 結構數組,這些結構表示要填充的多邊形的頂點。

下面代碼繪制如圖8.11所示的實多邊形

            Graphics g = this.CreateGraphics();

            SolidBrush blackBrush = new SolidBrush(Color.Black);

            // Create points that define polygon.

            Point point1 = new Point(50, 150);

            Point point2 = new Point(100, 125);

            Point point3 = new Point(200, 115);

            Point point4 = new Point(250, 150);

            Point point5 = new Point(300, 200);

            Point point6 = new Point(350, 300);

            Point point7 = new Point(250, 350);

            Point[] curvePoints =

             {

                 point1,

                 point2,

                 point3,

                 point4,

                 point5,

                 point6,

                 point7

             };

            // Draw polygon to screen.

            g.FillPolygon(blackBrush, curvePoints);

 

8.11實心多邊形

 

8.4 GDI+ 中的畫筆和實心形狀

閉合的形狀(例如,矩形或橢圓)由輪廓和內部組成。用鋼筆繪制出輪廓,並用畫筆填充其內部。GDI+ 提供了幾種填充閉合形狀內部的畫筆類:SolidBrushHatchBrushTextureBrushLinearGradientBrush PathGradientBrush。所有這些類都是從 Brush 類繼承的。下面的插圖顯示了用實心畫筆填充的矩形和用陰影畫筆填充的橢圓。

8.12 實心形狀

若要填充閉合的形狀,需要 Graphics 類的實例和 BrushGraphics 類的實例提供方法,如 FillRectangle FillEllipse,而 Brush 存儲填充的屬性,如顏色和模式。Brush 作為參數之一傳遞給填充方法。下面的代碼示例演示如何用純紅色填充橢圓。

SolidBrush mySolidBrush = new SolidBrush(Color.Red);

myGraphics.FillEllipse(mySolidBrush, 0, 0, 60, 40);

8.4.1 陰影畫筆

用陰影畫筆填充圖形時,要指定前景色、背景色和陰影樣式。前景色是陰影的顏色。

其格式為:

public HatchBrush (

        HatchStyle hatchstyle,

        Color foreColor,

        Color backColor

)

hatchstyle,表示此 HatchBrush 所繪制的圖案。

foreColor,它表示此 HatchBrush 所繪制線條的顏色。

backColor,它表示此 HatchBrush 繪制的線條間空間的顏色。

例如:

HatchBrush myHatchBrush =    new HatchBrush(HatchStyle.Vertical, Color.Blue, Color.Green);

GDI+ 提供 50 多種陰影樣式;在下面代碼繪制如圖8.13的實心形狀,顯示的三種樣式是:HorizontalForwardDiagonal Cross

           Graphics g = this.CreateGraphics();

            HatchBrush myHatchBrush1 =

            new HatchBrush(HatchStyle.Horizontal, Color.Black, Color.Gray);

            // Create rectangle for ellipse.

            int x = 100;

            int y = 100;

            int width = 200;

            int height = 100;

            Rectangle rect1 = new Rectangle(x, y, width, height);

            // Fill ellipse on screen.

            g.FillEllipse(myHatchBrush1, rect1);

             x = 320;

             y = 100;

             width = 200;

             height = 100;

            Rectangle rect2 = new Rectangle(x, y, width, height);

            HatchBrush myHatchBrush2=               new HatchBrush (HatchStyle.ForwardDiagonal, Color.Black, Color.Gray);

            // Fill ellipse on screen.

            g.FillEllipse(myHatchBrush2, rect2);

             x = 520;

             y = 100;

             width = 200;

             height = 100;

            Rectangle rect3 = new Rectangle(x, y, width, height);

            HatchBrush myHatchBrush3 =

                new HatchBrush(HatchStyle.Cross, Color.Black, Color.Gray);

 

            // Fill ellipse on screen.

            g.FillEllipse(myHatchBrush3, rect3);

8.13 繪制實心形狀

8.4.2 紋理畫筆

有了紋理畫筆,您就可以用位圖中存儲的圖案來填充圖形。

格式:

public TextureBrush (

        Image bitmap

)

BitmapImage 對象,使用它來填充其內部。

例如,假定圖片存儲在名為 MyTexture.bmp 的磁盤文件中。

Image myImage = Image.FromFile("MyTexture.bmp");

TextureBrush myTextureBrush = new TextureBrush(myImage);

下面代碼用圖8.14片來填充橢圓,其效果如圖8.15

8.14 填充圖片

            Graphics g = this.CreateGraphics();

           //打開填充的圖片

            Image myImage = Image.FromFile("e:\\text.jpg");

            TextureBrush myTextureBrush = new TextureBrush(myImage);

            g.FillEllipse(myTextureBrush, 100,100, 200, 100);

 

8.15 用小圖片進行填充

Image myImage = Image.FromFile("MyTexture.bmp");

TextureBrush myTextureBrush = new TextureBrush(myImage);

8.4.3 漸變畫筆

GDI+ 提供兩種漸變畫筆:線性和路徑。您可以使用線性漸變畫筆來用顏色(在您橫向、縱向或斜向移過圖形時會逐漸變化的顏色)填充圖形。下面的代碼示例演示如何用水平漸變畫筆填充一個橢圓,當從橢圓的左邊緣向右邊緣移動時,畫筆顏色會由藍變為綠。

常用格式:

public LinearGradientBrush (

        Rectangle rect,

        Color color1,

        Color color2,

        LinearGradientMode linearGradientMode

)

rect指定線性漸變的界限。

color1  表示漸變起始色的 Color 結構。

color2   表示漸變結束色的 Color 結構。

linearGradientMode LinearGradientMode 枚舉元素,它指定漸變方向。漸變方向決定漸變的起點和終點。例如,LinearGradientMode.ForwardDiagonal 指定起始點是矩形的左上角,而結束點是矩形的右下角。

LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(

   myRectangle,

   Color.Blue,

   Color.Green,

   LinearGradientMode.Horizontal);

下面的代碼用從藍到綠的漸變填充橢圓,如圖8-16

            Graphics g = this.CreateGraphics();

            Rectangle myRectangle = new Rectangle(100, 100, 200, 100);

            LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(

               myRectangle,

               Color.Blue,

               Color.Green,

               LinearGradientMode.ForwardDiagonal);

            g.FillEllipse(myLinearGradientBrush, 100, 100, 200, 100);

 

8.16 顏色漸變

 

8.5 繪制文本

到目前為止,本章還有一個非常重要的問題要討論—— 顯示文本。因為在屏幕上繪制文本通常比繪制簡單圖形更復雜。在不考慮外觀的情況下,只顯示一兩行文本是非常簡單的—— 它只需調用Graphics實例的一個方法Graphics.DrawString()

格式:

public void DrawString (

        string s,

        Font font,

        Brush brush,

        PointF point

)

s 為要繪制的字符串。

font定義字符串的文本格式。

brush確定所繪制文本的顏色和紋理。

point,它指定所繪制文本的左上角。

下面代碼以16磅宋體及32磅黑體分別顯示你好,如圖8.17

            Graphics g = this.CreateGraphics();

            String drawString = "你好宋體";

            // Create font and brush.

            Font drawFont = new Font("宋體", 16);

            SolidBrush drawBrush = new SolidBrush(Color.Black);

            // Create point for upper-left corner of drawing.

            PointF drawPoint = new PointF(150.0F, 150.0F);

            // Draw string to screen.

           g.DrawString(drawString, drawFont, drawBrush, drawPoint);

          

            Font drawFont2 = new Font("黑體", 32);

           SolidBrush drawBrush2 = new SolidBrush(Color.Gray);

           // Create point for upper-left corner of drawing.

           PointF drawPoint2 = new PointF(150.0F, 200.0F);

           drawString = "你好黑體32";

           // Draw string to screen.

       g.DrawString(drawString, drawFont2, drawBrush2, drawPoint2);

-17 顯示字符

 

8.6 顏色對話框

顏色對話框用於顯示並設置用戶可用的顏色。如圖8.18

8.18 顏色對話框

顏色對話框由ColorDialog類來實現。

其使用步驟為:

1 建立ColorDialog對象

            ColorDialog MyDialog = new ColorDialog();

2 設置用可以自定義顏色

MyDialog.AllowFullOpen = true;

 3 顯示對話框 

            if (MyDialog.ShowDialog() == DialogResult.OK)

            {

               …;

            }

以下代碼用顏色對話框設置鋼筆和畫筆的顏色,並用於畫實心和空心橢圓,如圖8.19

           Graphics g = this.CreateGraphics();

      //建立顏色對話框

            ColorDialog MyDialog = new ColorDialog();

            // 允許用戶自義顏色

            MyDialog.AllowFullOpen = true;

            MyDialog.ShowHelp = true;

//顯示顏色對話框

            if (MyDialog.ShowDialog() == DialogResult.OK)

            {

                Pen pen = new Pen(MyDialog.Color, 3);

                Brush brush = new SolidBrush(MyDialog.Color);

                Rectangle rect1 = new Rectangle(100, 100, 200, 100);

                Rectangle rect2 = new Rectangle(320, 100, 200, 100);

                // 畫空心空心橢圓.

                g.DrawEllipse(pen, rect1);

                g.FillEllipse(brush, rect2);

            }

8.19 用自定義顏色畫的橢圓

8.7 鼠標事件

繪制直線需要獲取起點坐標、終點坐標,繪制矩形、橢圓需要獲取起點坐標及繪制的大小。這些坐標或大小可以從鍵盤輸入,但這不方便,也不符合用戶的習慣。因而,我們需要學習用鼠標事件。

事件在發生其關注的事情時用來提供通知的一種方式,是可以通過代碼響應或處理的操作。事件可由用戶操作(如單擊鼠標或按某個鍵)、程序代碼或系統生成。事件驅動的應用程序執行代碼以響應事件。每個窗體和控件都公開一組預定義事件,您可根據這些事件進行編程。如果發生其中一個事件並且在相關聯的事件處理程序中有代碼,則調用該代碼。

事件處理函數通常有兩個參數:

第一個參數為引用事件源的對象,第二個參數為與事件相關的數據。如:

      private void button1_MMove ( object sender , System.Windows.Forms. MouseEventArgs e )

常用的鼠標事件如表8.3

8.3 常用的鼠標事件

鼠標事件

說明

MouseDown

當鼠標指針在控件上且用戶按下鼠標按鈕時發生此事件。此事件的處理程序接收類型為 MouseEventArgs 的參數。

MouseMove

當鼠標指針在控件上移動時發生此事件。此事件的處理程序接收類型為 MouseEventArgs 的參數。

MouseUp

當鼠標指針在控件上且用戶釋放鼠標按鈕時發生此事件。此事件的處理程序接收類型為 MouseEventArgs 的參數。

Click

釋放鼠標按鈕時發生此事件,通常發生在 MouseUp 事件前。此事件的處理程序接收類型為 EventArgs 的參數。如果只需要確定何時發生單擊,可處理此事件。

DoubleClick

雙擊控件時發生此事件。此事件的處理程序接收類型為 EventArgs 的參數。如果只需要確定何時發生雙擊,可處理此事件。

 

MouseEventArgs 的命名空間為System.Windows.Forms,它為 MouseUpMouseDown MouseMove 事件提供數據。

其常用的屬性如表8.4

8.4 鼠標常用的屬性

名稱

說明

Button

獲取曾按下的是哪個鼠標按鈕。

Clicks

獲取按下並釋放鼠標按鈕的次數。

Location

獲取鼠標在產生鼠標事件時的位置。

X

獲取鼠標在產生鼠標事件時的 x 坐標。

Y

獲取鼠標在產生鼠標事件時的 y 坐標。

 

事件的編程通常分為兩個步驟

l         編寫事件處理的函數

l         把事件與處理函數關聯起來(Delegate

對於MouseDownMouseUp,MouseMove事件,其格式為:

 "組件名稱"."事件名稱"+= new System.Windows.Forms. MouseEventHandler"事件名稱");

 

8.4.1 MouseMove

1) 編寫處理函數

假設我們已建立了名為Form1的視窗,我們可以在Form1的類中編寫如函數

private void Form1_OnMouseMove ( object sender , MouseEventArgs e )
{
       this.Text = "當前鼠標的位置為:( " + e.X + " , " + e.Y + ")" ;
}

2)關聯事件和處理函數

在視窗的初始函數InitializeComponent中加入如下語句。

this.MouseMove += new System.Windows.Forms.MouseEventHandlerForm1_OnMouseMove);

8.4.2 MouseDown

1) 編寫處理函數

假設我們已建立了名為Form1的視窗,我們可以在Form1的類中編寫如函數

private void Form1_MouseDown ( object sender , MouseEventArgs e )
{
     if ( e.Button == MouseButtons.Left )
            MessageBox.Show ( "按動鼠標左鍵!" ) ;
     if ( e.Button == MouseButtons.Middle )
          MessageBox.Show ( "按動鼠標中鍵!") ;
     if ( e.Button == MouseButtons.Right )
        MessageBox.Show ( "按動鼠標右鍵!") ;
}

2)關聯事件和處理函數

在視窗的初始函數InitializeComponent中加入如下語句。

this.MouseMove += new System.Windows.Forms.MouseEventHandlerForm1_OnMouseMove);

8.8 應用實例

本實例用鼠標拖動繪制直線,空實心矩形,橢圓,並可以設置線型及填充類型。可以在第七章的基礎上增加此功能。

步驟(若在第七章的基礎上增加功能直接轉到步驟5):

1)建立圖像處理項目,名字為”Paint”。並把Form1的自動滾動屬性“AutoScroll”設置為ture

2) 在窗體上繪制 PictureBox 控件,其名字為“ pictureBox1”

3)在Form1 類中增加一個成員變量,即

        private Bitmap bitmap;

4) 建立文件菜單,在其屬性中名字改為“File”

5)在文件下建立新建選項,在其屬性中名字改為“NewFile_M“

6)建立繪圖菜單,其名字為“Painting_M”,並在其上建立直線空心矩形實心矩形空心橢圓實心橢圓選項,在它們的屬性中名字分別改為“LineM”“RectangleM”“FillRectM”,“Ellipse_M”“FillEllM”

7)建立顏色菜單,其名字為“ColorM”,並在它上面建立紅色綠色藍色及自定義顏色選項,其名字分別為“RedM”“GreenM”“BlueM”“MyColor”

8)建立工具欄:單擊工具箱中的菜單及工具欄,把“ToolStrip”拖入視窗。

9)增加一個按鈕:單擊新建的工具欄中的增加ToolStripButton”按鈕,增加一個按鈕,並在屬性中為其改名,如改為“NewFile_T”

10) 附件中的畫圖內繪制工具欄按鈕的圖片,圖片的大小為16*16,新建的圖片為 ,並保存圖片,例如文件名取為“newfile.bmp”

11) 改變工具欄按鈕的圖片,,在工具欄增加一個按鈕,並單擊其屬性中的外觀選項中的“image”選項中的”…”, 彈出選擇資源對話框,單擊導入按鈕,選擇顯示圖片。

12) 重復9-11)步,直到為所有經常用的選項在工具建立對應的按鈕

13) 建立線型菜單,並在其下建立線型起始端點終點端點子菜單

14) 為線型建立 “Dash”“DashDot”“DashDotDot”“Dot”“Solid”子菜單

15 為起始點建立“ArrowAnchor”“DiamondAnchor”“SquareAnchor”“Triangle”“RoundAnchor”子菜單

16 為起始點建立“ArrowAnchor”“DiamondAnchor”“SquareAnchor”“Triangle”“RoundAnchor”子菜單

17) 雙擊文件菜單中的新建選項,系統自動為其建立響應函數的框架,在其中編寫程序,完成新建一個Bitmap圖像,並把它綁定pictureBox11上。

        private void New_Click(object sender, EventArgs e)

        {

            bitmap = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height);

            this.pictureBox1.Image = bitmap;

 

        }

18)雙擊工具欄新建按鈕,系統自動為其建立響應函數的框架,我們不必為其編寫新的代碼,只需要調用菜單中的新建選項的響應函數就行了。如下:

        private void NewT_Click(object sender, EventArgs e)

        {

            New_Click( sender,  e);

        }

注:以后工具欄的代碼與此類似,即直接調用對應的菜單選項的處理函數。

19)在Form1 中增加成員數據pen,為Pen類,用於畫直線,空心矩陣,實心橢圓。

   增加成員數brush,屬於Brush類,用於畫實心矩陣,實心矩陣,實心橢圓。

   增加成員數據selectint 類型,用於存放選擇的繪圖方式。其值為1時,表示繪制直線,為2表示繪制空心矩形,為3表示繪制空心橢圓,為4表示繪制實心矩形,為5表示繪制空心矩形。

   增加成員數據CanMove,bool類型,用於判斷移動鼠標是否按着左鍵。

   增加成員數據start,Point類型,用於存放按下鼠標左鍵時鼠標的位置。

如下:

        private Bitmap bitmap;

        private Point start;

        bool CanMove;

        int select = 0;

        Pen pen = new Pen(Color.Red, 2);

        Brush brush = new SolidBrush(Color.Gray);

20) 雙擊菜單中的直線選項,為其編寫程序

        private void LINE_Click(object sender, EventArgs e)

        {

            select = 1;

        }

21) 雙擊菜單中的空心矩形選項,為其編寫程序

        private void RECT_Click(object sender, EventArgs e)

        {

            select = 2;

        }

22) 雙擊菜單中的空心橢圓選項,為其編寫程序

        private void Ellipse_Click(object sender, EventArgs e)

        {

            select = 3;

        }

23) 雙擊菜單中的實心矩形選項,為其編寫程序

       private void FRect_Click(object sender, EventArgs e)

        {

            select = 4;

        }

24雙擊菜單中的實空心橢圓選項,為其編寫程序

        private void FEll_Click(object sender, EventArgs e)

        {

            select = 5;

        }

25) 雙擊菜單中的紅色選項,為其編寫程序

建立紅色的畫筆(Brush,及紅色的鋼筆(Pen)

        private void RED_Click(object sender, EventArgs e)

        {

            pen = new Pen(Color.Red, float.Parse(this.linesize.Text));

            brush=new  SolidBrush(Color.Red);

        }

26) 雙擊菜單中的綠色選項,為其編寫程序

建立綠色的畫筆(Brush,及綠色的鋼筆(Pen)

        private void GREE_Click(object sender, EventArgs e)

        {

            pen = new Pen(Color.Green, float.Parse(this.linesize.Text));

            brush = new SolidBrush(Color.Green);

 

        }

27) 雙擊菜單中的藍色選項,為其編寫程序

建立藍色的畫筆(Brush,及藍色的鋼筆(Pen)

        private void BLUE_Click(object sender, EventArgs e)

        {

            pen = new Pen(Color.Blue, float.Parse(this.linesize.Text));

            brush = new SolidBrush(Color.Blue);

        }

28) 雙擊自定義顏色選項,並為其編寫程序

      private void ColorSet_Click(object sender, EventArgs e)

        {

            ColorDialog MyDialog = new ColorDialog();

            // Keeps the user from selecting a custom color.

            MyDialog.AllowFullOpen = true;

            // Allows the user to get help. (The default is false.)

            MyDialog.ShowHelp = true;

            // Sets the initial color select to the current text color.

           // MyDialog.Color = textBox1.ForeColor;

 

            // Update the text box color if the user clicks OK

            if (MyDialog.ShowDialog() == DialogResult.OK)

            {

                pen = new Pen(MyDialog.Color,float.Parse(this.linesize.Text));

                brush = new SolidBrush(MyDialog.Color);

            }

 

        }

29 為鼠標移動編寫處理程序

當變量CanMoveTrue時,已獲取了繪制圖形的初始位置,但終止位置或大小還沒有確定,因而假設當位置為終止位置,動態地繪制圖形。Start為第一次按下鼠標左鍵時鼠標的位置,即繪制圖形的初始位置。e.x, e.y為當前鼠標的位置,繪制圖形的終止位置。因而顯然,e.X - start.X 為繪制圖像的寬度,e.y-start.y為繪制圖像的高度。Select為繪畫的方式,1為真線,2為空心矩形,3為空心橢圓,4為實心矩形,5為實心橢圓。

        private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)

        {

            if (this.CanMove == true)

            {

                this.pictureBox1.Image = (Bitmap)this.bitmap.Clone();

                Graphics g = Graphics.FromImage(this.pictureBox1.Image);

                switch(select){

                    case 1:

                       g.DrawLine(pen, this.start, new Point(e.X, e.Y));//重繪

                      break;

                    case 2:

                        if (start.X<e.X&&start.Y<e.Y)

                             g.DrawRectangle(pen, start.X,start.Y, e.X-start.X,e.Y-start.Y);

                        break;

                    case 3:

                        if (start.X < e.X && start.Y < e.Y)

                            g.DrawEllipse(pen, start.X, start.Y, e.X - start.X, e.Y - start.Y);

                        break;

                    case 4:

                        if (start.X < e.X && start.Y < e.Y)

                            g.FillRectangle(brush, start.X, start.Y, e.X - start.X, e.Y - start.Y);

                        break;

                    case 5:

                        if (start.X < e.X && start.Y < e.Y)

                            g.FillEllipse(brush, start.X, start.Y, e.X - start.X, e.Y - start.Y);

                        break;

                }

                g.Dispose();

            }

            this.MousePos.Text = "坐標" + e.X + "," + e.Y;

        }

30) 關聯鼠標移動事件和處理程序

Form1類中的InitializeComponent成員函數增加如下語句:

            this.pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);

因為圖形是畫在pictureBox1控件上的,因而當鼠標在pictureBox1上移動時會觸發鼠標處理函數。

31)為鼠標按左鍵編寫處理程序為

canMovefalse時,說明是剛按下鼠標左鍵,因而用this.start = new Point(e.X, e.Y);語句保存畫圖的起始點位置,並把canMove設置為true,因而鼠標移動時會動態地畫圖形。以后當再一次按下鼠標左鍵時,獲得圖形的終止位置,因而繪制圖形,並把canMove設置為false, 鼠標移動時不再畫圖形。

        private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

        {

            if (e.Button == MouseButtons.Left)

            {

                if (!CanMove)

                {

                    this.start = new Point(e.X, e.Y);

                    this.CanMove = true;

                }

                else

                {

                    this.pictureBox1.Image = this.bitmap;

                    Graphics g = Graphics.FromImage(this.pictureBox1.Image);

                    switch(select){

                        case 1:

                             g.DrawLine(pen, this.start, new Point(e.X, e.Y));

                            break;

                        case 2:

                            if (start.X < e.X && start.Y < e.Y)

                                g.DrawRectangle(pen, start.X, start.Y, e.X - start.X, e.Y – start.Y);

                            break;

                        case 3:

                            if (start.X < e.X && start.Y < e.Y)

                                g.DrawEllipse(pen, start.X, start.Y, e.X - start.X, e.Y - start.Y);

                            break;

                        case 4:

                            if (start.X < e.X && start.Y < e.Y)

                                g.FillRectangle(brush, start.X, start.Y, e.X - start.X, e.Y - start.Y);

                            break;

                        case 5:

                            if (start.X < e.X && start.Y < e.Y)

                                g.FillEllipse(brush, start.X, start.Y, e.X - start.X, e.Y - start.Y);

                            break;

                    }

                    g.Dispose();

                    CanMove = false;

                    //this.pictureBox1.Invalidate();

                }

            }

        }

32)-36)設置線的類型

32) 雙擊“Dash”選項,並為其編寫腳本

        private void Dash_Click(object sender, EventArgs e)

        {

            pen.DashStyle = DashStyle.Dash;

        }

33) 雙擊“DashDot ”選項,並為其編寫腳本

       private void DashDot_Click(object sender, EventArgs e)

        {

            pen.DashStyle = DashStyle.DashDot;

    }

34) 雙擊“DashDotDot 選項,並為其編寫腳本

       private void DashDotDot_Click(object sender, EventArgs e)

        {

            pen.DashStyle = DashStyle.DashDotDot;

        }

35) 雙擊“Dot 選項,並為其編寫腳本

        private void Dot_Click(object sender, EventArgs e)

        {

            pen.DashStyle = DashStyle.Dot;

        }

36) 雙擊“Solid ” 選項,並為其編寫腳本

        private void Solid _Click(object sender, EventArgs e)

        {

            pen.DashStyle =DashStyle.Solid

        }

37)-40)為線的起始端點設置類型

37) 雙擊“ArrowAnchor” 選項,並為其編寫腳本

      private void ArrowAnchor_Click(object sender, EventArgs e)

        {

            pen.StartCap = LineCap. ArrowAnchor;

        }

38)雙擊“DiamondAnchor” 選項,並為其編寫腳本

       private void DiamondAnchor _Click(object sender, EventArgs e)

        {

            pen.StartCap = LineCap.DiamondAnchor;

        }

39)   雙擊“squareAnchor” 選項,並為其編寫腳本雙擊

  private void squareAnchor_Click(object sender, EventArgs e)

        {

            pen.StartCap = LineCap.SquareAnchor;

        }

 

40)雙擊“triangle” 選項,並為其編寫腳本雙擊

        private void triangle_Click(object sender, EventArgs e)

        {

            pen.StartCap = LineCap.Triangle;

        }

41)-45)為為線的終止端點設置類型

41) 雙擊“ArrowAnchorEnd” 選項,並為其編寫腳本雙擊

        private void ArrowAnchorEnd_Click(object sender, EventArgs e)

        {

            pen.EndCap = LineCap.DiamondAnchor;

        }

42) 雙擊“DiamondAnchorEnd” 選項,並為其編寫腳本雙擊

      private void DiamondAnchorEnd_Click(object sender, EventArgs e)

        {

            pen.EndCap = LineCap.DiamondAnchor;

        }

43) 雙擊“RoundAnchorEnd” 選項,並為其編寫腳本雙擊

      private void RoundAnchorEnd_Click(object sender, EventArgs e)

        {

            pen.EndCap = LineCap.RoundAnchor;

        }

44)    雙擊“squareAnchorEnd” 選項,並為其編寫腳本雙擊

private void squareAnchorEnd_Click(object sender, EventArgs e)

        {

            pen.EndCap = LineCap.SquareAnchor;

 

        }

45)  雙擊“TriangleEnd” 選項,並為其編寫腳本雙擊

private void TriangleEnd_Click(object sender, EventArgs e)

        {

            pen.EndCap = LineCap.Triangle;

        }

 

本章小結

本章介紹用GDI+繪制圖形。主要包括:畫筆、鋼筆的基本概念,如何繪制直線、空心方框、橢圓、多邊形以及如何繪制實心的方框、橢圓、多邊形,鋼筆線的粗細、實線、虛線、起點及終點的設置,畫筆的填充方式等。在最后,我們在第七章的基礎上,綜合運用我們所學的知識,編寫一個簡單衫的畫圖程序。

基本概念

鋼筆 用於繪制線條圖案,它可以設置線的粗細、類型、起點終點的類型。

畫筆 用於實心的圖形,它可以設置不同的填充方式。

Point 圖像上的點

Size 表示大小

Rectangle 表示矩形區域

基本操作

DrawLine 繪制直線

DashStyle  Pen的屬性,用於設置虛線類型

StartCap   Pen的屬性,用於設置起始端點的類型

EndCap   Pen的屬性,用於設置終點端點的類型

DrawRectangle 繪制空心矩形

FillRectangle 繪制實心矩形

DrawEllipse繪制空心橢圓

DrawArc 繪制圓弧

FillEllipse 繪制實心橢圓

DrawPolygon 繪制空心多邊形

FillPolygon繪制實心多邊形

HatchBrush 設置陰影畫筆

TextureBrush設置紋理畫筆

LinearGradientBrush 設置漸變畫筆

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM