QQ 截图启动器
看雪论坛 0xEEEE 在逆向调用QQ截图NT与WeChatOCR这篇文章中发布了调用新版 QQ 截图功能的软件 QQScreenShotNT-Plus,虽然已经设置了 QQScreenshot.exe 的路径,但是每次启动这个软件都要提示是否重新自动获取,在设置中去掉“启动提示”依然无效。在那篇文章中作者说 QQScreenShotNT-Plus 是在 QQImpl 基础上实现的,但是作者没有发布对应的源代码,因此我准备基于 Windows Forms 技术复刻相关的功能。因为是第一次使用 .NET 相关技术开发 Windows 系统的应用软件,所以会详细地记录整个开发过程。源代码在 QQScreenShotLauncher。
创建解决方案
这部分内容参考项目和解决方案简介。启动 Visual Studio 2022,在 Visual Studio 2022 对话框选择 Create a new project

在 Create a new project 对话框的在搜索框输入 solution,选择语言、平台、项目类型,然后选择 Blank Solution

在 Configure your new project 对话框输入解决方案名称 QQScreenShotLauncher,保存位置 D:\projects\dotnet\

创建 Git 仓库
这部分内容参考从 Visual Studio 创建 Git 存储库。在 Git 变更选择 Create Git Repository

在 Create a Git repository 对话框选择 Local only,Local path、.gitignore template、License template 三项使用默认值,勾选 Add a README.md 复选框

创建项目
这部分内容参考项目和解决方案简介。在解决方案资源管理器中,右键单击 QQScreenShotLauncher 解决方案,依次选择 Add 和 New Project

在搜索框输入 Windows Forms App,选择语言、平台、项目类型,然后选择 Windows Forms App

在 Configure your new project 对话框输入项目名称 NTLauncher,保存位置保持默认值

在 Additional information 对话框选择框架版本 .NET 8.0 (Long Term Support)

添加图标资源
这部分参考管理应用程序资源。在解决方案资源管理器中,右键单击 NTLauncher 项目,选择 Properties

选中 Resources > General,点击 Create or open assembly resources 链接

在 Resource Explorer 点击加号按钮

在 Add a new resource 对话框,Type 下拉框选择 Icon,其他保持默认,然后点击 Add existing file 按钮

在文件选择对话框中选择 NTLauncher.ico(这个文件来自 0xEEEE 在逆向调用QQ截图NT与WeChatOCR 提供的 QQScreenShotNT-Lite.zip 压缩包)

在 Add a new resource 对话框,Neutral value 就是刚刚选择的文件,Store as 下拉框选择 System.Drawing.Icon (Windows Forms),其他保持默认

