




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、深入c# GDI+簡單繪圖的具體操作步驟 最近對GDI+這個東西接觸的比較多,也做了些簡單的實例,比如繪圖板,仿QQ截圖等 最早接觸這個類,是因為想做仿QQ截圖的效果巧的很,學會了如何做截圖后,.NET課堂上老師也正巧要講關(guān)于c#繪圖方面的知識,并且我自己又在網(wǎng)上學習金老師的培訓班,也是要用到這個類在學習中有一些體會,所以準備把這些體會記下來,因為內(nèi)容比較多,可能我會分幾次寫廢話不多說了,我們先來認識一下這個GDI+,看看它到底長什么樣.GDI+:Graphics Device Interface Plus也就是圖形設(shè)備接口,提供了各種豐富的圖形圖像處理功能;在C#.NET中,使用GDI+處理
2、二維(2D)的圖形和圖像,使用DirectX處理三維(3D)的圖形圖像,圖形圖像處理用到的主要命名空間是System . Drawing:提供了對GDI+基本圖形功能的訪問,主要有Graphics類、Bitmap類、從Brush類繼承的類、Font類、Icon類、Image類、Pen類、Color類等.大概了解了什么是GDI+后,我們來看一下繪圖要用到的主要工具,要畫圖,肯定要畫板吧,在C#中畫板可以通過Graphics這個類來創(chuàng)建,有了畫板,總得弄個筆什么之類的吧,不然怎么畫呀,難不成我們用手指畫.筆又可以分好多種類,比如鉛筆,畫刷等.它們的區(qū)別主要是鉛筆可以用來畫線條,而畫刷呢,嘿嘿,自己
3、考慮下.在c#中我們可以用Pen,Brush類來實現(xiàn)類似功能.顏料則自然是用Color類了.有了工具,我們就可以開始動手了!(所需命名空間:using System.Drawing;)實現(xiàn)效果:在空白窗體中畫基本圖形首先準備一個畫板:創(chuàng)建一個畫板主要有3種方式:A: 在窗體或控件的Paint事件中直接引用Graphics對象 B: 利用窗體或某個控件的CreateGraphics方法C: 從繼承自圖像的任何對象創(chuàng)建Graphics對象這次我們就先以A為例說明問題:復制代碼 代碼如下:private void Form1_Paint(object sender, PaintEventArgs e
4、) Graphics g = e.Graphics; /創(chuàng)建畫板,這里的畫板是由Form提供的. 然后,我們要只筆:復制代碼 代碼如下:private void Form1_Paint(object sender, PaintEventArgs e) Graphics g = e.Graphics; /創(chuàng)建畫板,這里的畫板是由Form提供的. Pen p = new Pen(Color.Blue, 2);/定義了一個藍色,寬度為的畫筆 接下來我們就可以來畫畫了.復制代碼 代碼如下:private void Form1_Paint(object sender, PaintEventArgs e)
5、 Graphics g = e.Graphics; /創(chuàng)建畫板,這里的畫板是由Form提供的. Pen p = new Pen(Color.Blue, 2);/定義了一個藍色,寬度為的畫筆 g.DrawLine(p, 10, 10, 100, 100);/在畫板上畫直線,起始坐標為(10,10),終點坐標為(100,100) g.DrawRectangle(p, 10, 10, 100, 100);/在畫板上畫矩形,起始坐標為(10,10),寬為,高為 g.DrawEllipse(p, 10, 10, 100, 100);/在畫板上畫橢圓,起始坐標為(10,10),外接矩形的寬為,高為 1.首
6、先我們來看下上一片中我們使用過的Pen.Pen的屬性主要有: Color(顏色),DashCap(短劃線終點形狀),DashStyle(虛線樣式),EndCap(線尾形狀), StartCap(線頭形狀),Width(粗細)等.我們可以用Pen 來畫虛線,帶箭頭的直線等復制代碼 代碼如下:Pen p = new Pen(Color.Blue, 5);/設(shè)置筆的粗細為,顏色為藍色Graphics g = this.CreateGraphics();/畫虛線p.DashStyle = DashStyle.Dot;/定義虛線的樣式為點g.DrawLine(p, 10, 10, 200, 10);/自
7、定義虛線p.DashPattern = new float 2, 1 ;/設(shè)置短劃線和空白部分的數(shù)組g.DrawLine(p, 10, 20, 200, 20);/畫箭頭,只對不封閉曲線有用p.DashStyle = DashStyle.Solid;/恢復實線p.EndCap = LineCap.ArrowAnchor;/定義線尾的樣式為箭頭g.DrawLine(p, 10, 30, 200, 30);g.Dispose();p.Dispose();以上代碼運行結(jié)果:2.接下來我們來看下Brush的使用作用:我們可以用畫刷填充各種圖形形狀,如矩形、橢圓、扇形、多邊形和封閉路徑等,主要有幾種不同
8、類型的畫刷:SolidBrush:畫刷最簡單的形式,用純色進行繪制HatchBrush:類似于 SolidBrush,但是可以利用該類從大量預(yù)設(shè)的圖案中選擇繪制時要使用的圖案,而不是純色TextureBrush:使用紋理(如圖像)進行繪制LinearGradientBrush:使用沿漸變混合的兩種顏色進行繪制PathGradientBrush :基于編程者定義的唯一路徑,使用復雜的混合色漸變進行繪制我們這里只是簡單介紹使用其中的幾種:復制代碼 代碼如下:Graphics g = this.CreateGraphics();Rectangle rect = new Rectangle(10, 1
9、0, 50, 50);/定義矩形,參數(shù)為起點橫縱坐標以及其長和寬/單色填充SolidBrush b1 = new SolidBrush(Color.Blue);/定義單色畫刷 g.FillRectangle(b1, rect);/填充這個矩形/字符串g.DrawString(字符串, new Font(宋體, 10), b1, new PointF(90, 10);/用圖片填充TextureBrush b2 = new TextureBrush(Image.FromFile(e:picture1.jpg);rect.Location = new Point(10, 70);/更改這個矩形的起點
10、坐標rect.Width = 200;/更改這個矩形的寬來rect.Height = 200;/更改這個矩形的高g.FillRectangle(b2, rect);/用漸變色填充rect.Location = new Point(10, 290);LinearGradientBrush b3 = new LinearGradientBrush(rect, Color.Yellow , Color.Black , LinearGradientMode.Horizontal);g.FillRectangle(b3, rect);運行效果圖: 3.坐標軸變換在winform中的坐標軸和我們平時接觸的
11、平面直角坐標軸不同,winform中的坐標軸方向完全相反:窗體的左上角為原點(0,0),水平向左則X增大,垂直下向則Y增大接下來,我們來實際操作下,通過旋轉(zhuǎn)坐標軸的方向來畫出不同角度的圖案,或通過更改坐標原點的位置來平衡坐標軸的位置.復制代碼 代碼如下:Graphics g = this.CreateGraphics();/單色填充/SolidBrush b1 = new SolidBrush(Color.Blue);/定義單色畫刷 Pen p = new Pen(Color.Blue,1);/轉(zhuǎn)變坐標軸角度for (int i = 0; i 90; i+) g.RotateTransform
12、(i);/每旋轉(zhuǎn)一度就畫一條線 g.DrawLine(p, 0, 0, 100, 0); g.ResetTransform();/恢復坐標軸坐標/平移坐標軸g.TranslateTransform(100, 100);g.DrawLine(p, 0, 0, 100, 0);g.ResetTransform();/先平移到指定坐標,然后進行度旋轉(zhuǎn)g.TranslateTransform(100,200);for (int i = 0; i 8; i+)g.RotateTransform(45);g.DrawLine(p, 0, 0, 100, 0);接下來看看這是如何做到的.思路:聊天窗體上有一
13、個截圖按鈕,點擊按鈕后,程序?qū)⒄麄€屏幕畫在一個新的全屏窗體上,然后顯示這個窗體.因為是全屏的窗體,并且隱藏了菜單欄、工具欄等,所以在我們看來就好像是一個桌面的截圖,然后在這個新窗體上畫矩形,最后保存矩形中的內(nèi)容并顯示在原來的聊天窗體中.步驟:A.新建一個窗體命名為Catch.然后設(shè)置這個窗體的FormBorderStyle為None,WindowState為MaximizedB.我們對代碼進行編輯:復制代碼 代碼如下:using System;using System.Collections.Generic;using System.ComponentModel;using System.Da
14、ta;using System.Drawing;using System.Text;using System.Windows.Forms;namespace Client public partial class Catch : Form public Catch() InitializeComponent(); 用戶變量#region 用戶變量 private Point DownPoint = Point.Empty;/記錄鼠標按下坐標,用來確定繪圖起點 private bool CatchFinished = false;/用來表示是否截圖完成 private bool CatchSta
15、rt = false;/表示截圖開始 private Bitmap originBmp;/用來保存原始圖像 private Rectangle CatchRect;/用來保存截圖的矩形 #endregion /窗體初始化操作 private void Catch_Load(object sender, EventArgs e) this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); this.UpdateSty
16、les(); /以上兩句是為了設(shè)置控件樣式為雙緩沖,這可以有效減少圖片閃爍的問題,關(guān)于這個大家可以自己去搜索下 originBmp = new Bitmap(this.BackgroundImage);/BackgroundImage為全屏圖片,我們另用變量來保存全屏圖片 /鼠標右鍵點擊結(jié)束截圖 private void Catch_MouseClick(object sender, MouseEventArgs e) if (e.Button = MouseButtons.Right) this.DialogResult = DialogResult.OK; this.Close(); /鼠
17、標左鍵按下時動作 private void Catch_MouseDown(object sender, MouseEventArgs e) if (e.Button = MouseButtons.Left) if (!CatchStart) /如果捕捉?jīng)]有開始 CatchStart = true; DownPoint = new Point(e.X, e.Y);/保存鼠標按下坐標 private void Catch_MouseMove(object sender, MouseEventArgs e) if (CatchStart) /如果捕捉開始 Bitmap destBmp = (Bit
18、map)originBmp.Clone();/新建一個圖片對象,并讓它與原始圖片相同 Point newPoint = new Point(DownPoint.X, DownPoint.Y);/獲取鼠標的坐標 Graphics g = Graphics.FromImage(destBmp);/在剛才新建的圖片上新建一個畫板 Pen p = new Pen(Color.Blue,1); int width = Math.Abs(e.X - DownPoint.X), height = Math.Abs(e.Y - DownPoint.Y);/獲取矩形的長和寬 if (e.X DownPoint.
19、X) newPoint.X = e.X; if (e.Y DownPoint.Y) newPoint.Y = e.Y; CatchRect = new Rectangle(newPoint,new Size(width,height);/保存矩形 g.DrawRectangle(p,CatchRect);/將矩形畫在這個畫板上 g.Dispose();/釋放目前的這個畫板 p.Dispose(); Graphics g1 = this.CreateGraphics();/重新新建一個Graphics類 /如果之前那個畫板不釋放,而直接g=this.CreateGraphics()這樣的話無法釋
20、放掉第一次創(chuàng)建的g,因為只是把地址轉(zhuǎn)到新的g了如同string一樣 g1 = this.CreateGraphics();/在整個全屏窗體上新建畫板 g1.DrawImage(destBmp,new Point(0,0);/將剛才所畫的圖片畫到這個窗體上 /這個也可以屬于二次緩沖技術(shù),如果直接將矩形畫在窗體上,會造成圖片抖動并且會有無數(shù)個矩形 g1.Dispose(); destBmp.Dispose();/要及時釋放,不然內(nèi)存將會被大量消耗 private void Catch_MouseUp(object sender, MouseEventArgs e) if (e.Button = M
21、ouseButtons.Left) if (CatchStart) CatchStart = false; CatchFinished = true; /鼠標雙擊事件,如果鼠標位于矩形內(nèi),則將矩形內(nèi)的圖片保存到剪貼板中 private void Catch_MouseDoubleClick(object sender, MouseEventArgs e) if (e.Button = MouseButtons.Left&CatchFinished) if (CatchRect.Contains(new Point(e.X, e.Y) Bitmap CatchedBmp = new Bitmap
22、(CatchRect.Width, CatchRect.Height);/新建一個于矩形等大的空白圖片 Graphics g = Graphics.FromImage(CatchedBmp); g.DrawImage(originBmp, new Rectangle(0, 0, CatchRect.Width, CatchRect.Height), CatchRect, GraphicsUnit.Pixel); /把orginBmp中的指定部分按照指定大小畫在畫板上 Clipboard.SetImage(CatchedBmp);/將圖片保存到剪貼板 g.Dispose(); CatchFini
23、shed = false; this.BackgroundImage = originBmp; CatchedBmp.Dispose(); this.DialogResult = DialogResult.OK; this.Close(); C.創(chuàng)建了Catch窗體后,我們在截圖按鈕(位于聊天窗體上)上加入以下事件:復制代碼 代碼如下: private void bCatch_Click(object sender, EventArgs e) if (bCatch_HideCurrent.Checked) this.Hide();/隱藏當前窗體 Thread.Sleep(50);/讓線程睡眠一
24、段時間,窗體消失需要一點時間 Catch CatchForm = new Catch(); Bitmap CatchBmp = new Bitmap(Screen.AllScreens0.Bounds.Width, Screen.AllScreens0.Bounds.Height);/新建一個和屏幕大小相同的圖片 Graphics g = Graphics.FromImage(CatchBmp); g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens0.Bounds.Width, Screen
25、.AllScreens0.Bounds.Height);/保存全屏圖片 CatchForm.BackgroundImage = CatchBmp;/將Catch窗體的背景設(shè)為全屏時的圖片 if (CatchForm.ShowDialog() = DialogResult.OK) /如果Catch窗體結(jié)束,就將剪貼板中的圖片放到信息發(fā)送框中 IDataObject iData = Clipboard.GetDataObject(); DataFormats.Format myFormat = DataFormats.GetFormat(DataFormats.Bitmap); if (iData
26、.GetDataPresent(DataFormats.Bitmap) richtextbox1.Paste(myFormat); Clipboard.Clear();/清除剪貼板中的對象 this.Show();/重新顯示窗體 這樣我們的截圖功能便完成了我想對于初學者來說如何消去第一次繪制的圖片是個比較困難的問題如果沒有采取措施,你會發(fā)現(xiàn)只要你鼠標移動,就會畫一個矩形,這樣便會出現(xiàn)N多的矩形,而我們只是要最后的那一個一般解決這種問題的方法有兩種:1.就是在繪制第二個圖形時,我們先用與底色相同的顏色將上次繪制的圖形重新繪制一下但這往往需要底色為純色時使用2.我們并不直接將圖形畫在畫板上,我們用
27、一個圖片A來保存原畫板上的圖片然后再新建一個與圖片A相同的圖片B,將我們要繪制的圖形畫在該圖片B上,然后再將該圖片B畫在畫板上這樣圖片A并沒有被改變于是第二次畫的時候我們還是同樣新建一個與圖片A相同的圖片進行繪制那么上一次的圖形就不會被保留下來問題也就解決了 g.Dispose();4.最后我們來看下Graphics這個畫板上我們還可以畫什么其實我們上面用到的都是在畫一些簡單的圖形,直線,矩形,扇形,圓孤等,我們還可以用它來繪制圖片,這可以用它的DrawImage方法.這里我不詳細講解,大家有興趣可以自己去MSDN了解下.我們后面會講到的截圖就會用到這個方法.個人認為如果想做一個功能強大的繪圖
28、工具,那么單純掌握GDI還遠遠不夠,我的目前也只能做一個比較簡單的繪圖工具了不足之處,歡迎大家討論!先來看一下最終效果吧:主要實現(xiàn)功能:畫直線,矩形,橡皮,圓形,切換顏色,打開圖片,保存圖片,清除圖片,手動調(diào)節(jié)畫布大小;軟件剛啟動時,為一張空白畫布,我們可以直接在畫布上繪畫,也可以通過菜單中的“打開”,導入一張圖片,然后我們就可以在這張圖片上進行繪制。平臺:VS2005 WINFORM由于代碼過多,在這里只簡要介紹下制作步驟,提供大家工程下載1.對整個界面進行布局2.實現(xiàn)繪圖工具的功能3.實現(xiàn)顏色拾取的功能,這里我們直接拿上次寫的自定義控件來用4.實現(xiàn)菜單功能5.實現(xiàn)手動調(diào)節(jié)畫布大小的功能6.
29、測試 實現(xiàn)繪圖工具的功能為了讓代碼藕合度小點,稍許用了些設(shè)計模式,因為不是很會,所以代碼還是有點亂亂的,嘿嘿!關(guān)于繪圖工具的這些功能塊全部寫在了DrawTools這個類里那么在主窗體中,只需要調(diào)用這個類來完成繪制就行了,而不需要過多的涉及到具體的繪圖代碼。繪圖工具這個類提供的主要工具就是:鉛筆、橡皮、直線、矩形、圓形、實心矩形、實心圓形。關(guān)于這些功能塊的代碼,并不難,只要大家對認真看過前幾篇內(nèi)容,那應(yīng)該都看得懂。這里要注意以下幾點:.如何防止記錄不必要的繪圖過程中的痕跡?這個問題在第三篇中有提到過,大家不妨先去看看那一篇。為了讓代碼看起來可讀性高點,我設(shè)置了兩個Image變量,finishin
30、gImg用來保存繪圖過程中的痕跡,orginalImg用來保存已完成的繪圖過程和初始時的背景圖片。2.這個類如何與主窗體進行通信?當然如果直接將這些功能塊寫在主窗體中自然沒有這個問題。但是那樣代碼會顯得很混雜,如果只是工具代碼出現(xiàn)問題就需要改整個項目。我在這里通過定義方法和屬性,讓主窗體通過給屬性賦值將畫板畫布以及顏色什么的信息傳給這個工具類,然后通過調(diào)用相應(yīng)的工具方法來使用這些工具。3.關(guān)鍵屬性要想讓這些工具能正常使用,必須傳遞給他以下幾樣東西:目標畫板(也就是picturebox),繪圖顏色,原始畫布。實現(xiàn)菜單功能這里就需要我們對文件的操作有一點了解,大家可以去查一下相關(guān)資料。難點主要就是
31、“打開”這個菜單項的實現(xiàn)我們要實現(xiàn)將打開后的圖片在修改后重新保存就必須讓文件在打開后就能關(guān)閉,否則就會因為文件打開而無法覆蓋原文件。就會導致編譯時彈出“GDI 一般性錯誤”。所以根據(jù)網(wǎng)上其它朋友的做法就是先將打開的圖片通過GDI+將圖片畫到另一個畫布上,然后及時關(guān)閉打開的圖片和用來繪制該圖片的畫板。復制代碼 代碼如下:private void openPic_Click(object sender, EventArgs e) OpenFileDialog ofd = OpenFileDialog();/實例化文件打開對話框 ofd.Filter = JPG|*.jpg|Bmp|*.bmp|所有
32、文件|*.*;/設(shè)置對話框打開文件的括展名 if (ofd.ShowDialog() = DialogResult.OK) Bitmap bmpformfile = new Bitmap(ofd.FileName);/獲取打開的文件 panel2.AutoScrollPosition = new Point(0,0);/將滾動條復位 pbImg.Size = bmpformfile.Size;/調(diào)整繪圖區(qū)大小為圖片大小 reSize.Location = new Point(bmpformfile.Width, bmpformfile.Height);/reSize為我用來實現(xiàn)手動調(diào)節(jié)畫布大小
33、用的 /因為我們初始時的空白畫布大小有限,打開操作可能引起畫板大小改變,所以要將畫板重新傳入工具類 dt.DrawTools_Graphics = pbImg.CreateGraphics(); Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height); Graphics g = Graphics.FromImage(bmp); g.FillRectangle(new SolidBrush(pbImg.BackColor), new Rectangle(0, 0, pbImg.Width, pbImg.Height);/不使用這句話,那么這個bmp的
34、背景就是透明的 g.DrawImage(bmpformfile, 0, 0,bmpformfile.Width,bmpformfile.H);/將圖片畫到畫板上 g.Dispose();/釋放畫板所占資源 /不直接使用pbImg.Image = Image.FormFile(ofd.FileName)是因為這樣會讓圖片一直處于打開狀態(tài),也就無法保存修改后的圖片 bmpformfile.Dispose();/釋放圖片所占資源 g = pbImg.CreateGraphics(); g.DrawImage(bmp, 0, 0); g.Dispose(); dt.OrginalImg = bmp;
35、bmp.Dispose(); sFileName = ofd.FileName;/儲存打開的圖片文件的詳細路徑,用來稍后能覆蓋這個文件 ofd.Dispose(); 清除圖像其實就是用白色填充整個畫布其它的都比較簡單,這就不具體講了。實現(xiàn)手動調(diào)節(jié)畫布大小網(wǎng)上有人說使用API,但是個人覺得還是使用其它控件幫忙比較簡單,至少我們還看得懂。思路:放置一個picturebox1(尺寸為5*5),將它固定在主畫板的右下角,然后改變鼠標進入時的Cursor為箭頭形狀,設(shè)置鼠標按下移動時的事件,讓該picturebox1 跟隨鼠標移動。當鼠標松開時,將主畫板的右下角坐標調(diào)整為picturebox1的坐標。下面來看下代碼:其中的reSize就是我們用來幫忙的picturebox控件復制代碼 代碼如下:private bool bReSize = false;/是否改變畫布大小
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 私人教練服務(wù)合同
- 食品供應(yīng)鏈全程監(jiān)控信息化項目協(xié)議
- 專業(yè)醫(yī)療器械購銷合同條款約定
- 農(nóng)村合作農(nóng)機購置補貼協(xié)議
- 房屋租賃擔保合同書
- 農(nóng)家樂轉(zhuǎn)讓租金合同
- 內(nèi)業(yè)資料承包合同
- 借款合同與抵押合同有何不同
- 單項木工承包合同
- 個人汽車貸款擔保合同協(xié)議
- 建筑安全員A證考試題庫附答案
- 綠色化學原理課件
- 《數(shù)獨》(第一課)教學課件
- 干部作風建設(shè) 講義課件
- 車輛過戶證明
- “供應(yīng)商融資安排”會計列報、披露問題研究
- 中國黃金集團公司黃金工業(yè)項目初步設(shè)計
- 裝修客戶需求表實用
- DB32∕T 3370-2018 雙孢蘑菇栽培基質(zhì)隧道發(fā)酵技術(shù)規(guī)程
- 中醫(yī)院新技術(shù)、新項目申請表、審批表及年季度工作報告表范本
- 2022年五級音樂吹起羌笛跳鍋莊教案反思
評論
0/150
提交評論