C#实现带光标的截图

1,目的:

  • 可通过热键实现带光标与不带光标两种模式的截图。

2,知识点:

  • 快捷键的注册与注销。
 [DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
  • 光标信息的获取,光标图标的复制。
[DllImport("user32.dll")]
public static extern IntPtr CopyIcon(IntPtr hIcon);
[DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
public static extern bool GetCursorInfo(ref CURSORINFO cInfo);
[DllImport("user32.dll", EntryPoint = "GetIconInfo")]
public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO iInfo);
  • 对配置文件(ini文件)的读写。
[DllImport("kernel32")]
public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath);
  • 系统消息的重写。(Message相关链接:Message类的Msg属性所关联的所有ID_msg=0x001a-CSDN博客)
protected override void WndProc(ref Message m)
{//WM_HOTKEY=0x0312,热键关联的消息IDconst int WM_HOTKEY = 0x0312;//按快捷键     switch (m.Msg){case WM_HOTKEY:switch (m.WParam.ToInt32()){case 81:    //按下的是Shift+F   string ss = "";CaptureImage(ref ss);break;}break;}base.WndProc(ref m);
}

3,效果展示:

  • 带图标效果:

  • 无图标效果

4代码:

public partial class Form1 : Form{public Form1(){InitializeComponent();}bool isCaptureIcon = false;string savePath;private void Form1_Load(object sender, EventArgs e){//判断是否存在配置文件如果不存在则创建,如果存在则读取string configPath = Path.GetFullPath("../../config.ini");if (File.Exists(configPath)){savePath = ReadFromINI(configPath, "Configuration", "Location");string str = ReadFromINI(configPath, "Configuration", "CaptureIcon");bool result;if (bool.TryParse(str, out result)){isCaptureIcon = result;}else{isCaptureIcon = false;}}else{File.Create(configPath);isCaptureIcon = false;}if (string.IsNullOrEmpty(savePath)){//获取当前启动位置的盘string startLocation = Application.StartupPath;string defaultLocation = Directory.GetDirectoryRoot(startLocation);savePath = defaultLocation;}textBox1.Text = savePath;checkBox1.Checked = isCaptureIcon;//进行热键注册APIHelper.RegisterHotKey(this.Handle, 81, KeyModifiers.Shift, Keys.C);}//设置截图存储路径private void btnOpenF_Click(object sender, EventArgs e){using (FolderBrowserDialog fbd = new FolderBrowserDialog()){if (fbd.ShowDialog() == DialogResult.OK){savePath = textBox1.Text = fbd.SelectedPath;}}}//保存配置private void btnSave_Click(object sender, EventArgs e){string iniPath = Path.GetFullPath("../../config.ini");if (!File.Exists(iniPath)){File.Create(iniPath);}WriteToINI(iniPath, "Configuration", "Location", textBox1.Text);WriteToINI(iniPath, "Configuration", "CaptureIcon", isCaptureIcon.ToString());MessageBox.Show("已保存", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);}private void checkBox1_CheckedChanged(object sender, EventArgs e){isCaptureIcon = checkBox1.Checked;}private void Form1_FormClosing(object sender, FormClosingEventArgs e){//热键注销APIHelper.UnregisterHotKey(this.Handle, 81);}//隐藏窗口private void btnHide_Click(object sender, EventArgs e){this.Hide();}private void btnCapture_Click(object sender, EventArgs e){string filePath = "";if (CaptureImage(ref filePath)){MessageBox.Show("已截图:" + filePath);}else{MessageBox.Show("截图失败");}}//双击图标显示窗口private void notifyIcon1_DoubleClick(object sender, EventArgs e){this.Show();this.WindowState = FormWindowState.Normal;this.Activate();}private void toolStripExit_Click(object sender, EventArgs e){APIHelper.UnregisterHotKey(this.Handle, 81);Application.Exit();}private void toolStripShow_Click(object sender, EventArgs e){this.Visible = true;}//对接收的消息进行重写protected override void WndProc(ref Message m){//WM_HOTKEY=0x0312,热键关联的消息IDconst int WM_HOTKEY = 0x0312;//按快捷键     switch (m.Msg){case WM_HOTKEY:switch (m.WParam.ToInt32()){case 81:    //按下的是Shift+F   string ss = "";CaptureImage(ref ss);break;}break;}base.WndProc(ref m);}bool CaptureImage(ref string filePath){Bitmap img;if (!isCaptureIcon){img = CaptureNoCursor();string imgDir = Path.Combine(savePath, "Image", "NoCursor");if (!Directory.Exists(imgDir)){Directory.CreateDirectory(imgDir);}string fileName = "IMG_" + DateTime.Now.ToString("HHmmss") + ".png";filePath = Path.Combine(imgDir, fileName);}else{img = CaptureCursor();string imgDir = Path.Combine(savePath, "Image", "Cursor");if (!Directory.Exists(imgDir)){Directory.CreateDirectory(imgDir);}string fileName = "IMG_" + DateTime.Now.ToString("HHmmss") + ".png";filePath = Path.Combine(imgDir, fileName);}if (img != null){img.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);return true;}else{return false;}}/// <summary>/// 不含光标的截图/// </summary>/// <returns></returns>Bitmap CaptureNoCursor(){//获取屏幕尺寸int width = APIHelper.GetSystemMetrics(0);int height = APIHelper.GetSystemMetrics(1);//创建图片Bitmap img = new Bitmap(width, height);using (Graphics g = Graphics.FromImage(img)){g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(width, height));}return img;}/// <summary>/// 包含光标的截图/// </summary>/// <returns></returns>Bitmap CaptureCursor(){//获取光标信息CURSORINFO cursor = new CURSORINFO();cursor.cbSize = Marshal.SizeOf(cursor);if (APIHelper.GetCursorInfo(ref cursor)){//flags==1时光标处于显示中if (cursor.flags == 1){ICONINFO iconinfo;//复制光标IntPtr hwn = APIHelper.CopyIcon(cursor.hCursor);//获取光标信息if (APIHelper.GetIconInfo(hwn, out iconinfo)){Icon icon = Icon.FromHandle(hwn);Point iconScreenPoint = new Point(cursor.ptScreenPos.X - iconinfo.xHotspot, cursor.ptScreenPos.Y - iconinfo.yHotspot);//获取屏幕尺寸int width = Screen.PrimaryScreen.Bounds.Width;int height = Screen.PrimaryScreen.Bounds.Height;//创建图片Bitmap img = new Bitmap(width, height);using (Graphics g = Graphics.FromImage(img)){g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(width, height));g.DrawIcon(icon, iconScreenPoint.X, iconScreenPoint.Y);}return img;}}}return null;}public static string ReadFromINI(string filePath, string rootValue, string key, string defValue = ""){StringBuilder sb = new StringBuilder(1024);APIHelper.GetPrivateProfileString(rootValue, key, defValue, sb, 1024, filePath);return sb.ToString();}public static void WriteToINI(string filePath, string rootValue, string key, string newVal){APIHelper.WritePrivateProfileString(rootValue, key, newVal, filePath);}}/// <summary>/// 有关图标或光标的信息/// </summary>[StructLayout(LayoutKind.Sequential)]struct ICONINFO{/// <summary>/// 指定此结构是定义图标还是游标。 值为 TRUE 指定图标; FALSE 指定游标。/// </summary>public bool fIcon;/// <summary>/// 光标热点的 x 坐标。 如果此结构定义了图标,则热点始终位于图标的中心,并且忽略此成员。/// </summary>public Int32 xHotspot;/// <summary>/// 光标热点的 y 坐标。 如果此结构定义了图标,则热点始终位于图标的中心,并且忽略此成员。/// </summary>public Int32 yHotspot;/// <summary>/// 单色掩码 位图图标的句柄。/// </summary>public IntPtr hbmMask;/// <summary>/// 图标颜色 位图的句柄。/// </summary>public IntPtr hbmColor;}/// <summary>/// 全局游标信息/// </summary>[StructLayout(LayoutKind.Sequential)]struct CURSORINFO{/// <summary>/// 结构大小(以字节为单位)。 调用方必须将此设置为 sizeof(CURSORINFO)。/// </summary>public Int32 cbSize;/// <summary>/// 游标状态。 此参数的取值可为下列值之一:0:光标处于隐藏。1:光标处于显示。2:Windows 8:取消光标。 此标志指示系统未绘制光标,因为用户是通过触摸或笔而不是鼠标提供输入。/// </summary>public Int32 flags;/// <summary>/// 光标的句柄。/// </summary>public IntPtr hCursor;/// <summary>/// 接收光标的屏幕坐标的结构。/// </summary>public Point ptScreenPos;}[Flags()]public enum KeyModifiers{None = 0,Alt = 1,Ctrl = 2,Shift = 4,WindowsKey = 8}class APIHelper{/// <summary>/// 获取与windows环境有关的信息/// </summary>/// <param name="mVal">指定获取信息</param>/// <returns></returns>[DllImport("user32.dll")]public static extern int GetSystemMetrics(int mVal);/// <summary>/// 获取指定图标或者鼠标的一个副本/// </summary>/// <param name="hIcon">欲复制的图标或指针的句柄</param>/// <returns></returns>[DllImport("user32.dll")]public static extern IntPtr CopyIcon(IntPtr hIcon);[DllImport("user32.dll", EntryPoint = "GetCursorInfo")]public static extern bool GetCursorInfo(ref CURSORINFO cInfo);[DllImport("user32.dll", EntryPoint = "GetIconInfo")]public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO iInfo);[DllImport("kernel32")]public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);[DllImport("kernel32")]public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath);/// <summary>/// 热键注册/// </summary>/// <param name="hWnd">要定义热键的窗口的句柄 </param>/// <param name="id">定义热键ID(不能与其它ID重复) </param>/// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效 </param>/// <param name="vk">定义热键的内容 </param>/// <returns>如果函数执行成功,返回值不为0。如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。</returns>[DllImport("user32.dll", SetLastError = true)]public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);/// <summary>/// 热键注销/// </summary>/// <param name="hWnd">要取消热键的窗口的句柄  </param>/// <param name="id">要取消热键的ID </param>/// <returns></returns>[DllImport("user32.dll", SetLastError = true)]public static extern bool UnregisterHotKey(IntPtr hWnd, int id);/// <summary>/// 从INI文件中读取数据/// </summary>/// <param name="filePath">INI文件的全路径</param>/// <param name="rootValue">根节点值,例如根节点[ConnectString]的值为:ConnectString</param>/// <param name="key">根节点下的键</param>/// <param name="defValue">当标记值未设定或不存在时的默认值</param>/// <returns></returns>}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/247147.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年春秋杯网络安全联赛冬季赛 Writeup

文章目录 Webezezez_phppicup Misc谁偷吃了外卖modules明文混淆 Pwnnmanagerbook Reupx2023 CryptoCF is Crypto Faker 挑战题勒索流量Ezdede 可信计算 Web ezezez_php 反序列化打redis主从复制RCE&#xff1a;https://www.cnblogs.com/xiaozi/p/13089906.html <?php c…

编码神仙插件Machinet AI GPT-4 Chat and Unit Tests

最近发现一个神仙插件Machinet AI GPT-4 Chat and Unit Tests&#xff0c;支持多个编译器安装使用。 我下载安装到Android Studio上&#xff0c;不需要登录直接可以使用。 可以直接提问&#xff0c;支持中文。

pyinstaller—PuLP投标价格预算项目打包过程踩坑

Python—pyinstaller打包PuLP踩坑 引言 在昨天的文章中&#xff0c;我们提到已经实现了相关代码的编写&#xff0c;即&#xff1a;通过Python环境和编辑器实现代码的运行&#xff0c;最终实现对数据的处理&#xff0c;得到想要的修改过后的项目结果。但是我们又面临着这样一个…

RK3588平台开发系列讲解(视频篇)RKMedia框架

文章目录 一、 RKMedia框架介绍二、 RKMedia框架API三、 视频处理流程四、venc 测试案例沉淀、分享、成长,让自己和他人都能有所收获!😄 📢RKMedia是RK提供的一种多媒体处理方案,可实现音视频捕获、音视频输出、音视频编解码等功能。 一、 RKMedia框架介绍 功能: VI(输…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-3 getBoundingClientRect()

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>getBoundingClientRect()</title> </head> <script>function getRect(){var obj document.getElementById(example); //获取元素对象var objR…

什么是数据库的三级模式两级映象?

三级模式两级映象结构图 概念 三级模式 内模式&#xff1a;也称为存储模式&#xff0c;是数据物理结构和存储方式的描述&#xff0c;是数据在数据库内部的表示方式。定义所有的内部记录类型、索引和文件组织方式&#xff0c;以及数据控制方面的细节。模式&#xff1a;又称概念…

第十八讲_HarmonyOS应用开发实战(实现电商首页)

HarmonyOS应用开发实战&#xff08;实现电商首页&#xff09; 1. 项目涉及知识点罗列2. 项目目录结构介绍3. 最终的效果图4. 部分源码展示 1. 项目涉及知识点罗列 掌握HUAWEI DevEco Studio开发工具掌握创建HarmonyOS应用工程掌握ArkUI自定义组件掌握Entry、Component、Builde…

数据目录驱动测试——深入探讨Pytest插件 pytest-datadir

在软件测试中,有效管理测试数据对于编写全面的测试用例至关重要。Pytest插件 pytest-datadir 提供了一种优雅的解决方案,使得数据目录驱动测试变得更加简单而灵活。本文将深入介绍 pytest-datadir 插件的基本用法和实际案例,助你更好地组织和利用测试数据。 什么是pytest-da…

Maven入门及其使用

目录 一、Maven入门 1.1 初识Maven 1.2 Maven的作用 1.2.1 依赖管理 1.2.2 统一项目结构 1.2.3 项目构建 1.3 Maven坐标 1.4 Maven仓库 1.4.1 Maven仓库概述 二、Maven的下载与安装 2.1 安装步骤 2.1.1 解压安装&#xff08;建议解压到没有中文、特殊字符的路径下。&#xff09…

基于 java+springboot+mybatis电影售票网站管理系统前台+后台设计和实现

基于 javaspringbootmybatis电影售票网站管理系统前台后台设计和实现 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承…

力扣hot100 字符串解码 栈 辅助栈

Problem: 394. 字符串解码 文章目录 思路&#x1f496; 辅助栈 思路 &#x1f468;‍&#x1f3eb; 路飞 &#x1f496; 辅助栈 ⏰ 时间复杂度: O ( n ) O(n) O(n) &#x1f30e; 空间复杂度: O ( n ) O(n) O(n) class Solution {public String decodeString(String s…

华为二层交换机与防火墙配置上网示例

二层交换机与防火墙对接上网配置示例 组网图形 图1 二层交换机与防火墙对接上网组网图 二层交换机简介配置注意事项组网需求配置思路操作步骤配置文件相关信息 二层交换机简介 二层交换机指的是仅能够进行二层转发&#xff0c;不能进行三层转发的交换机。也就是说仅支持二层…

力扣日记1.27-【回溯算法篇】131. 分割回文串

力扣日记&#xff1a;【回溯算法篇】131. 分割回文串 日期&#xff1a;2023.1.27 参考&#xff1a;代码随想录、力扣 131. 分割回文串 题目描述 难度&#xff1a;中等 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可…

常量和C预处理器

本文参考C Primer Plus第四章 文章目录 符号常量printf()函数和scanf()函数 printf()函数使用printf()printf()的转换说明修饰符 1.符号常量 C头文件limits.h和float.h分别提供了与整数类型和浮点类型大小限制相关的详细信息。头文件都定义了一系列供实现使用的符号常量。例如&…

腾讯云幻兽帕鲁4核16G14M服务器性能测评和价格

腾讯云幻兽帕鲁服务器4核16G14M配置&#xff0c;14M公网带宽&#xff0c;限制2500GB月流量&#xff0c;系统盘为220GB SSD盘&#xff0c;优惠价格66元1个月&#xff0c;277元3个月&#xff0c;支持4到8个玩家畅玩&#xff0c;地域可选择上海/北京/成都/南京/广州&#xff0c;腾…

网络安全02--负载均衡下的webshell连接

目录 一、环境准备 1.1ubentu虚拟机一台&#xff0c;docker环境&#xff0c;蚁剑 1.2环境压缩包&#xff08;文件已上传资源&#xff09;&#xff1a; 二、开始复原 2.1上传ubentu&#xff1a; 2.2解压缩 2.3版本20没有docker-compose手动下载&#xff0c;包已上传资源 …

uniapp复选框 实现排他选项

选择了排他选项之后 复选框其他选项不可以选择 <view class"reportData" v-for"(val, index) in obj" :key"index"> <view v-if"val.type 3" ><u-checkbox-group v-model"optionValue" placement"colu…

物联网协议Coap之C#基于Mozi的CoapClient调用解析

目录 前言 一、CoapClient相关类介绍 1、CoapClient类图 2、CoapClient的设计与实现 3、SendMessage解析 二、Client调用分析 1、创建CoapClient对象 2、实际发送请求 3、Server端请求响应 4、控制器寻址 总结 前言 在之前的博客内容中&#xff0c;关于在ASP.Net Co…

MongoDB实战

1.MongoDB介绍 1.1 什么是MongoDB MongoDB是一个文档数据库&#xff08;以JSON 为数据模型&#xff09;&#xff0c;由C语言编写&#xff0c;旨在为WEB应用提供可扩展的高性能数据存储解决方案。 文档来自于"JSON Document"&#xff0c;并非我们一般理解的 PDF&…

以太网交换基础VLAN原理与配置

目录 7.以太网交换基础 7.1.以太网协议 7.2.以太网帧介绍 7.3.以太网交换机 7.4.同网段数据通信全过程 8.VLAN原理与配置 8.1.VLAN的基本概念 8.2.VLAN的应用 7.以太网交换基础 7.1.以太网协议 以太网是当今现有局域网(Local Area Network,LAN)采用的最通用的通信协议…