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实现一个简单的在线聊天功能 一直很想试着做一做这个有意思的功能,感觉复杂的不是数据交互和表结构,麻 ...
随机推荐
- java中窗口的打开与关闭
作为小白的我,今天学习了java中打开与关闭窗口的方法. 1.在java中创建一个窗口 import java.awt.*;import java.awt.event.*;public class L ...
- java 单链表 练习
练习一下java单链表的简单习题 package com.test1; import java.util.Stack; public class SingleListDemo { /** * 返回单链 ...
- 移除 DevExpress 的 XtraForm 标题文字阴影
问题 在使用 DevExpress 开发 WinForm 程序时,我是使用的默认皮肤进行开发.但客户要求标题栏背景色改为蓝色,标题文字颜色改为白色. 改颜色比较简单,参考了 DevExpress Su ...
- ASP.NET Core部署系列二:发布到CentOS上
前言: 在上一节中,通过一系列的步骤,已经将项目部署到IIS上,虽然遇到了一些问题,但最终解决并成功运行了.而在这一节中,将尝试通过linux系统的环境下,部署项目,实现Net Core跨平台的亮点. ...
- $和jquery的关系
$和jquery的关系 $其实是jQuery的别名 一般直接使用$符号 在许多JavaScript库中都会有$作为标记.如果同时使用多个JavaScript库时难免会出现冲突. 解决方法:重新设置jQ ...
- ES6-Set的增加、查找、删除、遍历、查看长度、数组去重
set 是es6新出的一种数据结构,里边放的是数组. 作用:去重(set里边的数组不能重复) MDN:Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用. 总结: 1.成员唯一.无序且 ...
- JupyterLab安装与配置虚拟环境
JupyterLab安装: 推荐使用miniconda,相比于anaconda更加简洁,下载连接:https://mirrors.tuna.tsinghua.edu.cn/anaconda/minic ...
- tomcat修改进程名称
1.window平台: 打开tomcat_home\bin\setclasspath.bat文件,找到set _RUNJAVA=”%JRE_HOME%\bin\java”这一行. 将该行注释掉 ,然后 ...
- Fiddler 过滤掉无用域名
- 在 Fiters 一栏勾选Show only Internet Hosts 及Show only the following Hosts- 然后在下面输入需要保留的域名
- 使用docker-compose安装wordpress
一.建立应用的目录 mkdir my_wordpress cd my_wordpress 二.创建 docker-compose.yml touch docker-compose.yml;vi doc ...