C# - VS2019通过重写pictureBox实现简单的桌面截图功能
前言
通过创建客制化组件(继承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实现简单的桌面截图功能的更多相关文章
- VC++ 实现简单的桌面截图
使用了EasyX图像库,使用方法请参考:VC++ 制作一个简易的控制台时钟应用 简单的桌面截图代码: ///////////////////////////////////////////////// ...
- CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能
CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...
- 完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能
#!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能'''try: a=int(raw_input(" ...
- Selenium + PhantomJS + python 简单实现爬虫的功能
Selenium 一.简介 selenium是一个用于Web应用自动化程序测试的工具,测试直接运行在浏览器中,就像真正的用户在操作一样 selenium2支持通过驱动真实浏览器(FirfoxDrive ...
- iOS开发——使用技术OC篇&简单九宫格锁屏功能的实现与封装
简单九宫格锁屏功能的实现与封装 首先来看看最后的实现界面. 在这开始看下面的内容之前希望你能先大概思考活着回顾一下如果 你会怎么做,只要知道大概的思路就可以. 由于iphone5指纹解锁的实现是的这个 ...
- 简单 TCP/IP 服务功能
本主题使用每台 Windows 计算机上提供的 Echo 和 Quote of the Day 服务.在所有 Windows 版本中都提供了简单 TCP/IP 服务功能.该功能会提供了以下服务:Cha ...
- Python django实现简单的邮件系统发送邮件功能
Python django实现简单的邮件系统发送邮件功能 本文实例讲述了Python django实现简单的邮件系统发送邮件功能. django邮件系统 Django发送邮件官方中文文档 总结如下: ...
- Netty学习笔记(四) 简单的聊天室功能之服务端开发
前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...
- 基于PHP实现一个简单的在线聊天功能(轮询ajax )
基于PHP实现一个简单的在线聊天功能(轮询ajax ) 一.总结 1.用的轮询ajax 二.基于PHP实现一个简单的在线聊天功能 一直很想试着做一做这个有意思的功能,感觉复杂的不是数据交互和表结构,麻 ...
随机推荐
- PyCharm 2019 2.3 软件安装教程(1.补丁破解2.破解码)
一:补丁破解 PyCharm 2019 2.3 下载地址 https://pan.baidu.com/s/1HaWFcbO-x4vZuT6mVC0AGA 提取码:elu7 更多破解教程微信公众号关注“ ...
- SpringBootJPA实现增删改查
一.目录展示 二.导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...
- C - Train Problem II——卡特兰数
题目链接_HDU-1023 题目 As we all know the Train Problem I, the boss of the Ignatius Train Station want to ...
- 被忽略的CSS规则
说起CSS规则,除了普通规则(属性和值,key:value),可能大家都会想到@media,@keyframes,@fontface等常用的,那剩余的大家是否有所了解呢. 我们先来看一看CSS有哪些规 ...
- Linux之自动化部署
No.1 自动化部署git项目 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 ...
- C#面向对象--简介
一.C#提供对面向对象编程(Object Oriented Programming)的完整支持:类描述对象的类型,而对象是类的具体实例,创建对象的过程也被称为实例化(Instantiation):通常 ...
- [转]JS将图片转为base64编码
本文转自:https://blog.csdn.net/DeMonliuhui/article/details/79731359 1.根据img标签获取base64编码/** * * @param im ...
- ABP入门教程5 - 界面调整
点这里进入ABP入门教程目录 调整前 调整后 调整项 页面标题 把favicon.ico替换为指定Logo JD.CRS.Web.Mvc\wwwroot\favicon.ico 顶部工具栏 把logo ...
- win7下安装MySQL5.7教程
MySQL官网下载5.7 zip安装包 地址:https://dev.mysql.com/downloads/mysql/5.7.html#downloads 1.解压mysql-5.7.14-wi ...
- Thinkphp 模板中 if 嵌套层级过多的问题,嵌套3级就报错,取消层级限制
解决此问题有两种办法:1.第三层if换成eq或者原生<?php 'abc';> 2.修改Tp核心配置文件 1.第三层if换成eq或者原生<?php 'abc';> 如下图&l ...