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.mzph.cn/news/653460.shtml

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

相关文章

在Linux中用C语言实现Socket通信

Socket是封装了TCP协议&#xff0c;让我们更容易使用TCP协议。TCP协议在OSI模型中属于四层协议&#xff0c;即传输层协议。 TCP&#xff0c;中文叫传输控制协议&#xff0c;它是一种面向连接的协议&#xff0c;就是说它通信前必须先连接&#xff0c;再能通信。设计TCP这种协议的…

【算法与数据结构】139、LeetCode单词拆分

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题可以看做一个动态规划问题。其中&#xff0c;字符串s是背包&#xff0c;而字典中的单词就是物品。…

Dubbo框架注册中心-Zookeeper搭建

Dubbo 是阿里巴巴公司开源的高性能、轻量级的Java RPC框架&#xff0c;致力于提供高性能。 Dubbo官网 本篇开始dubbo的第一篇&#xff0c;注册中心 ZooKeeper 环境搭建。 环境前置&#xff1a;由于Zookeeper是基于Java环境&#xff0c;必须安装有JDK。查看命令 java -version。…

服务端开发小记01——Tomcat

Tomcat Tomcat简介Tomcat在Linux下的安装Tomcat验证Tomcat常用命令&#xff08;Linux下&#xff09; Tomcat简介 Tomcat是一个Web容器&#xff0c;JavaEE程序可以在此运行。Tomcat是一个中间件&#xff0c;在B/S架构中&#xff0c;浏览器发出的http请求经过tpmcat中间件&#…

面试经典题---30.串联所有单词的子串

30.串联所有单词的子串 我的解法&#xff1a; 滑动窗口&#xff1a; 解法中用到了两个哈希表map1和map2&#xff0c;分别用于记录words中各个单词的出现频数和当前滑动窗口[left, right)中单词的出现频数&#xff1b;外部for循环i从0到len - 1&#xff0c;内部while循环每次会…

降压模块LM2596S的操作使用

一、技术参数 二、使用说明 1.引脚说明&#xff1a; IN输入正极 IN-输入负极 OUT输出正极 OUT-输出负极 2.输入电压范围&#xff1a;直流3.2V 至 46V (输入的电压必须比要输出的电压高1.5V以上。不能升压) 3.输出电压范围&#xff1a;直流 1.25V至 35V 电压连续可调&#…

SBDD的节点选择(Node selection)和树的扩展(Tree expansion)的操作是怎么进行的?

Node selection: 1&#xff09;选择规则&#xff1a; “focus atom”是从生成的原子中选出的&#xff0c;如果一个原子没有“capped”&#xff0c;那么它就可以被选为“focus atom”。 一个原子被“capped”是因为它的化合价约束&#xff08;valency constraint&#xff09;…

内网安全:NTLM-Relay

目录 NTLM认证过程以及攻击面 NTLM Relay攻击 NTLM攻击总结 实验环境说明 域横向移动&#xff1a;NTLM中继攻击 攻击条件 实战一&#xff1a;NTLM中继攻击-CS转发上线MSF 原理示意图 一. CS代理转发 二. MSF架设路由 三. 适用smb_relay模块进行中继攻击 域横向移动…

【李宏毅机器学习】Transformer 内容补充

视频来源&#xff1a;10.【李宏毅机器学习2021】自注意力机制 (Self-attention) (上)_哔哩哔哩_bilibili 发现一个奇怪的地方&#xff0c;如果直接看ML/DL的课程的话&#xff0c;有很多都是不完整的。开始思考是不是要科学上网。 本文用作Transformer - Attention is all you…

ASP.NET Core基础之用扩展方法封装服务配置

阅读本文你的收获 了解C#中的扩展方法机制学会在ASP.NET Core 中&#xff0c;用扩展方法封装服务配置&#xff0c;使得代码更加简洁 一、什么是扩展方法 扩展方法使能够向现有类型添加方法&#xff0c;而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法…

