C# GDI+編程(一)

GDI+編程可以先參考一下http://hi.baidu.com/3582077/blog/item/56fbc926bd86260a8a82a18e.html

雖然是C++的,但總有一些相通的地方。

窗口刷新的時候,會產生Paint事件,那麼我們給這個事件添加一個處理函數。然後在這個函數裏畫圖。就能保證所畫的圖不被刷新掉,

它可以總是顯示。Paint事件對應的委託是:public delegate void PaintEventHandler(object sender, PaintEventArgs e);

先來個最簡單的繪製,在窗口上畫一根線。(創建WindowsForms應用程序)

   public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

          //添加Paint事件處理函數
            this.Paint += formPaint;
        }
        private void formPaint(Object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            //畫筆,綠色,2像素寬
            Pen pen=new Pen(Color.FromArgb(0,255,0),2);
            //畫一根線,兩點是0,0和100,100
            graphics.DrawLine(pen,new Point(0,0),new Point(100,100));
        }
    }

像繪製直線,矩形,圓形,還有圖片,都可以通過Graphics類來完成。

示例2:一個填充矩形

 Graphics graphics = e.Graphics;
 //藍色畫刷
 SolidBrush brush = new SolidBrush(Color.FromArgb(0, 0, 255));
  //一個矩形
 Rectangle rect = new Rectangle(0, 0, 100, 100);
 //填充一個矩形
 graphics.FillRectangle(brush, rect);

示例3:畫一張png圖片(用PNG是因爲可以顯示透明的圖片,GIF圖片也有這個作用)

        private void formPaint(Object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            //加載圖片
            Image img=Image.FromFile("d:\\Image\\win.png");
            //圖片顯示起始位置
            Point strPoint=new Point(50,50);
            //不限制大小繪製
            graphics.DrawImage(img, strPoint);
            //縮小圖片繪製,限制在一個矩形內
            Rectangle rect=new Rectangle(50,50,100,100);
            graphics.DrawImage(img, rect);
        }

效果圖如下:


用DrawString顯示文字

DrawString在Grahpics類裏有好幾個重載,有的可以讓字符串在一個矩形內顯示,有的可以使用特定的顯示格式。這裏就不做詳細介紹了。

只講比較常用的。

看例子吧,處理鍵盤輸入字符事件,在窗口顯示輸入的字符。如下:

    public partial class Form1 : Form
    {
        public static String strText = "";
        public Form1()
        {
            InitializeComponent();
            this.Paint += formPaint;
            this.KeyPress += formKeyPress;
          
        }
        private void formPaint(Object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            //創建畫刷
            SolidBrush brush=new SolidBrush(Color.FromArgb(0,255,0));
            //創建字體
            Font font=new Font("宋體",20f);
            //顯示字符串,在一個矩形內
            graphics.DrawString(strText, font, brush, this.ClientRectangle);
         
        }
        private void formKeyPress(object sender, KeyPressEventArgs e)
        {
            strText += e.KeyChar;
            //刷新整個窗口
            this.Invalidate();
        }
    }

還有graphics.DrawString(strText, font, brush, new Point(100, 100));顯示方式,這個只是指定了文字顯示的起始位置。

關於顯示格式看下例:

 //顯示字符串,在一個矩形內
 StringFormat strFormat = new StringFormat(StringFormatFlags.DirectionRightToLeft);
 graphics.DrawString(strText, font, brush, this.ClientRectangle,strFormat);

StringFormatFlags是一個枚舉類型,自己一個一個試吧,看看每個枚舉成員表示什麼樣的格式。

接下來,我們來看一下。Form類中默認處理事件的方法,和你的添加的事件處理方法,這兩者有什麼關係。

一個示例:處理鼠標左鍵事件

   public partial class Form1 : Form
    {
        private Color prBackColor;
        public Form1()
        {
            InitializeComponent();
            //窗口默認的背景顏色
            prBackColor = this.BackColor;
            //添加事件處理
            this.MouseDown += formMouseDown;
            this.MouseUp += formMouseUp;
        }
        //鼠標鍵按下事件處理方法
        private void formMouseDown(object sender, MouseEventArgs e)
        {
            //如果是鼠標右鍵按下
            if (e.Button == MouseButtons.Right)
            {
                Form1 form1 = (Form1)sender;
                //改變背景顏色
                form1.BackColor = Color.FromArgb(0, 255, 0);
            }
        }
        //鼠標鍵彈起(鬆開)事件處理方法
        private void formMouseUp(object sender, MouseEventArgs e)
        {
            if(e.Button==MouseButtons.Right)
            {
            Form1 form1 = (Form1)sender;
            form1.BackColor = prBackColor;
            }

        }

}

像鼠標鍵按下MouseDown和鼠標鍵鬆開,Form都有默認的事件處理方法,這些方法都是虛方法,你可以重寫它們,比如重寫

protected virtual void OnMouseDown(MouseEventArgs e);和protected virtual void OnMouseUp(MouseEventArgs e);

這樣就可以不必添加事件處理方法,也能處理鼠標事件了,可以通過重寫父類默認事件處理方法,來實現上面的例子。

而在查MSDN可以發現,像這些默認的事件處理方法,調用都能引發其對應的事件。比如,我調用了OnMouseDown就能引發鼠標左鍵按下事件,其實也就是執行了我們添加的事件處理方法(委託)。而且我們還是多播委託的,因爲我們是用"+="添加委託方法的。

