截圖工具-開發過程隨談


 

半路出家,沒有經過系統的學習。寫代碼的時候心里總是沒底,自己都不相信自己寫的這些代碼可以執行。這是目前自己的一個狀態。2015-02-04日記!

一個偶然的機會,得知公司很多員工不會使用windows截圖。然而在生產線上的員工是不能連接網絡,所以不能使用qq截圖。頓時想自己寫一個截圖工具。以便大家可以記錄下異常時的情形!

有了這樣一個想法,但是怎么去實現呢?沒有啥好的新創意。但是國人有一個優秀的品質,不會創新咱就仿制唄。瞄上咱最熟悉的qq截圖。

首先分析qq截圖的過程=》

========點擊截圖按鈕--》進入截圖的狀態--》按下鼠標左鍵開始截圖--》移動鼠標【起點和終點之間組成的矩形框便是截圖區間】--》彈起鼠標左鍵截圖結束--》截圖保存到剪切板--》截圖完成--》cltr+v粘貼到界面

===========================》按下右鍵結束截圖狀態

那么問題來了。進入截圖狀態。怎么實現呢?

怎樣讓桌面狀態保持不變。這個是怎么做出來的效果呢?

大家是不是想到了,我們看到的就是一張圖片。然后把這張圖片放在了一個窗體中,然后把這個窗體置頂了。所以。。。這樣是不是基本上吻合了那個狀態呢?

那就這樣的思路做吧!

按照上面的想法,我們有兩個窗體一個是我們操作的窗體,一個是截圖的窗體!

這個是用戶操作頁面的窗體。在這個頁面的代碼主要就是兩個事件

截圖事件

 1  private void button1_Click(object sender, EventArgs e)
 2         {
 3             
 4             // 新建一個和屏幕大小相同的圖片
 5             Bitmap CatchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
 6 
 7             // 創建一個畫板,讓我們可以在畫板上畫圖
 8             // 這個畫板也就是和屏幕大小一樣大的圖片
 9             // 我們可以通過Graphics這個類在這個空白圖片上畫圖
10             Graphics g = Graphics.FromImage(CatchBmp);
11 
12             // 把屏幕圖片拷貝到我們創建的空白圖片 CatchBmp中
13             g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height));
14 
15             // 創建截圖窗體
16             screen = new Form2();
17 
18             // 指示窗體的背景圖片為屏幕圖片
19             screen.BackgroundImage = CatchBmp;
20             // 顯示窗體
21             //cutter.Show();
22             // 如果Cutter窗體結束,則從剪切板獲得截取的圖片,並顯示在聊天窗體的發送框中
23             if (screen.ShowDialog() == DialogResult.OK)
24             {
25                 IDataObject iData = Clipboard.GetDataObject();
26                 DataFormats.Format format = DataFormats.GetFormat(DataFormats.Bitmap);
27                 if (iData.GetDataPresent(DataFormats.Bitmap))
28                 {
29                     richTextBox1.Paste(format);
30 
31                     // 清楚剪貼板的圖片
32                     //Clipboard.Clear();
33                 }
34             }
35         }

然后就是圖片的保存操作

 1  /// <summary>  2 /// 圖片保存  3 /// </summary>  4 /// <param name="sender"></param>  5 /// <param name="e"></param>  6 private void button2_Click(object sender, EventArgs e)  7  {  8 if (DialogResult.No==MessageBox.Show("確認保存圖片?","",MessageBoxButtons.YesNo,MessageBoxIcon.Question,MessageBoxDefaultButton.Button1))  9  { 10 return; 11  } 12 13 for (int i = 0; i < richTextBox1.TextLength; i++) 14  { 15 richTextBox1.Select(i, 1); 16 RichTextBoxSelectionTypes rt = richTextBox1.SelectionType; 17 if (rt==RichTextBoxSelectionTypes.Object) 18  { 19  richTextBox1.Copy(); 20 Image img = Clipboard.GetImage(); 21 if (img != null) 22  { 23 //System.IO.Directory path = new System.IO.Directory("D:\\新建文件夾2",); 24 if (!System.IO.Directory.Exists("D:\\黑貓截圖")) 25  { 26 System.IO.Directory.CreateDirectory("D:\\黑貓截圖"); 27  } 28 29 img.Save("D:\\黑貓截圖\\" + DateTime.Now.ToString("YYYY-MM-DDHHmmss") + i.ToString() + ".png"); 30  img.Dispose(); 31  } 32 33  } 34  } 35  richTextBox1.Clear(); 36 Thread t = new Thread(message); 37  t.Start(); 38 label1.Text = str; 39 label1.ForeColor = Color.Green; 40 //for (int i = 0; i < 5; i++) 41 //{ 42 // Thread.Sleep(1000); 43 //} 44 //label1.Text = ""; 45  } 46 47 private delegate void FlushClient();//代理 48 49 50 public static string str = "保存成功!"; 51 private void message() 52  { 53 Thread.Sleep(5000); 54  retext(); 55  } 56 57 private void retext() 58  { 59 if (this.label1.InvokeRequired) 60  { 61 FlushClient fc = new FlushClient(retext); 62 this.Invoke(fc);//通過代理調用刷新方法 63 64  } 65 else { label1.Text = ""; } 66 }

這里有一個小地方讓我弄了很久的,就是那個保存的狀態lable1 怎樣才能動態顯示。

如果直接給lable1 賦值,然后給主線程延時 Thread.Sleep(5000);lable1.Text=“”; 這樣的話就看不到任何效果。

考慮到多線程。新建線程。但是運行就報【不能訪問不是該線程所生成的控件】的錯誤。

又學到一個知識就是多線程訪問控件。

