實現過程:
(1) 新建窗體應用程序
(2) 添加一個MenuScrip控件;添加一個ToolScrip控件。
在ToolScrip控件中對每個單元,要將DisplayStyle屬性改為Text
(3)程序代碼。
1、新建菜單事件主要用白色清除窗體的背景,從而實現“文件新建”功能
[csharp] view plain copy private void 新建ToolStripMenuItem_Click(object sender, EventArgs e) { Graphics g = this.CreateGraphics(); g.Clear(backColor); toolStrip1.Enabled = true; //創建一個Bitmap theImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); editFileName = "新建文件"; //修改窗口標題 this.Text = "MyDraw\t" + editFileName; ig = Graphics.FromImage(theImage); ig.Clear(backColor); }
2、打開事件用於打開“打開文件”對話框,並選擇相應的圖片,將圖片繪制到窗體上.
[csharp] view plain copy private void 打開ToolStripMenuItem_Click(object sender, EventArgs e) { openFileDialog1.Multiselect = false; if (openFileDialog1.ShowDialog() == DialogResult.OK) { //修改窗口標題 this.Text = "MyDraw\t" + openFileDialog1.FileName; editFileName = openFileDialog1.FileName; theImage = Image.FromFile(openFileDialog1.FileName); Graphics g = this.CreateGraphics(); g.DrawImage(theImage, this.ClientRectangle); ig = Graphics.FromImage(theImage); ig.DrawImage(theImage, this.ClientRectangle); //ToolBar可以使用了 toolStrip1.Enabled = true; } }
(3) 保存菜單項的Click事件用於將窗體背景保存為BMP格式的圖片
[csharp] view plain copy private void 保存ToolStripMenuItem_Click(object sender, EventArgs e) { saveFileDialog1.Filter = "圖像(*.bmp)|*.bmp"; saveFileDialog1.FileName = editFileName; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { theImage.Save(saveFileDialog1.FileName, ImageFormat.Bmp); this.Text = "MyDraw\t" + saveFileDialog1.FileName; editFileName = saveFileDialog1.FileName; } }
(4) 在Paint事件中將Image中保存的圖像,繪制出來
[csharp] view plain copy private void Form1_Paint(object sender, PaintEventArgs e) { //將Image中保存的圖像,繪制出來 Graphics g = this.CreateGraphics(); if (theImage != null) { g.Clear(Color.White); g.DrawImage(theImage, this.ClientRectangle); } }
(5)添加Frm_Text.cs文字輸入框。
添加一個Window窗體,取名為Frm_Text,然后對窗體的屬性修改:
把FormBorderStyle屬性改為 None;
把Modifiers的屬性改為 Public
(6) 在窗體的MouseDown事件中,如果當前繪制的是字符串,在鼠標的當前位置顯示文本框;如果繪制的是圖開,設置圖形的起始位置。
[cpp] view plain copy private void Frm_Main_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { //如果選擇文字輸入,則打開strInput窗體 if (drawTool == drawTools.String) { Frm_Text inputBox = new Frm_Text(); inputBox.StartPosition = FormStartPosition.CenterParent; if (inputBox.ShowDialog() == DialogResult.OK) { Graphics g = this.CreateGraphics(); Font theFont = this.Font; g.DrawString(inputBox.textBox1.Text, theFont, new SolidBrush(foreColor), e.X, e.Y); ig.DrawString(inputBox.textBox1.Text, theFont, new SolidBrush(foreColor), e.X, e.Y); } } //如果開始繪制,則開始記錄鼠標位置 else if ((isDrawing = !isDrawing) == true) { startPoint = new Point(e.X, e.Y); oldPoint = new Point(e.X, e.Y); } } }
(7) 在窗體的MouseMove 事件中,根據鼠標移動的大小繪制指定的圖形.
[cpp] view plain copy private void Form1_MouseMove(object sender, MouseEventArgs e) { Graphics g; g = this.CreateGraphics(); if (isDrawing) { switch (drawTool) { case drawTools.None: break; case drawTools.Pen: //從上一個點到當前點繪制線段 g.DrawLine(new Pen(foreColor, 1), oldPoint, new Point(e.X, e.Y)); ig.DrawLine(new Pen(foreColor, 1), oldPoint, new Point(e.X, e.Y)); oldPoint.X = e.X; oldPoint.Y = e.Y; break; case drawTools.Line: //首先恢復此次操作之前的圖像,然后再添加Line this.Frm_Main_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle)); g.DrawLine(new Pen(foreColor, 1), startPoint, new Point(e.X, e.Y)); break; case drawTools.Ellipse: //首先恢復此次操作之前的圖像,然后再添加Ellipse this.Frm_Main_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle)); g.DrawEllipse(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); break; case drawTools.Rectangle: //首先恢復此次操作之前的圖像,然后再添加Rectangle this.Frm_Main_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle)); g.DrawRectangle(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); break; case drawTools.String: break; case drawTools.Rubber: //用背景色繪制寬線段 g.DrawLine(new Pen(backColor, 20), oldPoint, new Point(e.X, e.Y)); ig.DrawLine(new Pen(backColor, 20), oldPoint, new Point(e.X, e.Y)); oldPoint.X = e.X; oldPoint.Y = e.Y; break; } } }
(8) 在窗體的MouseUp事件中,根據用戶選擇的畫筆,繪制直線,橢圓或矩形等指定圖形。
[csharp] view plain copy private void Form1_MouseUp(object sender, MouseEventArgs e) { isDrawing = false; switch (drawTool) { case drawTools.Line: ig.DrawLine(new Pen(foreColor, 1), startPoint, new Point(e.X, e.Y)); break; case drawTools.Ellipse: ig.DrawEllipse(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); break; case drawTools.Rectangle: ig.DrawRectangle(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); break; } }
=============================================================================================================
這里解釋為什么在拉直線時線會跟着鼠標動,而用選擇畫筆時移動鼠標就會畫出線。
這里有兩個Graphics:
(1) 真實的場景graphics. 它它上面畫出的畫面就是我個看到的畫面。
eg:
private void Form1_Paint(object sender, PaintEventArgs e)
{
//將Image中保存的圖像,繪制出來
Graphics g = this.CreateGraphics();
(2)做為臨時存儲用的Graphic.
它在新建的時候創建:
[csharp] view plain copy //創建一個Bitmap theImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); editFileName = "新建文件"; //修改窗口標題 this.Text = "MyDraw\t" + editFileName; ig = Graphics.FromImage(theImage); ig.Clear(backColor);
顯示出來: 把theImage顯示出來就是把以前保存在ig里的東西顯示出來了
[csharp] view plain copy private void Frm_Main_Paint(object sender, PaintEventArgs e) { //將Image中保存的圖像,繪制出來 Graphics g = this.CreateGraphics(); if (theImage != null) { g.Clear(Color.White); g.DrawImage(theImage, this.ClientRectangle); } }
在Form1_MouseMove里
如果是畫筆,那么把圖像保存到了兩個graphic中,這樣我們可以看到移動的畫,最后也將顯示所有畫。
如果直線或矩形,那么只先畫到第一個graphics里,在鼠標放開時才畫到第二個graphic里。
通過本實例了解如何在窗體上繪制各種圖形,如矩形、橢圓、線條、文字等。運行效果如下: