C#实现截图工具小项目
短信预约 -IT技能 免费直播动态提醒
本文实例为大家分享了C#实现截图工具小项目的具体代码,供大家参考,具体内容如下
1.起因
一直用的截图是qq的截图,所以想要实现一个简单点的截图,为了方便。
2.思路
讲一下实现流程。
1、主窗体,上有截图按钮,点击进入截图窗体
2、在截图窗体中,背景设置为全屏幕的截图图片,无边框,窗体最大化,这时你看到的就是一张屏幕图,其实是一个窗体,然后我们将在这个窗体中截取图片,其实主要就是画板Graphics的使用,截取完之后图片将保存到剪切板。
3.代码
热键注册类 HotKey.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace test {
/// <summary>
/// 热键类
/// </summary>
public class HotKey {
/// <summary>
/// 如果函数执行成功,返回值不为0,如果执行失败,返回值为0
/// </summary>
/// <returns></returns>
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(
IntPtr hWnd, // 窗口的句柄, 当热键按下时,会产生WM_HOTKEY信息,该信息该会发送该窗口句柄
int id, // 定义热键ID,属于唯一标识热键的作用
uint fsModifiers, // 热键只有在按下Alt、 Ctrl、Shift、Windows等键时才会生效,即才会产生WM_HOTKEY信息
Keys vk // 虚拟键,即按了Alt+Ctrl+ X ,X就是代表虚拟键
);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(
IntPtr hWnd, // 窗口句柄
int id // 要取消热键的ID
);
}
}
主窗体 Form1.cs
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
namespace test {
public partial class Form1 : Form {
[Flags]
public enum KeyModifiers { //定义热键值字符串(热键值是系统规定的,不能改变)
None = 0,
Alt = 1,
Ctrl = 2,
Shift = 4,
WindowsKey = 8
}
public Form1() {
InitializeComponent();
}
//窗体加载时-注册快捷键
private void Form1_Load(object sender, EventArgs e) {
uint ctrlHotKey = (uint)(KeyModifiers.Alt | KeyModifiers.Ctrl);
// 注册热键为Alt+Ctrl+A, "100"为唯一标识热键
HotKey.RegisterHotKey(Handle,100,ctrlHotKey,Keys.A);
}
//截图按钮
private void button1_Click(object sender, EventArgs e) {
if (this.WindowState != FormWindowState.Minimized) {
this.WindowState = FormWindowState.Minimized;
Thread.Sleep(200);
}
int swidth = Screen.PrimaryScreen.Bounds.Width;
int sheight = Screen.PrimaryScreen.Bounds.Height;
Bitmap btm = new Bitmap(swidth,sheight); //空图与屏幕同大小
Graphics g = Graphics.FromImage(btm); //空图的画板
g.CopyFromScreen(new Point(0,0),new Point(0,0),new Size(swidth,sheight)); //将屏幕内容复制到空图
Cutter cutter = new Cutter(btm); //传送截图
cutter.FormBorderStyle = FormBorderStyle.None; //截图全屏,无边框
cutter.BackgroundImage = btm; //新的窗体截图做背景
cutter.Show();
}
private void tiaoZ(object sender, ElapsedEventArgs e) {
}
//窗体关闭-取消热键
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
HotKey.UnregisterHotKey(Handle,100);
}
//快捷键按下执行的事件
private void GlobalKeyProcess() {
this.WindowState = FormWindowState.Minimized;
Thread.Sleep(200);
button1.PerformClick();
}
//重写。监视系统消息,调用对应方法
protected override void WndProc(ref Message m) {
const int WM_HOTKEY = 0x0312;
//如果m.Msg的值为0x0312(我也不知道为什么是0x0312)那么表示用户按下了热键
switch (m.Msg) {
case WM_HOTKEY:
if (m.WParam.ToString().Equals("100")) {
GlobalKeyProcess();
}
//todo 其它热键
break;
}
// 将系统消息传递自父类的WndProc
base.WndProc(ref m);
}
}
}
截图窗体-核心 Cutter.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test {
public partial class Cutter : Form {
Bitmap screenBtmp = null; //电脑屏幕的截图
public Cutter(Bitmap btm) {
InitializeComponent();
screenBtmp = btm;
}
//鼠标右键退出
private void Cutter_MouseClick(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Right) {
this.DialogResult = DialogResult.OK;
this.Close();
}
}
bool CatchStart = false; //自由截图开始
Point downPoint; //初始点
//鼠标左键按下-开始自由截图
private void Cutter_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
if (!CatchStart) {
CatchStart = true;
downPoint = new Point(e.X,e.Y); //初始点
}
}
}
Rectangle catchRec;//存放截取范围
//鼠标移动-绘制自由截图路径
private void Cutter_MouseMove(object sender, MouseEventArgs e) { //路径绘制,核心
if (CatchStart) {
//
//二次缓冲
//不是直接在控件的背景画板上进行绘制鼠标移动路径,那样会造成绘制很多路径,因为前面绘制的路径还在
//而是在内存中每移动一次鼠标就创建一张和屏幕截图一样的新BImtap,在这个Bitmap中绘制鼠标移动路径
//然后在窗体背景画板上,绘制这个新的Bitmap,这样就不会造成绘制很多路径,因为每次都绘制了全新的Bitmao
//但是这样做的话,因为鼠标移动的次数是大量的,所以在内存中会创建大量的Bitmap会造成内存消耗严重,所以每次移动绘制完后,
//需要释放Dispose() 画板,画笔,Bitmap资源。
//
Bitmap copyBtmp = (Bitmap)screenBtmp.Clone(); //创建新的,在其上绘制路径
//左上角
Point firstP = new Point(downPoint.X,downPoint.Y);
//新建画板,画笔
Graphics g = Graphics.FromImage(copyBtmp);
Pen p = new Pen(Color.Red,1);
//计算路径范围
int width = Math.Abs(e.X - downPoint.X);
int height = Math.Abs(e.Y - downPoint.Y);
if (e.X < downPoint.X) {
firstP.X = e.X;
}
if (e.Y < downPoint.Y) {
firstP.Y = e.Y;
}
//绘制路径
catchRec = new Rectangle(firstP,new Size(width,height));
//将路径绘制在新的BItmap上,之后要释放
g.DrawRectangle(p, catchRec);
g.Dispose();
p.Dispose();
//窗体背景画板
Graphics gf = this.CreateGraphics();
//将新图绘制在窗体的画板上 -- 自由截图-路径绘制处,其实还是一张和屏幕同样大小的图片,只不过上面有红色的选择路径
gf.DrawImage(copyBtmp,new Point(0,0));
gf.Dispose();
//释放内存Bimtap
copyBtmp.Dispose();
}
}
bool catchFinished = false; //自由截图结束标志
//鼠标左键弹起-结束自由截图
private void Cutter_MouseUp(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
if (CatchStart) {
CatchStart = false;
catchFinished = true;
}
}
}
//鼠标左键双击,保存自由截取的图片
private void Cutter_MouseDoubleClick(object sender, MouseEventArgs e) {
if((e.Button == MouseButtons.Left) && catchFinished){
//创建用户截取的范围大小的空图
Bitmap catchBtmp = new Bitmap(catchRec.Width,catchRec.Height);
Graphics g = Graphics.FromImage(catchBtmp);
//在原始的屏幕截图ScreenBitmap上 截取 用户选择范围大小的区域 绘制到上面的空图
//绘制完后,这个空图就是我们想要的截取的图片
//参数1 原图
//参数2 在空图上绘制的范围区域
//参数3 原图的截取范围
//参数4 度量单位
g.DrawImage(screenBtmp,new Rectangle(0,0,catchRec.Width,catchRec.Height),catchRec,GraphicsUnit.Pixel);
//将自由截取的图片保存到剪切板中
Clipboard.Clear();
Clipboard.SetImage(catchBtmp);
g.Dispose();
catchFinished = false;
this.BackgroundImage = screenBtmp;
catchBtmp.Dispose();
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341