設置代理。至於里面的原理,還有待研究研究。(初次在開發上使用多線程)

然后就是 截圖頁面了

這個窗體沒有什么特別的,就是沒有邊框即設置 FormBorderStyle 的屬性為None

但是重點也是在這個窗體上。因為這個窗體打開,就表示我們已經開始進入截圖狀態。然后就是將上面說的步驟寫成事件

 1    /// <summary>
 2         /// 鼠標左鍵按下事件
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void Form2_MouseDown(object sender, MouseEventArgs e)
 7         {
 8             //如果鼠標左鍵按下,表示開始截圖
 9             if (e.Button == MouseButtons.Left)
10             {
11                 //如果捕捉沒有開始
12                 if (!CatchStart)
13                 {
14                     CatchStart = true;
15                     //保存此時鼠標按下的坐標
16                     DownPoint = new Point(e.X, e.Y);
17                 }
18             }
19         }
鼠標左鍵按下事件
 1         /// <summary>
 2         /// 鼠標移動事件
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void Form2_MouseMove(object sender, MouseEventArgs e)
 7         {
 8             //確保截圖開始
 9             if (CatchStart)
10             {
11                 //新建一個圖片對象,讓它與屏幕圖片相同
12                 Bitmap copyBmp = (Bitmap)originBmp.Clone();
13 
14                 //獲取鼠標按下的坐標
15                 Point newPoint = new Point(DownPoint.X, DownPoint.Y);
16 
17                 //新建畫板和畫筆
18                 Graphics g = Graphics.FromImage(copyBmp);
19                 Pen p = new Pen(Color.Red, 1);
20 
21                 //獲取矩形的長寬  Math.Abs--返回有符號32位整數的絕對值
22                 int width = Math.Abs(e.X - DownPoint.X);
23                 int height = Math.Abs(e.Y - DownPoint.Y);
24 
25                 if (e.X < DownPoint.X)
26                 {
27                     newPoint.X = e.X;
28                 }
29                 if (e.Y < DownPoint.Y)
30                 {
31                     newPoint.Y = e.Y;
32                 }
33 
34                 CatchRectangle = new Rectangle(newPoint, new Size(width, height));
35 
36                 //將矩形畫在畫板上
37                 g.DrawRectangle(p, CatchRectangle);
38 
39                 // 釋放目前的畫板
40                 g.Dispose();
41                 p.Dispose();
42 
43                 // 從當前窗體創建新的畫板
44                 Graphics g1 = this.CreateGraphics();
45 
46                 // 將剛才所畫的圖片畫到截圖窗體上
47                 // 為什么不直接在當前窗體畫圖呢?
48                 // 如果自己解決將矩形畫在窗體上,會造成圖片抖動並且有無數個矩形
49                 // 這樣實現也屬於二次緩沖技術
50                 g1.DrawImage(copyBmp, new Point(0, 0));
51                 g1.Dispose();
52                 // 釋放拷貝圖片,防止內存被大量消耗
53                 copyBmp.Dispose();
54             }
55         }
鼠標移動事件
 1  /// <summary>  2 /// 鼠標左鍵彈起事件  3 /// </summary>  4 /// <param name="sender"></param>  5 /// <param name="e"></param>  6 private void Form2_MouseUp(object sender, MouseEventArgs e)  7  {  8 if (e.Button == MouseButtons.Left)  9  { 10 // 如果截圖已經開始,鼠標左鍵彈起設置截圖完成 11 if (CatchStart) 12  { 13 CatchStart = false; 14 CatchFinished = true; 15  } 16  } 17 }
左鍵彈起事件
 1  /// <summary>
 2         /// 鼠標左鍵雙擊事件
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void Form2_MouseDoubleClick(object sender, MouseEventArgs e)
 7         {
 8             if (e.Button == MouseButtons.Left && CatchFinished)
 9             {
10                 // 新建一個與矩形一樣大小的空白圖片
11                 Bitmap CatchedBmp = new Bitmap(CatchRectangle.Width, CatchRectangle.Height);
12 
13                 Graphics g = Graphics.FromImage(CatchedBmp);
14 
15                 // 把originBmp中指定部分按照指定大小畫到空白圖片上
16                 // CatchRectangle指定originBmp中指定部分
17                 // 第二個參數指定繪制到空白圖片的位置和大小
18                 // 畫完后CatchedBmp不再是空白圖片了,而是具有與截取的圖片一樣的內容
19                 g.DrawImage(originBmp, new Rectangle(0, 0, CatchRectangle.Width, CatchRectangle.Height), CatchRectangle, GraphicsUnit.Pixel);
20 
21                 // 將圖片保存到剪切板中
22                 Clipboard.SetImage(CatchedBmp);
23                 g.Dispose();
24                 CatchFinished = false;
25                 this.BackgroundImage = originBmp;
26                 CatchedBmp.Dispose();
27                 this.DialogResult = DialogResult.OK;
28                 this.Close();
29             }
30         }
左鍵雙擊
 1 /// <summary>
 2         /// 鼠標右鍵事件
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void Form2_MouseClick(object sender, MouseEventArgs e)
 7         {
 8             if (e.Button == MouseButtons.Right)
 9             {
10                 this.DialogResult = DialogResult.OK;
11                 this.Close();
12             }
13         }
鼠標單擊右鍵事件


完成這些事件,這個圖就完成了。並且可以直接ctrl+v直接復制使用。並且可以保存在D:\黑貓截圖 \ 的文件夾下面了。

感謝你耐心看完這篇隨筆,如果需要源碼參考學習

樓主補充:

由於有部分人已經發郵件給我需要源碼,特此公布:

http://download.csdn.net/download/paulzn/8428537

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM