半路出家,沒有通過系統的學習。寫代碼的時候內心老是沒底,本身都不相信本身寫的這些代碼能夠執行。這是目前本身的一個狀態。2015-02-04日記!windows
一個偶然的機會,得知公司不少員工不會使用windows截圖。然而在生產線上的員工是不能鏈接網絡,因此不能使用qq截圖。頓時想本身寫一個截圖工具。以便你們能夠記錄下異常時的情形!網絡
有了這樣一個想法,可是怎麼去實現呢?沒有啥好的新創意。可是國人有一個優秀的品質,不會創新咱就仿製唄。瞄上咱最熟悉的qq截圖。多線程
首先分析qq截圖的過程=》ide
========點擊截圖按鈕--》進入截圖的狀態--》按下鼠標左鍵開始截圖--》移動鼠標【起點和終點之間組成的矩形框即是截圖區間】--》彈起鼠標左鍵截圖結束--》截圖保存到剪切板--》截圖完成--》cltr+v粘貼到界面工具
===========================》按下右鍵結束截圖狀態學習
那麼問題來了。進入截圖狀態。怎麼實現呢?ui
怎樣讓桌面狀態保持不變。這個是怎麼作出來的效果呢?this
你們是否是想到了,咱們看到的就是一張圖片。而後把這張圖片放在了一個窗體中,而後把這個窗體置頂了。因此。。。這樣是否是基本上吻合了那個狀態呢?spa
那就這樣的思路作吧!.net
按照上面的想法,咱們有兩個窗體一個是咱們操做的窗體,一個是截圖的窗體!
這個是用戶操做頁面的窗體。在這個頁面的代碼主要就是兩個事件
截圖事件
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