Python笔记12-多线程、网络编程、正则表达式

文章目录 多线程网络编程正则表达式 多线程 现代操作系统比如Mac OS X&#xff0c;UNIX&#xff0c;Linux&#xff0c;Windows等&#xff0c;都是支持“多任务”的操作系统。 进程&#xff1a; 就是一个程序&#xff0c;运行在系统之上&#xff0c;那么便称之这个程序为一个运…

LLMs 的记忆和信息检索服务器 Motorhead

LLMs 的记忆和信息检索服务器 Motorhead 1. 为什么使用 Motorhead&#xff1f;2. 通过 Docker 启动 Motorhead3. Github 地址4. python 使用示例地址 1. 为什么使用 Motorhead&#xff1f; 使用 LLMs构建聊天应用程序时&#xff0c;每次都必须构建记忆处理。Motorhead是协助该…

CTF CRYPTO 密码学-7

题目名称&#xff1a;敲击 题目描述&#xff1a; 让我们回到最开始的地方 0110011001101100011000010110011101111011011000110110010100110011011001010011010100110000001100100110001100101101001101000011100001100011001110010010110100110100011001000011010100110000…

系统分析师-23年-论文试题

系统分析师-23年-论文试题 更多软考知识请访问 https://ruankao.blog.csdn.net/ 题目任选其一 摘要字数在400字以内&#xff0c;可以分条叙述&#xff0c;但不允许有图、表、流程图。 正文字数为2000字至300字&#xff0c;文中可以分条叙述&#xff0c;但不要全部用分条叙述…

微搭低代码从入门到精通01应用介绍

目录 1 学习路线图2 应用介绍3 编辑器介绍总结 低代码的概念于2014年由 Forrester 首次正式提出。其将低代码定义为&#xff1a;能够以“最少的手写代码”和设置快速开发应用、配置和部署业务应用程序。 不同应用厂商的解法不一样&#xff0c;Gartner评估了400多款低代码/无代码…

Spark Exchange节点和Partitioning

​Exchange 在explain时&#xff0c;常看到Exchange节点&#xff0c;这个节点其实就是发生了数据交换 此图片来自于网络截取 BroadcastExchangeExec 主要是用来广播的 ShuffleExchangeExec 里面决定了数据分布的方式和采用哪种shuffle 在这里可以看到好几种不同的分区器 shuf…

Android 13.0 SystemUI下拉状态栏定制二 锁屏页面横竖屏时钟都居中功能实现二

1.前言 在13.0的系统rom定制化开发中,在关于systemui的锁屏页面功能定制中,由于在平板横屏锁屏功能中,时钟显示的很大,并且是在左旁边居中显示的, 由于需要和竖屏显示一样,所以就需要用到小时钟显示,然后同样需要居中,所以就来分析下相关的源码,来实现具体的功能 如图…

51单片机智能小车

51单片机智能小车 delay.c #include "intrins.h"void Delay2000ms() //11.0592MHz {unsigned char i, j, k;i 15;j 2;k 235;do{do{while (--k);} while (--j);} while (--i); }void Delay10us() //11.0592MHz {unsigned char i;i 2;while (--i); }void Delay…

Spring 事务原理二

该说些什么呢&#xff1f;一连几天&#xff0c;我都沉溺在孤芳自赏的思维中无法自拔。不知道自己为什么会有这种令人不齿的表现&#xff0c;更不知道这颗定时炸弹何时会将人炸的粉身碎骨。好在儒派宗师曾老夫子“吾日三省吾身”的名言警醒了我。遂潜心自省&#xff0c;溯源头以…

Azure AD 和 Identity Server4 客户端身份验证和授权

使用 React 和 IdentityServer4 进行身份验证 1.安装所需的库 npm install oidc-client2.配置 IdentityServer4 客户端 在 IdentityServer4 中&#xff0c;需要配置一个客户端来使用 OpenID Connect 协议进行身份验证。客户端需要配置客户端 ID、客户端秘钥、重定向 URI 和要…