前言

通过创建客制化组件(继承pictureBox),新增属性和构造方法,实现屏幕截图时需要用到的功能点。再通过监控鼠标按下、移动和释放,来获取起始点区域。最后通过操作BMP图像,实现截图的新增、修改和保存功能。

核心点

  • 组件的创建(重写)
  • 鼠标监控事件
  • BMP图像重绘

核心代码

     /// <summary>
/// 重写图片控件
/// </summary>
[Serializable]
public partial class HexPictureBox : PictureBox
{
#region 属性和构造函数 public HexPictureBox()
{
InitializeComponent();
} private bool startDraw = false; public bool StartDraw
{
get { return startDraw; } set { startDraw = value; }
} private List<HLine> lineHistory = new List<HLine>(); public List<HLine> LineHistory
{
get { return lineHistory; } private set { lineHistory = value; }
} private HLine curLine = new HLine() { LineColor = Color.White, LineWidth = , PointList = new List<Point>() }; /// <summary>
/// 当前绘制线
/// </summary>
public HLine CurLine
{
get { return curLine; } private set { curLine = value; }
} private HRectangle curRect = new HRectangle() { LineColor = Color.White, LineWidth = , Start = new Point(, ), End = new Point(, ) }; /// <summary>
/// 当前需要绘制的矩形
/// </summary>
public HRectangle CurRect
{
get { return curRect; } set { curRect = value; }
} private List<HRectangle> rectHistory = new List<HRectangle>(); public List<HRectangle> RectHistory
{
get { return rectHistory; } private set { rectHistory = value; }
} private DrawType drawTypes = DrawType.None; public DrawType DrawTypes
{
get { return drawTypes; } set { drawTypes = value; }
} #endregion #region 绘制功能 protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Graphics g = pe.Graphics;
DrawHistory(g);
//绘制当前线
if (startDraw && this.curLine.PointList != null && this.curLine.PointList.Count > )
{
DrawLine(g, this.curLine);
}
if (startDraw && this.curRect.Start != null && this.curRect.End != null && this.curRect.Start != this.curRect.End)
{
DrawRectangle(g, this.curRect);
}
} public void DrawHistory(Graphics g)
{
//绘制线历史记录
if (LineHistory != null)
{
foreach (HLine lh in LineHistory)
{
if (lh.PointList.Count > )
{
DrawLine(g, lh);
}
}
}
//绘制矩形历史记录
if (RectHistory != null)
{
foreach (HRectangle lh in RectHistory)
{
if (lh.Start != null && lh.End != null && lh.Start != lh.End)
{
DrawRectangle(g, lh);
}
}
}
} /// <summary>
/// 绘制线
/// </summary>
/// <param name="g"></param>
/// <param name="line"></param>
private void DrawLine(Graphics g, HLine line)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
using (Pen p = new Pen(line.LineColor, line.LineWidth))
{
//设置起止点线帽
p.StartCap = LineCap.Round;
p.EndCap = LineCap.Round; //设置连续两段的联接样式
p.LineJoin = LineJoin.Round;
g.DrawCurve(p, line.PointList.ToArray()); //画平滑曲线
}
} /// <summary>
/// 绘制矩形
/// </summary>
/// <param name="g"></param>
/// <param name="rect"></param>
private void DrawRectangle(Graphics g, HRectangle rect)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
using (Pen p = new Pen(rect.LineColor, rect.LineWidth))
{
//设置起止点线帽
p.StartCap = LineCap.Round;
p.EndCap = LineCap.Round; //设置连续两段的联接样式
p.LineJoin = LineJoin.Round;
g.DrawRectangle(p, rect.Start.X, rect.Start.Y, rect.End.X - rect.Start.X, rect.End.Y - rect.Start.Y); //画平滑曲线
}
} public void Earser(Point p0)
{
for (int i = lineHistory.Count - ; i >= ; i--)
{
HLine line = lineHistory[i];
bool flag = false;
foreach (Point p1 in line.PointList)
{
double distance = GetDistance(p0, p1);
if (Math.Abs(distance) < )
{
//需要删除
flag = true;
break;
} }
if (flag)
{
lineHistory.RemoveAt(i);
}
}
//擦除矩形
for (int i = rectHistory.Count - ; i >= ; i--)
{
HRectangle rect = rectHistory[i]; if (p0.X > rect.Start.X && p0.X < rect.End.X && p0.Y > rect.Start.Y && p0.Y < rect.End.Y)
{ rectHistory.RemoveAt(i);
}
}
} /// <summary>
/// 获取两点之间的距离
/// </summary>
/// <param name="p0"></param>
/// <param name="p1"></param>
/// <returns></returns>
private double GetDistance(Point p0, Point p1)
{
return Math.Sqrt(Math.Pow((p0.X - p1.X), ) + Math.Pow((p0.Y - p1.Y), ));
} #endregion #region 鼠标事件响应 /// <summary>
/// 鼠标移动时设置点
/// </summary>
/// <param name="p"></param>
public void SetPointAndRefresh(Point p)
{
if (this.drawTypes == DrawType.Line)
{
this.curLine.PointList.Add(p);
}
if (this.drawTypes == DrawType.Rect)
{
this.curRect.End = p;
}
this.Refresh(); } public void OnMouseDown(Point p)
{
if (this.DrawTypes == DrawType.Line)
{
this.CurLine.PointList.Clear();
this.CurLine.PointList.Add(p);
}
if (this.DrawTypes == DrawType.Rect)
{
this.CurRect.Start = p;
}
} public void OnMouseUp(Point p)
{
if (this.DrawTypes == DrawType.Line)
{
//右键起来时,停止绘图,并写入历史记录
Point[] pCopy = this.CurLine.PointList.ToArray();
List<Point> lstPoint = new List<Point>();
lstPoint.AddRange(pCopy);
this.LineHistory.Add(new HLine() { LineColor = this.CurLine.LineColor, LineWidth = this.CurLine.LineWidth, PointList = lstPoint });
this.CurLine.PointList.Clear();
}
if (this.DrawTypes == DrawType.Rect)
{
this.RectHistory.Add(new HRectangle() { LineColor = this.CurRect.LineColor, LineWidth = this.CurRect.LineWidth, Start = this.CurRect.Start, End = this.CurRect.End });
this.CurRect.Start = new Point(, );
this.CurRect.End = new Point(, );
}
if (this.DrawTypes == DrawType.Earser)
{
//如果是橡皮擦功能
this.Earser(p);
this.Refresh();
}
} #endregion #region 初始设置 public void SetPen(Color c)
{
this.DrawTypes = DrawType.Line;
this.CurLine.LineWidth = ;
this.CurLine.LineColor = c;
//通过图片的句柄获取指针
this.Cursor = new Cursor(global::ScreenShot.Properties.Resources.pen.GetHicon());
this.StartDraw = true;
} public void SetLightPen()
{
this.StartDraw = true;
this.CurLine.LineWidth = ;
this.DrawTypes = DrawType.Line;
this.Cursor = new Cursor(global::ScreenShot.Properties.Resources.lightpen.GetHicon());
this.CurLine.LineColor = Color.FromArgb(, Color.Yellow);
} public void SetRectangle()
{
this.StartDraw = true;
this.CurRect.LineWidth = ;
this.DrawTypes = DrawType.Rect;
this.CurRect.LineColor = Color.Red;
this.Cursor = Cursors.Cross;
} public void SetEarser()
{
this.DrawTypes = DrawType.Earser;//橡皮檫
this.Cursor = new Cursor(global::ScreenShot.Properties.Resources.easer1.GetHicon());
} public void SetDefault()
{
this.Cursor = Cursors.Default;
this.StartDraw = false;
} #endregion
}

