C# GDI+ 简单绘图 (三)
前兩篇已經基本向大家介紹了繪圖的基本知識.那么,我就用我們上兩篇所學的,做幾個例子.
我們先來做一個簡單的----仿QQ截圖,關于這個的例子其實網上已經有這方面的資料了,但是為了文章的完整性,還是覺得有必要講解.
我們先來看一下效果:
??????????????????????????????
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????(圖1)
??????????????????????????????????????????????????????
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????(圖2)
接下來看看這是如何做到的.
思路:聊天窗體上有一個截圖按鈕,點擊按鈕后,程序將整個屏幕畫在一個新的全屏窗體上,然后顯示這個窗體.因為是全屏的窗體,并且隱藏了菜單欄、工具 欄等,所以在我們看來就好像是一個桌面的截圖,然后在這個新窗體上畫矩形,最后保存矩形中的內容并顯示在原來的聊天窗體中.
步驟:
A.新建一個窗體.命名為Catch.然后設置這個窗體的FormBorderStyle為None,WindowState為Maximized.
B.我們對代碼進行編輯:
using?System.Collections.Generic;
using?System.ComponentModel;
using?System.Data;
using?System.Drawing;
using?System.Text;
using?System.Windows.Forms;
namespace?Client
{
????public?partial?class?Catch?:?Form
????{
????????public?Catch()
????????{
????????????InitializeComponent();
????????}
????????用戶變量
????????//窗體初始化操作
????????private?void?Catch_Load(object?sender,?EventArgs?e)
????????{
????????????this.SetStyle(ControlStyles.OptimizedDoubleBuffer?|?ControlStyles.AllPaintingInWmPaint?|?ControlStyles.UserPaint,?true);
????????????this.UpdateStyles();
????????????//以上兩句是為了設置控件樣式為雙緩沖,這可以有效減少圖片閃爍的問題,關于這個大家可以自己去搜索下
????????????originBmp?=?new?Bitmap(this.BackgroundImage);//BackgroundImage為全屏圖片,我們另用變量來保存全屏圖片
????????}
????????//鼠標右鍵點擊結束截圖
????????private?void?Catch_MouseClick(object?sender,?MouseEventArgs?e)
????????{
????????????if?(e.Button?==?MouseButtons.Right)
????????????{
????????????????this.DialogResult?=?DialogResult.OK;
????????????????this.Close();
????????????}
????????}
????????//鼠標左鍵按下時動作
????????private?void?Catch_MouseDown(object?sender,?MouseEventArgs?e)
????????{
????????????if?(e.Button?==?MouseButtons.Left)
????????????{
????????????????if?(!CatchStart)
????????????????{//如果捕捉沒有開始
????????????????????CatchStart?=?true;
????????????????????DownPoint?=?new?Point(e.X,?e.Y);//保存鼠標按下坐標
????????????????}
????????????}
????????}
????????private?void?Catch_MouseMove(object?sender,?MouseEventArgs?e)
????????{
????????????if?(CatchStart)
????????????{//如果捕捉開始
????????????????Bitmap?destBmp?=?(Bitmap)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.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()這樣的話無法釋放掉第一次創建的g,因為只是把地址轉到新的g了.如同string一樣
????????????????g1?=?this.CreateGraphics();//在整個全屏窗體上新建畫板
????????????????g1.DrawImage(destBmp,new?Point(0,0));//將剛才所畫的圖片畫到這個窗體上
????????????????//這個也可以屬于二次緩沖技術,如果直接將矩形畫在窗體上,會造成圖片抖動并且會有無數個矩形.
????????????????g1.Dispose();
????????????????destBmp.Dispose();//要及時釋放,不然內存將會被大量消耗
????????????????
????????????}
????????}
????????private?void?Catch_MouseUp(object?sender,?MouseEventArgs?e)
????????{
????????????if?(e.Button?==?MouseButtons.Left)
????????????{
????????????????if?(CatchStart)
????????????????{
????????????????????CatchStart?=?false;
????????????????????CatchFinished?=?true;
??????????????????
????????????????}
????????????}
????????}
????????//鼠標雙擊事件,如果鼠標位于矩形內,則將矩形內的圖片保存到剪貼板中
????????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(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();
????????????????????CatchFinished?=?false;
????????????????????this.BackgroundImage?=?originBmp;
????????????????????CatchedBmp.Dispose();
????????????????????this.DialogResult?=?DialogResult.OK;
????????????????????this.Close();
????????????????}
????????????}
????????}
????}
}
C.創建了Catch窗體后,我們在截圖按鈕(位于聊天窗體上)上加入以下事件:
????????private?void?bCatch_Click(object?sender,?EventArgs?e)????????{
????????????if?(bCatch_HideCurrent.Checked)
????????????{
????????????????this.Hide();//隱藏當前窗體
????????????????Thread.Sleep(50);//讓線程睡眠一段時間,窗體消失需要一點時間
????????????????Catch?CatchForm?=?new?Catch();
????????????????Bitmap?CatchBmp?=?new?Bitmap(Screen.AllScreens[0].Bounds.Width,?Screen.AllScreens[0].Bounds.Height);//新建一個和屏幕大小相同的圖片?????????
????????????????Graphics?g?=?Graphics.FromImage(CatchBmp);
????????????????g.CopyFromScreen(new?Point(0,?0),?new?Point(0,?0),?new?Size(Screen.AllScreens[0].Bounds.Width,?Screen.AllScreens[0].Bounds.Height));//保存全屏圖片
????????????????CatchForm.BackgroundImage?=?CatchBmp;//將Catch窗體的背景設為全屏時的圖片
????????????????if?(CatchForm.ShowDialog()?==?DialogResult.OK)
????????????????{//如果Catch窗體結束,就將剪貼板中的圖片放到信息發送框中
????????????????????IDataObject?iData?=?Clipboard.GetDataObject();
????????????????????DataFormats.Format?myFormat?=?DataFormats.GetFormat(DataFormats.Bitmap);
????????????????????if?(iData.GetDataPresent(DataFormats.Bitmap))
????????????????????{
????????????????????????richtextbox1.Paste(myFormat);
????????????????????????Clipboard.Clear();//清除剪貼板中的對象
????????????????????}
????????????????????this.Show();//重新顯示窗體
????????????????}
????????????}
????????} 這樣我們的截圖功能便完成了.
我想對于初學者來說如何消去第一次繪制的圖片是個比較困難的問題.如果沒有采取措施,你會發現只要你鼠標移動,就會畫一個矩形,這樣便會出現N多的矩形,而我們只是要最后的那一個.
一般解決這種問題的方法有兩種:
1.就是在繪制第二個圖形時,我們先用與底色相同的顏色將上次繪制的圖形重新繪制一下.但這往往需要底色為純色時使用.
2.我們并不直接將圖形畫在畫板上,我們用一個圖片A來保存原畫板上的圖片.然后再新建一個與圖片A相同的圖片B,將我們要繪制的圖形畫在該圖片B 上,然后再將該圖片B畫在畫板上.這樣圖片A并沒有被改變.于是第二次畫的時候我們還是同樣新建一個與圖片A相同的圖片進行繪制.那么上一次的圖形就不會 被保留下來.問題也就解決了.
下一次,向大家介紹如何做一個仿windows畫板的程序.
轉載于:https://www.cnblogs.com/zzh1236/archive/2012/06/29/2570050.html
總結
以上是生活随笔為你收集整理的C# GDI+ 简单绘图 (三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上海欢乐谷搜包吗
- 下一篇: libcurl 客户端实例