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

  • 相关阅读:
    Kubernetes 集成研发笔记
    Rust 1.44.0 发布
    Rust 1.43.0 发布
    PAT 甲级 1108 Finding Average (20分)
    PAT 甲级 1107 Social Clusters (30分)(并查集)
    PAT 甲级 1106 Lowest Price in Supply Chain (25分) (bfs)
    PAT 甲级 1105 Spiral Matrix (25分)(螺旋矩阵,简单模拟)
    PAT 甲级 1104 Sum of Number Segments (20分)(有坑,int *int 可能会溢出)
    java 多线程 26 : 线程池
    OpenCV_Python —— (4)形态学操作
  • 原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878975.html
Copyright © 2011-2022 走看看