• 截图工具-开发过程随谈


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

    作者:不再奢望
    出处:http://www.cnblogs.com/mgxiaobo/
    本文版权归作者和博客园共同拥有,欢迎转载,但未经作者同意必须保留此段声明,且在页面明显位置给出原文链接,否则保留追究法律责任的权利。

  • 相关阅读:
    PC上图标显示异常 白色框框处理方案
    判断Javascript变量是否为空 undefined 或者null(附样例)
    MySQL双版本共存解决方案
    跨境电商进口业务的通关模式
    史上最完整跨境电商投资分析报告!
    Fastcgi_Finish_Request 提高页面响应速度
    浏览器工作原理
    thinkphp 命名规范
    git diff ^M的消除
    git简明教程
  • 原文地址:https://www.cnblogs.com/mgxiaobo/p/4273111.html
Copyright © 2020-2023  润新知