为.NET应用添加截图功能

简介: 本文介绍了 .NET 实现截图功能的思路和过程,如果你仅想了解最后的解决方案,可以直接查看文章末尾。

截图的功能我们应该都经常使用,在开发软件时,我们有时也或多或少需要提供这方面的功能,无论是为用户更方便提供远程诊断,还是获取用户的选择区域,亦或是提供某些功能上的辅助。

开发截图无非就这几种选择:教用户使用截图工具、自行开发一个、使用第三方库。

教用户使用

教的成本无疑是最低的,但是不知道用户那边会发生什么,存在很大的不确定性。截图软件除了我们经常用的聊天工具和系统自带的 Win + Ctrl + S外,我用起来感觉最好的还是 C++ 写的开源软件 flameshot ,功能非常强大。

flameshot

使用的第三方的截图软件,不仅有教的成本,还会打断用户对本身软件的一个使用体验。教用户使用最好还是用系统自带的 Win + Ctrl + S截图,已经可以满足基本的截图需求。

自行开发

自行开发的原理也非常简单:创建一个半透明的全屏无边框窗体,记录鼠标在窗体上的框选矩形位置,使用CopyFromScreen获取该位置的屏幕图片即可。

以上只是针对单个显示器的情况,若有多个显示器,则需要增加鼠标所在显示器的逻辑。

虽然听起来不难,但代码实现起来还是有许多要注意的细节。简单的矩形截图实现不难,难得是让用户易用,易接受,毕竟聊天软件已经帮你培养了用户习惯。

使用第三方库

CSkin 是我在 2012 年就在使用的一款界面库,在 WinForm 无疑是软件 UI 美化的王者,可以直接作出和 PC 端 QQ 一样的界面体验。库里也提供了截图工具 FrmCapture,没中不足的是,在多显示器场景下会报错,无法正常使用,代码库也有 4 年没有更新了。

private FrmCapture m_frmCapture;
if (m_frmCapture == null || m_frmCapture.IsDisposed)
{
    m_frmCapture = new FrmCapture();
}
m_frmCapture.IsCaptureCursor = false;
// 截图结束事件
m_frmCapture.Disposed += M_frmCapture_Disposed;
m_frmCapture.Show();

HandyControl 和在 nuget 上搜索到的 ScreenCapturerSharp 虽然也可以实现截图功能,但都无法处理多显示器的场景。HandyControl 社区活跃,其使用体验会比较好。ScreenCapturerSharp 提供了类似 QQ 的截图工具库,在 UI 上稍差一些。

如何又快又好又容易

如果只是获取截图,有没有更简单的方式呢?我们只需要模拟按键 Win + Ctrl + S 就可以了呀,然后通过剪贴板获取到截图。说起来容易,但是事情其实并没有那么简单。

首先 SendKeys 就不支持发送 Windows 徽标按键,我们需要通过 WinAPI keybd_event 来替代实现,然后还要获取到截图结束的事件。