实现效果

作者:Jeremy.Wu
  出处:https://www.cnblogs.com/jeremywucnblog/

  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

C# - VS2019通过重写pictureBox实现简单的桌面截图功能的更多相关文章

  1. VC++ 实现简单的桌面截图

    使用了EasyX图像库,使用方法请参考:VC++ 制作一个简易的控制台时钟应用 简单的桌面截图代码: ///////////////////////////////////////////////// ...

  2. CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能

    CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...

  3. 完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能

    #!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能'''try: a=int(raw_input(" ...

  4. Selenium + PhantomJS + python 简单实现爬虫的功能

    Selenium 一.简介 selenium是一个用于Web应用自动化程序测试的工具,测试直接运行在浏览器中,就像真正的用户在操作一样 selenium2支持通过驱动真实浏览器(FirfoxDrive ...

  5. iOS开发——使用技术OC篇&简单九宫格锁屏功能的实现与封装

    简单九宫格锁屏功能的实现与封装 首先来看看最后的实现界面. 在这开始看下面的内容之前希望你能先大概思考活着回顾一下如果 你会怎么做,只要知道大概的思路就可以. 由于iphone5指纹解锁的实现是的这个 ...

  6. 简单 TCP/IP 服务功能

    本主题使用每台 Windows 计算机上提供的 Echo 和 Quote of the Day 服务.在所有 Windows 版本中都提供了简单 TCP/IP 服务功能.该功能会提供了以下服务:Cha ...

  7. Python django实现简单的邮件系统发送邮件功能

    Python django实现简单的邮件系统发送邮件功能 本文实例讲述了Python django实现简单的邮件系统发送邮件功能. django邮件系统 Django发送邮件官方中文文档 总结如下: ...

  8. Netty学习笔记(四) 简单的聊天室功能之服务端开发

    前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...

  9. 基于PHP实现一个简单的在线聊天功能(轮询ajax )

    基于PHP实现一个简单的在线聊天功能(轮询ajax ) 一.总结 1.用的轮询ajax 二.基于PHP实现一个简单的在线聊天功能 一直很想试着做一做这个有意思的功能,感觉复杂的不是数据交互和表结构,麻 ...

随机推荐

  1. [读论文]Shading-aware multi view stereo

    如何实现refine的? 几何误差和阴影误差如何加到一起? 为了解决什么问题? 弱纹理或无纹理:单纯的多视图立体算法在物体表面弱纹理或者无纹理区域重建完整度不够高,精度也不够高,因此结合阴影恢复形状来 ...

  2. Linux中,Tomcat 怎么承载高并发(深入Tcp参数 backlog)

    一.前言 这两天看tomcat,查阅 tomcat 怎么承载高并发时,看到了backlog参数.我们知道,服务器端一般使用mq来减轻高并发下的洪峰冲击,将暂时不能处理的请求放入队列,后续再慢慢处理.其 ...

  3. JavaScript空字符串判断

    JavaScript空字符串判断 本文完整示例代码GIT仓: 测试用例完整代码:isNullOrEmpty jPublic GIT仓:jPublic 比较常见写法 if (str == 'undefi ...

  4. SpringCloud的入门学习之概念理解、Ribbon负载均衡入门

    1.Ribbon负载均衡,Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端.负载均衡的工具. 答:简单的说,Ribbon是Netflix发布的开源项目,主要功能 ...

  5. C#中获取指定路径下特定开头和后缀的所有文件

    场景 指定一个文件路径,获取当前路径下所有文件,并筛选出以指定内容开头和结尾的文件. 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 ...

  6. python爬虫-京东商品爬取

    京东商品爬取 仅供学习 一.使用selenium from selenium import webdriver from selenium.webdriver.common.keys import K ...

  7. PHP 7.0 7.3 (Unix) - 'gc' Disable Functions Bypass

    <?php # PHP 7.0-7.3 disable_functions bypass PoC (*nix only) # # Bug: https://bugs.php.net/bug.ph ...

  8. Vulnhub DC-1靶机渗透学习

    前言 之前听说过这个叫Vulnhub DC-1的靶机,所以想拿来玩玩学习,结果整个过程都是看着别人的writeup走下来的,学艺不精,不过这个过程也认识到,学会了很多东西. 所以才想写点东西,记录一下 ...

  9. [20191112]oracle共享连接模式端口.txt

    [20191112]oracle共享连接模式端口.txt --//如果使用共享服务模式,你可以发现每次重启数据库对应的端口号会发生变化.# netstat -tunlp | egrep "A ...

  10. Pycharm界面的子窗口不见了,怎么办?

    pycharm程序界面一般有很多子窗口,如图1所示. 图1  Pycharm子窗口 如果你发现某些子窗口不见了,图2是最过分的情形,无须担心. 图2  Pycharm界面的子窗口不见了 打开项目视图子 ...