C编写一个简单易用的Windows截屏增强工具
半年前我开源了 DreamScene2 一个小而快并且功能强大的 Windows 动态桌面软件。有很多的人喜欢,这使我有了继续做开源的信心。这是我的第二个开源作品 ScreenshotEx 一个简单易用的 Windows 截屏增强工具。
欢迎 Star 和 Fork https://github.com/he55/ScreenshotEx 前言
在使用 Windows 系统的截屏快捷键 PrintScreen 截屏时,如果需要把截屏保存到文件,需要先粘贴到画图工具然后另存为文件。以前我还没有觉得很麻烦,后来使用了 macOS 系统的截屏工具,我才知道原来一个小小的截屏工具也可以这么简单易用。于是参考 macOS 系统的截屏工具做了一个 Windows 版的。功能自动保存截屏到桌面
点击截屏预览可以编辑截屏
实现原理
如果想在按下系统的截屏快捷键后做一些事情,能想到的方法应该就是如何监听键盘事件。WIN32 API 提供的 SetWindowsHookExA 钩子函数刚好可以实现这个需求, idHook 参数设置成 WH_KEYBOARD_LL 时是低等级键盘钩子可以捕获键盘消息。
SetWindowsHookExA 函数定义HHOOK SetWindowsHookExA( [in] int idHook, // 钩子类型 [in] HOOKPROC lpfn, // 钩子处理函数 [in] HINSTANCE hmod, // 模块句柄 [in] DWORD dwThreadId // 线程Id );
键盘处理函数定义 LRESULT CALLBACK LowLevelKeyboardProc( _In_ int nCode, _In_ WPARAM wParam, // 键盘消息 _In_ LPARAM lParam // KBDLLHOOKSTRUCT 结构体指针 ); 代码
C# PInvoke 定义 const int HC_ACTION = 0; const int WH_KEYBOARD_LL = 13; const int WM_KEYUP = 0x0101; const int WM_SYSKEYUP = 0x0105; const int VK_SNAPSHOT = 0x2C; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct KBDLLHOOKSTRUCT { public uint vkCode; public uint scanCode; public uint flags; public uint time; public UIntPtr dwExtraInfo; } [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr HookProc(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hmod, int dwThreadId); [DllImport("User32.dll", SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("User32.dll", SetLastError = false, ExactSpelling = true)] public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr GetModuleHandle([Optional] string lpModuleName);
注册键盘钩子
需要注意:因为 SetWindowsHookEx 是非托管函数第二个参数是个委托类型,GC 不会记录非托管函数对 .NET 对象的引用。如果用临时变量保存委托出作用域就会被 GC 释放,当 SetWindowsHookEx 去调用已经被释放的委托就会报错。
SetWindowsHookEx 函数第一个参数传 WH_KEYBOARD_LL 低等级键盘钩子、第二个参数传键盘消息处理函数的委托、第三个参数使用 GetModuleHandle 函数获取模块句柄、第四个参数传 0。HookProc _hookProc; IntPtr _hhook; void StartHook() { _hookProc = new HookProc(LowLevelKeyboardProc); // 使用成员变量保存委托 _hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, GetModuleHandle(null), 0); // 注册键盘钩子,保存返回值卸载钩子时用到。GetModuleHandle(null) 获取当前模块句柄 }
键盘消息处理函数
在键盘消息处理函数里面捕获 PrintScreen 按键消息,然后显示预览和保存图片逻辑IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam) { if (nCode == HC_ACTION) { if (lParam.vkCode == VK_SNAPSHOT) // 捕获 PrintScreen 按键消息 { if ((int)wParam == WM_KEYUP || (int)wParam == WM_SYSKEYUP) // 按键释放时保存图片 SaveImage(); else _previewWindow.SetHide(); } } return CallNextHookEx(_hhook, nCode, wParam, ref lParam); }
保存图片
从系统剪贴板获取图片 void SaveImage() { if (Clipboard.ContainsImage()) { if (!Directory.Exists(_settings.SavePath)) Directory.CreateDirectory(_settings.SavePath); string ext = "png"; ImageFormat imageFormat = ImageFormat.Png; switch (_settings.SaveExtension) { case 0: imageFormat = ImageFormat.Png; ext = "png"; break; case 1: imageFormat = ImageFormat.Jpeg; ext = "jpg"; break; case 2: imageFormat = ImageFormat.Bmp; ext = "bmp"; break; } if (_settings.SaveName == 0) { string name = DateTime.Now.ToString("yyyy-MM-dd HH.mm.ss"); _saveFilePath = Path.Combine(_settings.SavePath, #34;{PrefixName} {name}.{ext}"); } else { do { _saveFilePath = Path.Combine(_settings.SavePath, #34;{PrefixName} {_nameIndex}.{ext}"); _nameIndex++; } while (File.Exists(_saveFilePath)); } Image image = Clipboard.GetImage(); image.Save(_saveFilePath, imageFormat); if (_settings.IsPlaySound) _soundPlayer.Play(); if (_settings.IsShowPreview) _previewWindow.SetImage(_saveFilePath); } }
完整代码 https://github.com/he55/ScreenshotEx
文章来自https://www.cnblogs.com/he55/p/16253321.html
中国电信研究院院长张成良在最好的时代做顶天立地的科创人在中国电信科技创新的这盘大棋中,中国电信研究院将发挥怎样的作用,将进行哪些机制创新?如何实现成果转化,将论文写在祖国大地上?又如何将网络牢牢控制在自己手里?带着一系列问题,记者近日
技术支付宝小程序开发笔记最近开发支付宝小程序,记录一下遇到的坑1sjs只支持从sjs文件中导入模块,不能从其他js中引入。这个限制,只能在sjs里写一些小功能。2sjs不支持正则!sjs支持es6语法,这
不违法而且赚钱从1688搬运产品卖到亚马逊,方法都在这里赶紧收藏起来!操作就是从国内1688找产品搬运到亚马逊美国站,赚取一个产品差价美元汇率差价。举个例子这款仿真玫瑰花,在美国亚马逊站点可以卖
一文速览以太坊ETH核心开发者会议更新要点以下是本次更新的重点最新的合并测试网Kiln已经启动。在上面进行的PoS过渡揭示了一些实现上的问题,现在所有人都把工作重心放在合并测试上。下一次的以太坊升级上海升级在拟定中,计划中
涉及三大领域!2022年北京以色列联合研发计划课题建议征集开始啦关于征集2022年北京以色列联合研发计划课题建议的通知各有关单位为促进本市与以色列间技术创新与研发合作,现征集北京以色列联合研发计划课题建议,相关工作安排如下1hr支持方向北京以色
电子邮件的工作原理在Internet上将一段文本信息从一台计算机传送到另外一台计算机,可通过两种协议来完成,即SMTP(SimpleMailTransferProtocol,简单邮件传输协议)和PO
全球6G技术大会重磅发布13本白皮书本报讯(记者张伟)3月2224日,在第二届全球6G技术大会期间,主办方之一未来移动通信论坛重磅发布13本白皮书。其中,在6G主题方面发布了总体白皮书ICDT融合下的6G网络2。0,
新特性解读作者杨涛涛资深数据库专家,专研MySQL十余年。擅长MySQLPostgreSQLMongoDB等开源数据库相关的备份恢复SQL调优监控运维高可用架构设计等。目前任职于爱可生,为各
腾讯报告全真互联分布式云原生等技术将助力金融科技创新于蒙蒙中国证券报中证网中证网讯(记者于蒙蒙)3月29日,腾讯金融研究院腾讯云和毕马威联合发布数实共生2022金融科技十大趋势展望报告。该报告从可信数据智能安全普惠五个层面出发,提出
华为公司已经度过最黑暗的时期3月28日,华为公司发布了2021年度经营情况。华为收入虽然大降28。7,但是净利润和经营现金流都大幅增长超过50,并且研发费用达到1427亿元,占收入比大约为22。4。借用孟晚舟
为什么很多人都说百度是家缺德的公司?我不是IT界人士,但听到很多此类说法。比如这里有篇文章httpwww。williamlong。infoarchives376。html,韩寒因为版权的问题也骂过李彦宏。但想知道赞同