程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C# GDI+簡單繪圖(三)

C# GDI+簡單繪圖(三)

編輯:關於C#

感謝大家的支持,這幾天從早忙到晚,一個字累呀!!!現在挺困的,但是又不習慣這麼早睡覺,哎~~還是利用這個時間繼續來寫第三篇吧.

前兩篇已經基本向大家介紹了繪圖的基本知識.那麼,我就用我們上兩篇所學的,做幾個例子.

我們先來做一個簡單的----仿QQ截圖,關於這個的例子其實網上已經有這方面的資料了,但是為了文章的完整性,還是覺得有必要講解.

我們先來看一下效果:

(圖1)

(圖2)

接下來看看這是如何做到的.

思路:聊天窗體上有一個截圖按鈕,點擊按鈕後,程序將整個屏幕畫在一個新的全屏窗體上,然後顯示這個窗體.因為是全屏的窗體,並且隱藏了菜單欄、工具欄等,所以在我們看來就好像是一個桌面的截圖,然後在這個新窗體上畫矩形,最後保存矩形中的內容並顯示在原來的聊天窗體中.

步驟:

A.新建一個窗體.命名為Catch.然後設置這個窗體的FormBorderStyle為None,WindowState為Maximized.

B.我們對代碼進行編輯:

using System;
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();
    }

用戶變量#region 用戶變量

private Point DownPoint = Point.Empty;//記錄鼠標按下坐標,用來確定繪圖起點
    private bool CatchFinished = false;//用來表示是否截圖完成
    private bool CatchStart = 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.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畫板的程序.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved