zoukankan      html  css  js  c++  java
  • C#软件开发实例.私人订制自己的屏幕截图工具(四)基本截图功能实现

    本实例全部文章目录


    实现原理

    基本截图的功能主要靠响应主窗体的鼠标按下、鼠标移动、鼠标抬起几个事件的功能来实现的。截取的图片区域使用“Label”组件来显示,需要重新实现“Label”组件的“Paint”方法。

    左键单击开始截图,右键单击取消截图,双击鼠标左键完成截图,将截取的图片保存到Windows剪贴板中。

    添加“Label”组件

    工具箱》公共组件》双击“Label”组件,修改组件属性:

    Name=lbl_CutImage,

    AutoSize=False,

    BackColor=Transparent,

    Text = “”

    “Form1_Load”事件添加代码:

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. this.lbl_CutImage.Hide();  

    定义截图功能依赖的基本变量

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. #region 截图基本变量  
    2. /// <summary>  
    3. /// 用于判断是否已经开始截图,控制信息框是否显示。  
    4. /// </summary>  
    5. private bool isCuting;  
    6. /// <summary>  
    7. /// 鼠标按下的点  
    8. /// </summary>  
    9. private Point beginPoint;  
    10. /// <summary>  
    11. /// 最终确定的绘图基点  
    12. /// </summary>  
    13. private Point endPoint;  
    14. /// <summary>  
    15. /// 用于记录截图显示区域的大小(包括调整块的区域,调整区域边框宽度2px)  
    16. /// </summary>  
    17. private Rectangle cutImageRect = new Rectangle(0, 0, 5, 5);  
    18. #endregion  

    定义枚举类型:更新UI的模式

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 更新UI的模式,用于标记哪些需要显示,哪些需要隐藏;  
    3. /// </summary>  
    4. [FlagsAttribute]  
    5. public enum UpdateUIMode : uint  
    6. {  
    7.     //值得注意的是,如果要使用组合值,那么就不能用连接的数字表示,必须是几何级增长!  
    8.     None = 0,  
    9.     ShowTextPro = 1,  
    10.     ShowPenStyle = 2,  
    11.     ShowToolBox = 4,  
    12.     ShowInfoBox = 8,  
    13.     ShowZoomBox = 16,  
    14.     ShowCutImage = 32,  
    15.     HideTextPro = 64,  
    16.     HidePenStyle = 128,  
    17.     HideToolBox = 256,  
    18.     HideInfoBox = 512  
    19. }  

    添加方法:计算并保存截图的区域框的大小

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 计算并保存截图的区域框的大小  
    3. /// </summary>  
    4. private void SaveCutImageSize(Point beginPoint, Point endPoint)  
    5. {  
    6.     // 保存最终的绘图基点,用于截取选中的区域  
    7.     this.endPoint = beginPoint;  
    8.   
    9.     // 计算截取图片的大小  
    10.     int imgWidth = Math.Abs(endPoint.X - beginPoint.X) + 1;  
    11.     int imgHeight = Math.Abs(endPoint.Y - beginPoint.Y) + 1;  
    12.     int lblWidth = imgWidth + 4;  
    13.     int lblHeight = imgHeight + 4;  
    14.   
    15.     // 设置截图区域的位置和大小  
    16.     this.cutImageRect = new Rectangle(beginPoint.X - 2, beginPoint.Y - 2, lblWidth, lblHeight);  
    17. }  

    添加方法:执行截图,将选定区域的图片保存到剪贴板

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 执行截图,将选定区域的图片保存到剪贴板  
    3. /// </summary>  
    4. /// <param name="saveToDisk">  
    5. /// 是否将图片保存到磁盘  
    6. /// </param>  
    7. private void ExecCutImage(bool saveToDisk, bool uploadImage) //bool saveToDisk = false, bool uploadImage = false  
    8. {  
    9.     // 如果图片获取区域不可见,则退出保存图片过程  
    10.     if (!this.lbl_CutImage.Visible) { return; }  
    11.     Rectangle srcRect = new Rectangle();  
    12.     srcRect.X = this.lbl_CutImage.Location.X + 2;  
    13.     srcRect.Y = this.lbl_CutImage.Location.Y + 2;  
    14.     srcRect.Width = this.lbl_CutImage.Width - 4;  
    15.     srcRect.Height = this.lbl_CutImage.Height - 4;  
    16.     Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);  
    17.     Bitmap bmp = new Bitmap(srcRect.Width, srcRect.Height);  
    18.     Graphics g = Graphics.FromImage(bmp);  
    19.     g.DrawImage(this.screenImage, destRect, srcRect, GraphicsUnit.Pixel);  
    20.   
    21.     Clipboard.SetImage(bmp);  
    22.   
    23.     ExitCutImage(true);  
    24. }  

    添加方法:退出截图过程

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2.  /// 退出截图过程  
    3.  /// </summary>  
    4.  private void ExitCutImage(bool hideWindow) //  = true  
    5.  {  
    6.      this.lbl_CutImage.Visible = false;  
    7.      this.isCuting = false;  
    8.   
    9.      if (hideWindow)  
    10.      {  
    11.          this.screenImage.Dispose();  
    12.          this.Hide();  
    13.      }  
    14.  }  

    主窗口鼠标按下事件处理程序

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 截图窗口鼠标按下事件处理程序  
    3. /// </summary>  
    4. /// <param name="sender"></param>  
    5. /// <param name="e"></param>  
    6. private void Form1_MouseDown(object sender, MouseEventArgs e)  
    7. {  
    8.     // 左键单击事件  
    9.     if (e.Button == MouseButtons.Left && e.Clicks == 1)  
    10.     {  
    11.         if (!this.lbl_CutImage.Visible)  
    12.         {  
    13.             this.isCuting = true;  
    14.             this.beginPoint = e.Location;  
    15.             this.endPoint = e.Location;  
    16.             SaveCutImageSize(e.Location, e.Location);  
    17.   
    18.             UpdateCutInfoLabel(UpdateUIMode.ShowCutImage | UpdateUIMode.ShowInfoBox);  
    19.         }  
    20.     }  
    21.     // 左键双击事件  
    22.     if (e.Button == MouseButtons.Left && e.Clicks == 2)  
    23.     {  
    24.         if (this.lbl_CutImage.Visible)  
    25.         {  
    26.             ExecCutImage(falsefalse);  
    27.         }  
    28.   
    29.     }  
    30.     // 右键单击事件  
    31.     if (e.Button == MouseButtons.Right)  
    32.     {  
    33.         ExitCutImage(!this.lbl_CutImage.Visible);  
    34.     }  
    35.   
    36. }  

    主窗口鼠标移动事件处理程序

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 截图窗口鼠标移动事件处理程序  
    3. /// </summary>  
    4. /// <param name="sender"></param>  
    5. /// <param name="e"></param>  
    6. private void Form1_MouseMove(object sender, MouseEventArgs e)  
    7. {  
    8.     // 如果截取区域不可见,则退出处理过程  
    9.     if (!this.lbl_CutImage.Visible)  
    10.     {  
    11.         UpdateCutInfoLabel(UpdateUIMode.None);  
    12.         return;  
    13.     }  
    14.   
    15.     Point pntBgn = this.beginPoint;  
    16.     Point pntEnd = e.Location;  
    17.   
    18.     // 如果是反向拖动,重新设置起始点  
    19.     if (e.Location.X < this.beginPoint.X && e.Location.Y < this.beginPoint.Y)  
    20.     {  
    21.         pntBgn = e.Location;  
    22.         pntEnd = this.beginPoint;  
    23.     }  
    24.     else  
    25.     {  
    26.         if (e.Location.X < this.beginPoint.X)  
    27.         {  
    28.             pntBgn = new Point(e.Location.X, this.beginPoint.Y);  
    29.             pntEnd = new Point(this.beginPoint.X, e.Location.Y);  
    30.         }  
    31.         else  
    32.         {  
    33.             if (e.Location.Y < this.beginPoint.Y)  
    34.             {  
    35.                 pntBgn = new Point(this.beginPoint.X, e.Location.Y);  
    36.                 pntEnd = new Point(e.Location.X, this.beginPoint.Y);  
    37.             }  
    38.         }  
    39.     }  
    40.   
    41.     if (this.isCuting)  
    42.     {  
    43.         SaveCutImageSize(pntBgn, pntEnd);  
    44.     }  
    45.   
    46.     UpdateCutInfoLabel(UpdateUIMode.None);  
    47. }  

    主窗口鼠标抬起事件处理程序

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 截图窗口鼠标抬起事件处理程序  
    3. /// </summary>  
    4. /// <param name="sender"></param>  
    5. /// <param name="e"></param>  
    6. private void Form1_MouseUp(object sender, MouseEventArgs e)  
    7. {  
    8.     if (e.Button == MouseButtons.Left)  
    9.     {  
    10.         if (this.isCuting)  
    11.         {  
    12.             this.isCuting = false;  
    13.   
    14.             UpdateCutInfoLabel(UpdateUIMode.None);  
    15.         }  
    16.     }  
    17. }  

    截取区域图片绘制

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 截取区域图片的绘制事件处理程序  
    3. /// </summary>  
    4. /// <param name="sender"></param>  
    5. /// <param name="e"></param>  
    6. private void lbl_CutImage_Paint(object sender, PaintEventArgs e)  
    7. {  
    8.     int imgWidth = this.lbl_CutImage.Width - 4;  
    9.     int imgHeight = this.lbl_CutImage.Height - 4;  
    10.     if (imgWidth < 1) { imgWidth = 1; }  
    11.     if (imgHeight < 1) { imgHeight = 1; }  
    12.   
    13.     // 创建缓存图像,先将要绘制的内容全部绘制到缓存中,最后再一次性绘制到 Label 上,  
    14.     // 这样可以提高性能,并且可以防止屏幕闪烁的问题  
    15.     Bitmap bmp_lbl = new Bitmap(this.lbl_CutImage.Width, this.lbl_CutImage.Height);  
    16.     Graphics g = Graphics.FromImage(bmp_lbl);  
    17.   
    18.     // 将要截取的部分绘制到缓存  
    19.     Rectangle destRect = new Rectangle(2, 2, imgWidth, imgHeight);  
    20.     Point srcPoint = this.lbl_CutImage.Location;  
    21.     srcPoint.Offset(2, 2);  
    22.     Rectangle srcRect = new Rectangle(srcPoint, new System.Drawing.Size(imgWidth, imgHeight));  
    23.     g.DrawImage(this.screenImage, destRect, srcRect, GraphicsUnit.Pixel);  
    24.   
    25.     SolidBrush brush = new SolidBrush(Color.FromArgb(10, 124, 202));  
    26.     Pen pen = new Pen(brush, 1.0F);  
    27.   
    28.     //以下部分(边框和调整块)的绘制放在(编辑内容)的后面,是解决绘制编辑内容会覆盖(边框和调整块)的问题  
    29.   
    30.     // 绘制边框外的区域,解决会被编辑内容覆盖的问题  
    31.     // 上边  
    32.     destRect = new Rectangle(0, 0, this.lbl_CutImage.Width, 2);  
    33.     srcPoint = this.lbl_CutImage.Location;  
    34.     //srcPoint.Offset(2, 2);  
    35.     srcRect = new Rectangle(srcPoint, new System.Drawing.Size(this.lbl_CutImage.Width, 2));  
    36.     g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);  
    37.   
    38.     // 下边  
    39.     destRect = new Rectangle(0, this.lbl_CutImage.Height - 2, this.lbl_CutImage.Width, 2);  
    40.     srcPoint = this.lbl_CutImage.Location;  
    41.     srcPoint.Offset(0, this.lbl_CutImage.Height - 2);  
    42.     srcRect = new Rectangle(srcPoint, new System.Drawing.Size(this.lbl_CutImage.Width, 2));  
    43.     g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);  
    44.   
    45.     // 左边  
    46.     destRect = new Rectangle(0, 2, 2, this.lbl_CutImage.Height - 4);  
    47.     srcPoint = this.lbl_CutImage.Location;  
    48.     srcPoint.Offset(0, 2);  
    49.     srcRect = new Rectangle(srcPoint, new System.Drawing.Size(2, this.lbl_CutImage.Height - 4));  
    50.     g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);  
    51.   
    52.     // 右边  
    53.     destRect = new Rectangle(this.lbl_CutImage.Width - 2, 2, 2, this.lbl_CutImage.Height - 4);  
    54.     srcPoint = this.lbl_CutImage.Location;  
    55.     srcPoint.Offset(this.lbl_CutImage.Width - 2, 2);  
    56.     srcRect = new Rectangle(srcPoint, new System.Drawing.Size(2, this.lbl_CutImage.Height - 4));  
    57.     g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);  
    58.   
    59.     // 绘制边框  
    60.     g.DrawLine(pen, 2, 2, this.lbl_CutImage.Width - 3, 2);  
    61.     g.DrawLine(pen, 2, 2, 2, this.lbl_CutImage.Height - 3);  
    62.     g.DrawLine(pen, this.lbl_CutImage.Width - 3, 2, this.lbl_CutImage.Width - 3, this.lbl_CutImage.Height - 3);  
    63.     g.DrawLine(pen, 2, this.lbl_CutImage.Height - 3, this.lbl_CutImage.Width - 3, this.lbl_CutImage.Height - 3);  
    64.   
    65.     // 绘制四个角的调整块  
    66.     g.FillRectangle(brush, 0, 0, 4, 5);  
    67.     g.FillRectangle(brush, this.lbl_CutImage.Width - 4, 0, 4, 5);  
    68.     g.FillRectangle(brush, 0, this.lbl_CutImage.Height - 5, 4, 5);  
    69.     g.FillRectangle(brush, this.lbl_CutImage.Width - 4, this.lbl_CutImage.Height - 5, 4, 5);  
    70.   
    71.     // 绘制中间的四个调整块  
    72.     int blockX = this.lbl_CutImage.Width / 2 - 2;  
    73.     int blockY = this.lbl_CutImage.Height / 2 - 2;  
    74.     g.FillRectangle(brush, blockX, 0, 4, 5);  
    75.     g.FillRectangle(brush, 0, blockY, 4, 5);  
    76.     g.FillRectangle(brush, blockX, this.lbl_CutImage.Height - 5, 4, 5);  
    77.     g.FillRectangle(brush, this.lbl_CutImage.Width - 4, blockY, 4, 5);  
    78.   
    79.     // 绘制到 Label 上  
    80.     e.Graphics.DrawImage(bmp_lbl, 0, 0);  
    81.     bmp_lbl.Dispose();  
    82. }  

    双击鼠标左键完成截图功能

    [csharp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /// <summary>  
    2. /// 截取区域图片的鼠标按下事件处理程序  
    3. /// </summary>  
    4. /// <param name="sender"></param>  
    5. /// <param name="e"></param>  
    6. private void lbl_CutImage_MouseDown(object sender, MouseEventArgs e)  
    7. {  
    8.     // 左键双击事件  
    9.     if (e.Button == MouseButtons.Left && e.Clicks == 2)  
    10.     {  
    11.         if (this.lbl_CutImage.Visible)  
    12.         {  
    13.             ExecCutImage(falsefalse);  
    14.         }  
    15.     }  
    16. }  

    注意:代码都贴完了,别忘了为窗体或组件绑定事件处理程序;

    例如:截取区域图片的鼠标按下事件处理程序“lbl_CutImage_MouseDown”,就是“lbl_CutImage”组件的“MouseDown”事件的处理程序,绑定方法参考下图:


    到此,基本截图的功能实现已经实现,赶快去截取一张图片,粘贴到QQ的聊天窗口看看吧。
    源码下载:http://download.csdn.net/detail/testcs_dn/7261365

  • 相关阅读:
    010 Editor无限制免费安装注册破解图文教程(破解补丁)
    请求设置
    请求方法
    Session
    Config
    Model
    模板2
    模板语法
    动态路由
    Put和Delete
  • 原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878975.html
Copyright © 2011-2022 走看看