截图工具-开发过程随谈

 

半路出家,没有经过系统的学习。写代码的时候心里总是没底,自己都不相信自己写的这些代码可以执行。这是目前自己的一个状态。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

 

posted @ 2015-02-04 18:58  不再奢望  阅读(1969)  评论(6编辑  收藏  举报