分享

C#软件开发实例.私人订制自己的屏幕截图工具(四)基本截图功能实现

 3dC 2017-03-01

本实例全部文章目录


实现原理

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

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

添加“Label”组件

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

Name=lbl_CutImage,

AutoSize=False,

BackColor=Transparent,

Text = “”

“Form1_Load”事件添加代码:

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

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

[csharp] view plain copy
在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 plain copy
在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 plain copy
在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 plain copy
在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 plain copy
在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 plain copy
在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(false, false);  
  27.         }  
  28.   
  29.     }  
  30.     // 右键单击事件  
  31.     if (e.Button == MouseButtons.Right)  
  32.     {  
  33.         ExitCutImage(!this.lbl_CutImage.Visible);  
  34.     }  
  35.   
  36. }  

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

[csharp] view plain copy
在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 plain copy
在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 plain copy
在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 plain copy
在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(false, false);  
  14.         }  
  15.     }  
  16. }  

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

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


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



你这样写的话,没法截取反向的,其实可以修改SaveCutImageSize方法
//this.endPoint = begainPoint;
int beginX = beginPoint.X;int begingY = beginPoint.Y;
if(endPoint.X<begainPoint.X){beginX = endPoint.X;}
if(endPoint.Y<beginPoint.Y){begingY = endPoint.Y;}
int imgWidth = Math.Abs(endPoint.X - begainPoint.X) + 1;
int imgHeight = Math.Abs(endPoint.Y - begainPoint.Y) + 1;
int lblWidth = imgWidth + 4;
int lblHeight = imgHeight + 4;

this.cutImageRect = new Rectangle(beginX - 2, begingY - 2, lblWidth, lblHeight);

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    来自: 3dC > 《c#》

    0条评论

    发表

    请遵守用户 评论公约