设置应用程序图标
这部分参考指定应用程序图标 (Visual Basic, C#)。在解决方案资源管理器中,右键单击 NTLauncher 项目,选择 Properties

选中 Application > Win32 Resources,点击 Browse 按钮

在文件选择对话框中选择 NTLauncher.ico,注意选择文件所在的目录,这个文件是上一步添加图标资源添加到项目的 Resources 目录的

文件选择完成后 Icon 项的值为 Resources\NTLauncher.ico

添加系统托盘和右键菜单
这部分主要参考了以下资料
- NotifyIcon 组件概述(Windows 窗体)
- 如何使用 Windows 窗体 (Windows Forms) NotifyIcon 组件向任务栏添加应用程序图标
- 如何:将快捷菜单与 Windows 窗体 NotifyIcon 组件相关联
- 如何将 ContextMenuStrip 与控件关联
- 如何:向 ContextMenuStrip 添加菜单项
- NotifyIcon 类
- ContextMenuStrip 类
- winform实现最小化至系统托盘
- C#实现 Winform 程序在系统托盘显示图标 & 开机自启动
- WinForm窗体隐藏任务栏图标和系统托盘显示图标
添加 NotifyIcon 和 ContextMenuStrip 控件
在 Toolbox 搜索 NotifyIcon,将 NotifyIcon 控件拖入 Form1

对 ContextMenuStrip 控件进行类似的操作,控件添加完成后

配置 NotifyIcon 图标
选中 notifyIcon1 控件,在 Properties 找到 Appearance > Icon,点击右侧 … 按钮

在文件选择对话框中选择 NTLauncher.ico,注意选择文件所在的目录,这个文件是在添加图标资源添加到项目的 Resources 目录的

配置 NotifyIcon 右键菜单
选中 notifyIcon1 控件,在 Properties 找到 Behavior > ContextMenuStrip,在右侧下来选项中选择 contextMenuStrip1

配置 NotifyIcon 其他属性
选中 notifyIcon1 控件,配置 Appearance > Text 为 NTLauncher,配置 Behavior > Visible 为 True

notifyIcon1 的 Visible 配合 Form1 的 ShowInTaskbar 和 WindowState 就可以实现启动应用程序只显示托盘图标的功能。
添加右键菜单项
选中 contextMenuStrip1 控件,点击右上角三角形图标,在弹出的 ContextMenuStrip Tasks 中点击 Edit Items

在 Items Collection Editor 对话框选中 contextMenuStrip1 成员,选择 MenuItem,点击 Add 按钮添加菜单项

在 Items Collection Editor 对话框选中 contextMenuStrip1 成员,选择 Separator,点击 Add 按钮添加分割线

我们将添加 7 个菜单项,3 条分割线,通过右侧的功能按钮排序或删除

选中 toolStripMenuItem1,修改 Appearance > Text 的值为关于

对其他菜单项进行类似操作,编辑完成后的 Form1

使应用程序只显示托盘图标
选中 Form1 控件,设置 Layout > WindowState 为 Minimized,设置 Window Style > ShowInTaskbar 为 False

添加托盘退出事件
选中 contextMenuStrip1 控件,然后选中退出菜单项,配置 Action > Click 为 toolStripMenuItem7_Click

上面的操作会自动在 Form1.cs
中创建函数 toolStripMenuItem7_Click
,其实现为
1 | private void toolStripMenuItem7_Click(object sender, EventArgs e) |
添加设置对话框
这部分内容主要参考了以下资料
- C# Winform同一子窗体只允许打开一次
- WinForm窗体应用——父窗体每次只打开一个子窗体的方法
- c# WinForm 点击出现弹出多个窗体, 怎么才能只显示一个窗体。解决方案
- C# WinForm 点击按钮显示唯一窗体
- C#窗体程序(winform)禁止最小化、最大化,或去掉关闭按钮
- WinForm 设置窗体启动位置在活动屏幕右下角
新增设置对话框
在 NTLauncher 项目上单击右键,在弹出菜单中依次选择 Add > New Items

在 Add New Item 对话框中选中 Installed > C# Items,在右侧选中 Form (Windows Forms),注意下方 Name 的值 Form2.cs

点击设置菜单项显示设置对话框
在 Form1 选中 contextMenuStrip1 控件,然后选中设置菜单项,配置 Action > Click 为 toolStripMenuItem2_Click

上面的操作会自动在 Form1.cs
中创建函数 toolStripMenuItem2_Click
,其实现为
1 | private Form2? form2 = null; |
在这个实现里增加了一个变量 form2
来表示打开的设置对话,对话框关闭时把该变量置空,这保证多次点击设置菜单只打开一个对话框。
配置设置对话框样式
选中 Form2,设置 Appearance > Text 为 设置,设置 Window Style > MaximizeBox 为 False,设置 Window Style > MinimizeBox 为 False,设置 Window Style > ShowIcon 为 False,设置 Window Style > ShowInTaskbar 为 False

设置对话框启动位置在屏幕右下角
选中 Form2,设置 Layout > StartPosition 为 Manual

在 Form2.cs
中重新计算对话框的位置
1 | public Form2() |
绘制对话框
这部分内容主要参考了以下资料
- 教程:使用 .NET 创建 Windows 窗体应用
- 教程:创建数学测验 WinForms 应用
- 控件的位置和布局(Windows 窗体 .NET)
- 演示:使用捕捉线排列 Windows 窗体上的控件
- 如何:在 Windows 窗体上对齐多个控件
- Winform禁止调整大小
主要用到的控件为 GroupBox、CheckBox、Label、TextBox、Button,成品图如下所示

选中 Form2,设置 Appearance > FormBorderStyle 为 FixedSingle,禁止改变窗口大小