[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

其实上面是一个保底的通用方案,我们可以自行启动截图软件,启动截图软件读取剪贴板Clipboard.GetImage() 一套结束,无缝无感,堪称完美:

Process snippingToolProcess = new Process()
{
    StartInfo = new ProcessStartInfo("C:\\Windows\\system32\\SnippingTool.exe", "/clip"),
    EnableRaisingEvents = true,
};
snippingToolProcess.Exited += SnippingToolProcess_Exited;
snippingToolProcess.Start();

事情其实远没有那么简单,直到我在 Win11 用了我的软件。才意识到,这只是可以在 Win10 的 64 位操作系统使用。SnippingTool /clip 这样带参数启动在 Win11 不支持了,这个路径下的 exe 还被删除了。

虽然你可以在 Win11 通过控制台使用SnippingTool /clip启动截图软件,但是并不会直接进入截图流程,而是打开软件主界面。

仔细研究你会发现,Win11 的截图其实已经是 UWP 应用了,就算你吧 Win10 的 SnippingTool.exe 复制到 Win11 也是报错,无法使用的,所以你也不可能在自己的软件打包带上它。

经过几番折腾,我在微软社区提问和提交反馈( Win + F 的时候我觉得这个软件是不是这样启动直接就先截了个屏 ),但是没有找到新版本截图的启动参数。最后直到我前几天发现 Microsoft Learn 的文章 启动屏幕截取 - UWP applications。在 UWP 里使用这么简单嘛,使用 LaunchUriAsync 就可以了。

bool result = await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-screenclip:"));

有了 URI 的方式,一切就变简单了,你甚至可以在浏览器里调用截图,放一个超链接,或者直接在浏览器地址栏粘贴ms-screenclip:后回车打开截图。

之后我们只需要监听进程结束就可以了,这里需要说明的是,不是启动的进程,而是截图的进程,下面直接上在 WinForm 中使用的代码:

var psi = new ProcessStartInfo()
{
    UseShellExecute = true,
    FileName = "ms-screenclip:"
};
Process.Start(psi);

// 获取 ScreenClippingHost 这个截图进程的结束事件
var snippingToolProcess = Process.GetProcessesByName("ScreenClippingHost")[0];
snippingToolProcess.EnableRaisingEvents = true;
snippingToolProcess.Exited += SnippingToolProcess_Exited;

SnippingToolProcess_Exited 事件:

private void SnippingToolProcess_Exited(object? sender, EventArgs e)
{
    this.BeginInvoke(new Action(() =>
    {
        var img = Clipboard.GetImage();
    }));
}
相关文章
|
29天前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
60 10
|
2月前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
18天前
|
数据采集 JSON API
.NET 3.5 中 HttpWebRequest 的核心用法及应用
【9月更文挑战第7天】在.NET 3.5环境下,HttpWebRequest 类是处理HTTP请求的一个核心组件,它封装了HTTP协议的细节,使得开发者可以方便地发送HTTP请求并接收响应。本文将详细介绍HttpWebRequest的核心用法及其实战应用。
53 6
|
2月前
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
67 3
|
2月前
|
缓存 Java API
【揭秘】.NET高手不愿透露的秘密:如何让应用瞬间提速?
【8月更文挑战第28天】本文通过对比的方式,介绍了针对 .NET 应用性能瓶颈的优化方法。以一个存在响应延迟和并发处理不足的 Web API 项目为例,从性能分析入手,探讨了使用结构体减少内存分配、异步编程提高吞吐量、EF Core 惰性加载减少数据库访问以及垃圾回收机制优化等多个方面,帮助开发者全面提升 .NET 应用的性能和稳定性。通过具体示例,展示了如何在不同场景下选择最佳实践,以实现更高效的应用体验。
32 3
|
2月前
|
前端开发 JavaScript 开发工具
跨域联姻:React.NET——.NET应用与React的完美融合,解锁前后端高效协作新姿势。
【8月更文挑战第28天】探索React.NET,这是将热门前端框架React与强大的.NET后端无缝集成的创新方案。React以其组件化和虚拟DOM技术著称,能构建高性能、可维护的用户界面;.NET则擅长企业级应用开发。React.NET作为桥梁,使.NET应用轻松采用React构建前端,并优化开发流程与性能。通过直接托管React组件,.NET应用简化了部署流程,同时支持服务器端渲染(SSR),提升首屏加载速度与SEO优化。
28 1
|
2月前
|
存储 缓存 安全
.NET 在金融行业的应用:高并发交易系统的构建与优化之路
【8月更文挑战第28天】在金融行业,交易系统需具备高并发处理、低延迟及高稳定性和安全性。利用.NET构建此类系统时,可采用异步编程提升并发能力,优化数据库访问以降低延迟,使用缓存减少数据库访问频率,借助分布式事务确保数据一致性,并加强安全性措施。通过综合优化,满足金融行业的严苛要求。
33 1
|
2月前
|
大数据 开发工具 开发者
从零到英雄:.NET核心技术带你踏上编程之旅,构建首个应用,开启你的数字世界探险!
【8月更文挑战第28天】本文带领读者从零开始,使用强大的.NET平台搭建首个控制台应用。无论你是新手还是希望扩展技能的开发者,都能通过本文逐步掌握.NET的核心技术。从环境搭建到创建项目,再到编写和运行代码,详细步骤助你轻松上手。通过计算两数之和的小项目,你不仅能快速入门,还能为未来开发更复杂的应用奠定基础。希望本文为你的.NET学习之旅开启新篇章!
29 1
|
2月前
|
缓存 运维 前端开发
阿里云云效操作报错合集之如何解决在使用流水线构建net8应用时遇到无法构建的报错
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
2月前
|
数据库 C# 开发者
WPF开发者必读:揭秘ADO.NET与Entity Framework数据库交互秘籍,轻松实现企业级应用!
【8月更文挑战第31天】在现代软件开发中,WPF 与数据库的交互对于构建企业级应用至关重要。本文介绍了如何利用 ADO.NET 和 Entity Framework 在 WPF 应用中访问和操作数据库。ADO.NET 是 .NET Framework 中用于访问各类数据库(如 SQL Server、MySQL 等)的类库;Entity Framework 则是一种 ORM 框架,支持面向对象的数据操作。文章通过示例展示了如何在 WPF 应用中集成这两种技术,提高开发效率。
41 0
下一篇
无影云桌面