這樣的話,如果你重寫了OnMouseDown一定要在裏面調用基類的OnMouseDown方法,

不然我們添加的MouseDown方法就不會被執行(如果有)

那麼知道了上面那些,我就來做一個實際例子吧。重寫OnPaintBackground繪製背景的方法。

  public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        //重寫OnPaintBackground方法
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //禁止基類處理,我們自己來繪製背景
            //base.OnPaintBackground(e);
            //透明背景畫刷
            SolidBrush brush=new SolidBrush(Color.Transparent);
            //填充整個窗口
            e.Graphics.FillRectangle(brush,this.ClientRectangle);
            //再畫一個圓圈
            Pen pen = new Pen(Color.FromArgb(0, 255, 0),3);
            e.Graphics.DrawEllipse(pen, this.ClientRectangle);
        }
    }

運行效果圖:


TextureBursh圖片畫刷

可以用圖片來填充一個形狀,如矩形,圓形。圖片不夠大則平鋪顯示。

示例:

   private void formPaint(Object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            //創建圖片畫刷
            Rectangle rect = new Rectangle(10, 10, 70, 70);
            TextureBrush brush = new TextureBrush(Image.FromFile("d:\\Image\\345.jpg"),rect);
            graphics.FillEllipse(brush, 0, 0, 200, 200);
        }

構造函數最後一個參數,rect表示要用圖片的哪部分進行填充,10,10表示圖片起始位置(左上角),70,70表示寬度和高度,注意不能超出圖片原有範圍。整張圖片填充的話,則不需要指定rect。構造函數裏填一個參數就行了。

LinearGradientBursh線性漸變畫刷(這個類存在於System.Drawing.Drawing2D命名空間裏)

LinearGradientBursh類有一個構造函數重載,它有四個參數,是兩個點,和兩種顏色。

這四個參數指定了起始點的顏色,和結束點的顏色。還有位置。

看下例:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Paint += formPaint;

        }
        private void formPaint(Object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            LinearGradientBrush lineBrush = new LinearGradientBrush(new Point(0, 0), new Point(50, 0),
                                            Color.FromArgb(255, 255, 255), Color.FromArgb(0, 0, 0));
            //填充整個窗口
            graphics.FillRectangle(lineBrush,this.ClientRectangle);
        }
    }

運行效果圖:

起始點是0,0 結束點是0,50的效果圖。從白色到黑色的漸變顏色段。超過50的部分,又開始重新漸變。

就好比在使用PS的時候,漸變顏色是白到黑,然後拉一根線。起始點是0,0,結束點是0,50。

那麼如果我用這個屬性的漸變畫刷在窗口隨便畫一個矩形是什麼樣的呢,看上面效果圖就可以知道。

比如 graphics.FillRectangle(lineBrush, 0, 0, 100, 100);這句的效果就是

這個矩形的畫刷填充跟第一張效果的對應的矩形區域是一樣的。

如果改變起始點和結束點的值,也可以看得出來。這其中是按着什麼方式來填充的。

比如起始點改成0,0,結束點改變50,50。

 private void formPaint(Object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            LinearGradientBrush lineBrush = new LinearGradientBrush(new Point(0, 0), new Point(50, 50),
                                            Color.FromArgb(255, 255, 255), Color.FromArgb(0, 0, 0));
            //填充整個窗口
            graphics.FillRectangle(lineBrush, this.ClientRectangle);
            Pen pen = new Pen(Color.FromArgb(0, 255,0));
            graphics.DrawRectangle(pen, 0, 0, 50, 50);
        }

那麼它的效果就是這樣:

在裏面繪製填充圖形,就是按上面的規則來顯示的。這個窗口並沒有禁止掉最大化功能,可以改變窗口大小以便更進一步的觀察。

多種顏色漸變

LinearGradientBrush類有個InterpolationColors屬性成員可以指定多種顏色漸變,這個成員是一個ColorBlend類型,像之前的漸變,都只能限於兩種顏色的漸變,使用了InterpolationColors後,就可以使用多種,如從紅到綠的漸變,然後綠到藍。

看示例:

   private void formPaint(Object sender, PaintEventArgs e)
        {
           //創建ColorBlend對象,指定多種顏色漸變信息
            ColorBlend color_blend=new ColorBlend();
            //指定幾種顏色
            color_blend.Colors=new Color[]{Color.Red,Color.Green,Color.Blue};
            //指定顏色的範圍
            color_blend.Positions=new float[]{0/3f,2/3f,3/3f};
            Rectangle rect=new Rectangle(0,0,200,100);
            //創建漸變畫刷
            LinearGradientBrush brush=
                new LinearGradientBrush(new Point(0,0),new Point(200,0),Color.White,Color.White);
        
            brush.InterpolationColors=color_blend;
            e.Graphics.FillRectangle(brush,rect);
        }

效果圖:

color_blend.Colors數組是指定有多少顏色漸變,比如上面就是紅綠藍,那麼漸變應該是這樣的,從紅到綠漸變,然後從綠到藍漸變。

color_blend.Positions指定顏色的範圍,如把那上面那個矩形寬度看作整體1的話,那麼紅到綠漸變,是從0/3f至2/3f完成的,也就是在這個

範圍內完成了紅到綠的漸變,那麼綠到藍漸變的範圍就是2/3f至3/3f。

如果要各佔一半的話,那就是color_blend.Positions=new float[]{0/2f,1/2f,2/2f};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章