1. 增加 窗口控制帮助类

2. 增加 热键编辑窗体
3. 增加 进程选择窗体
4. 增加 KeyGo核心功能类
5. 实现 热键信息到XML文件IO
6. 实现 热键注册与注销相关操作
This commit is contained in:
筱傑 2021-04-28 18:43:41 +08:00
parent da0a4032b9
commit 723a9f16f5
14 changed files with 1247 additions and 92 deletions

143
KeyGo/AppControl.cs Normal file
View File

@ -0,0 +1,143 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
namespace KeyGo
{
public class AppControl
{
/// <summary>
/// 获取本应用程序当前正在运行的进程若不存在则返回null
/// </summary>
/// <returns>当前正在运行的进程</returns>
private static Process GetCurrentRunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
//遍历与当前进程名称相同的进程列表
foreach (Process process in processes)
{
//如果实例已经存在则忽略当前进程
if (process.Id != current.Id)
{
//保证要打开的进程同已经存在的进程来自同一文件路径
if (Assembly.GetExecutingAssembly().Location.Replace('/', '\\') == current.MainModule.FileName)
{
//返回已经存在的进程
return process;
}
}
}
return null;
}
/// <summary>
/// 显示指定实例窗体
/// </summary>
/// <param name="instance">The instance.</param>
private static void ShowWindow(Process instance)
{
if (instance != null && instance.MainWindowHandle != IntPtr.Zero)
ShowWindowAsync(instance.MainWindowHandle, (int)CmdShow.Show);
//SetForegroundWindow(instance.MainWindowHandle);
}
/// <summary>
/// 隐藏指定实例窗体
/// </summary>
/// <param name="instance">The instance.</param>
public static void HideWindow(Process instance)
{
if (instance != null && instance.MainWindowHandle != IntPtr.Zero)
ShowWindowAsync(instance.MainWindowHandle, (int)CmdShow.Hide);
}
private enum CmdShow : int
{
/// <summary>
/// Minimizes a window, even if the thread that owns the window is not responding.
/// This flag should only be used when minimizing windows from a different thread.
/// </summary>
ForceMinimize = 11,
/// <summary>
/// Hides the window and activates another window.
/// </summary>
Hide = 0,
/// <summary>
/// Maximizes the specified window.
/// </summary>
Maximize = 3,
/// <summary>
/// Minimizes the specified window and activates the next top-level window in the Z order.
/// </summary>
Minimize = 6,
/// <summary>
/// Activates and displays the window.
/// If the window is minimized or maximized,
/// the system restores it to its original size and position.
/// An application should specify this flag when restoring a minimized window.
/// </summary>
Restore = 9,
/// <summary>
/// Activates the window and displays it in its current size and position.
/// </summary>
Show = 5,
/// <summary>
/// Sets the show state based on the SW_ value specified in the STARTUPINFO
/// structure passed to the CreateProcess function by the program that started
/// the application.
/// </summary>
ShowDefault = 10,
/// <summary>
/// Activates the window and displays it as a maximized window.
/// </summary>
ShowMaximized = 3,
/// <summary>
/// Activates the window and displays it as a minimized window.
/// </summary>
ShowMinimized = 2,
/// <summary>
/// Displays the window as a minimized window.
/// This value is similar to SW_SHOWMINIMIZED,
/// except the window is not activated.
/// </summary>
ShowMinnoActive = 7,
/// <summary>
/// Displays the window in its current size and position.
/// This value is similar to SW_SHOW, except that the window is not activated.
/// </summary>
ShowNA = 8,
/// <summary>
/// Displays a window in its most recent size and position.
/// This value is similar to SW_SHOWNORMAL, except that the window is not activated.
/// </summary>
ShowNoactivate = 4,
/// <summary>
/// Activates and displays a window.
/// If the window is minimized or maximized,
/// the system restores it to its original size and position.
/// An application should specify this flag when displaying the window for the first time.
/// </summary>
ShowNormal= 1,
}
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(System.IntPtr hWnd);
}
}

View File

@ -1,30 +1,56 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace KeyGo
{
public class AppHotKey
{
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
/// <summary>
/// 注册热键
/// </summary>
/// <param name="hwnd">窗口句柄</param>
/// <param name="hotKey_id">热键ID</param>
/// <param name="keyModifiers">组合键</param>
/// <param name="key">热键</param>
public static void RegKey(IntPtr hwnd, int hotKey_id, KeyModifiers keyModifiers, Keys key)
{
if (!RegisterHotKey(hwnd, hotKey_id, keyModifiers, key))
{
throw new Win32Exception();
//int code = Marshal.GetLastWin32Error();
//if (code == 1409)
// MessageBox.Show("热键被占用!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
//else
// MessageBox.Show("注册热键失败!错误代码:" + code.ToString(), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 注销热键
/// </summary>
/// <param name="hwnd">窗口句柄</param>
/// <param name="hotKey_id">热键ID</param>
public static void UnRegKey(IntPtr hwnd, int hotKey_id)
{
//注销Id号为hotKey_id的热键设定
UnregisterHotKey(hwnd, hotKey_id);
}
//如果函数执行成功返回值不为0。
//如果函数执行失败返回值为0。要得到扩展错误信息调用GetLastError。
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(
private static extern bool RegisterHotKey(
IntPtr hWnd, //要定义热键的窗口的句柄
int id, //定义热键ID不能与其它ID重复
int id, //定义热键ID不能与其它ID重复
KeyModifiers fsModifiers, //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效
Keys vk //定义热键的内容
);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(
private static extern bool UnregisterHotKey(
IntPtr hWnd, //要取消热键的窗口的句柄
int id //要取消热键的ID
);
@ -39,41 +65,5 @@ namespace KeyGo
Shift = 4,
WindowsKey = 8
}
/// <summary>
/// 注册热键
/// </summary>
/// <param name="hwnd">窗口句柄</param>
/// <param name="hotKey_id">热键ID</param>
/// <param name="keyModifiers">组合键</param>
/// <param name="key">热键</param>
public static void RegKey(IntPtr hwnd, int hotKey_id, KeyModifiers keyModifiers, Keys key)
{
//try
//{
if (!RegisterHotKey(hwnd, hotKey_id, keyModifiers, key))
{
throw new Win32Exception();
//int code = Marshal.GetLastWin32Error();
//if (code == 1409)
// MessageBox.Show("热键被占用!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
//else
// MessageBox.Show("注册热键失败!错误代码:" + code.ToString(), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
//}
//catch (Exception ex)
//{
// MessageBox.Show("注册热键失败!异常信息:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
//}
}
/// <summary>
/// 注销热键
/// </summary>
/// <param name="hwnd">窗口句柄</param>
/// <param name="hotKey_id">热键ID</param>
public static void UnRegKey(IntPtr hwnd, int hotKey_id)
{
//注销Id号为hotKey_id的热键设定
UnregisterHotKey(hwnd, hotKey_id);
}
}
}
}

196
KeyGo/FormHotKey.Designer.cs generated Normal file
View File

@ -0,0 +1,196 @@

namespace KeyGo
{
partial class FormHotKey
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.BtnAccept = new System.Windows.Forms.Button();
this.BtnCancel = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.TxtProcessName = new System.Windows.Forms.TextBox();
this.TxtStartupPath = new System.Windows.Forms.TextBox();
this.TxtHotKey = new System.Windows.Forms.TextBox();
this.BtnSelectProcess = new System.Windows.Forms.Button();
this.BtnSelectStartupPath = new System.Windows.Forms.Button();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.SuspendLayout();
//
// BtnAccept
//
this.BtnAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.BtnAccept.Location = new System.Drawing.Point(320, 64);
this.BtnAccept.Name = "BtnAccept";
this.BtnAccept.Size = new System.Drawing.Size(75, 23);
this.BtnAccept.TabIndex = 2;
this.BtnAccept.Text = "确定";
this.BtnAccept.UseVisualStyleBackColor = true;
this.BtnAccept.Click += new System.EventHandler(this.BtnAccept_Click);
//
// BtnCancel
//
this.BtnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.BtnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.BtnCancel.Location = new System.Drawing.Point(401, 64);
this.BtnCancel.Name = "BtnCancel";
this.BtnCancel.Size = new System.Drawing.Size(75, 23);
this.BtnCancel.TabIndex = 3;
this.BtnCancel.Text = "取消";
this.BtnCancel.UseVisualStyleBackColor = true;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(68, 17);
this.label1.TabIndex = 4;
this.label1.Text = "进程名称:";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 38);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(68, 17);
this.label3.TabIndex = 6;
this.label3.Text = "启动路径:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 67);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(68, 17);
this.label2.TabIndex = 6;
this.label2.Text = "触发热键:";
//
// TxtProcessName
//
this.TxtProcessName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.TxtProcessName.Location = new System.Drawing.Point(86, 6);
this.TxtProcessName.Name = "TxtProcessName";
this.TxtProcessName.Size = new System.Drawing.Size(168, 23);
this.TxtProcessName.TabIndex = 7;
this.toolTip1.SetToolTip(this.TxtProcessName, "应用将通过该名称来查找窗口");
//
// TxtStartupPath
//
this.TxtStartupPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.TxtStartupPath.Location = new System.Drawing.Point(86, 35);
this.TxtStartupPath.Name = "TxtStartupPath";
this.TxtStartupPath.Size = new System.Drawing.Size(354, 23);
this.TxtStartupPath.TabIndex = 7;
this.toolTip1.SetToolTip(this.TxtStartupPath, "应用将通过该路径来启动程序");
//
// TxtHotKey
//
this.TxtHotKey.BackColor = System.Drawing.Color.White;
this.TxtHotKey.Location = new System.Drawing.Point(86, 64);
this.TxtHotKey.Name = "TxtHotKey";
this.TxtHotKey.ReadOnly = true;
this.TxtHotKey.Size = new System.Drawing.Size(120, 23);
this.TxtHotKey.TabIndex = 7;
this.TxtHotKey.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.toolTip1.SetToolTip(this.TxtHotKey, "应用将通过该热键来触发控制");
this.TxtHotKey.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TxtHotKey_KeyDown);
//
// BtnSelectProcess
//
this.BtnSelectProcess.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.BtnSelectProcess.Location = new System.Drawing.Point(260, 6);
this.BtnSelectProcess.Name = "BtnSelectProcess";
this.BtnSelectProcess.Size = new System.Drawing.Size(30, 23);
this.BtnSelectProcess.TabIndex = 8;
this.BtnSelectProcess.Text = "...";
this.toolTip1.SetToolTip(this.BtnSelectProcess, "选择进程获取信息");
this.BtnSelectProcess.UseVisualStyleBackColor = true;
this.BtnSelectProcess.Click += new System.EventHandler(this.BtnSelectProcess_Click);
//
// BtnSelectStartupPath
//
this.BtnSelectStartupPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.BtnSelectStartupPath.Location = new System.Drawing.Point(446, 35);
this.BtnSelectStartupPath.Name = "BtnSelectStartupPath";
this.BtnSelectStartupPath.Size = new System.Drawing.Size(30, 23);
this.BtnSelectStartupPath.TabIndex = 9;
this.BtnSelectStartupPath.Text = "...";
this.toolTip1.SetToolTip(this.BtnSelectStartupPath, "手动选择启动文件路径");
this.BtnSelectStartupPath.UseVisualStyleBackColor = true;
this.BtnSelectStartupPath.Click += new System.EventHandler(this.BtnSelectStartupPath_Click);
//
// FormHotKey
//
this.AcceptButton = this.BtnAccept;
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.BtnCancel;
this.ClientSize = new System.Drawing.Size(488, 99);
this.Controls.Add(this.BtnSelectStartupPath);
this.Controls.Add(this.BtnSelectProcess);
this.Controls.Add(this.TxtHotKey);
this.Controls.Add(this.TxtStartupPath);
this.Controls.Add(this.TxtProcessName);
this.Controls.Add(this.label2);
this.Controls.Add(this.label3);
this.Controls.Add(this.label1);
this.Controls.Add(this.BtnCancel);
this.Controls.Add(this.BtnAccept);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FormHotKey";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "热键设置";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button BtnAccept;
private System.Windows.Forms.Button BtnCancel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox TxtProcessName;
private System.Windows.Forms.TextBox TxtStartupPath;
private System.Windows.Forms.TextBox TxtHotKey;
private System.Windows.Forms.Button BtnSelectProcess;
private System.Windows.Forms.Button BtnSelectStartupPath;
private System.Windows.Forms.ToolTip toolTip1;
}
}

62
KeyGo/FormHotKey.cs Normal file
View File

@ -0,0 +1,62 @@
using System;
using System.Windows.Forms;
namespace KeyGo
{
public partial class FormHotKey : Form
{
public FormHotKey()
{
InitializeComponent();
}
private void BtnAccept_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
private void TxtHotKey_KeyDown(object sender, KeyEventArgs e)
{
if (e.Modifiers == Keys.None)
return;
if (e.KeyCode == Keys.ControlKey || e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.Menu)
return;
string text = e.KeyCode.ToString();
if (e.Shift)
text = "Shift+" + text;
if (e.Alt)
text = "Alt+" + text;
if (e.Control)
text = "Ctrl+" + text;
TxtHotKey.Text = text;
}
private void BtnSelectProcess_Click(object sender, EventArgs e)
{
var frm = new FormProcessSelector();
if (frm.ShowDialog() == DialogResult.OK)
{
var p = frm.SelectedItem;
TxtProcessName.Text = p.ProcessName;
TxtStartupPath.Text = p.MainModule.FileName;
}
}
private void BtnSelectStartupPath_Click(object sender, EventArgs e)
{
var frm = new OpenFileDialog()
{
Title = "请选择启动应用",
Filter = "Exe file (*.exe)|*.exe|All file (*.*)|*.*",
RestoreDirectory = true,
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
};
if (frm.ShowDialog() == DialogResult.OK)
{
TxtStartupPath.Text = frm.FileName;
}
}
}
}

123
KeyGo/FormHotKey.resx Normal file
View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -29,41 +29,41 @@ namespace KeyGo
/// </summary>
private void InitializeComponent()
{
this.TxtHotKey1 = new System.Windows.Forms.TextBox();
this.BtnTest = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// TxtHotKey1
// BtnTest
//
this.TxtHotKey1.BackColor = System.Drawing.Color.White;
this.TxtHotKey1.Location = new System.Drawing.Point(96, 122);
this.TxtHotKey1.Name = "TxtHotKey1";
this.TxtHotKey1.ReadOnly = true;
this.TxtHotKey1.Size = new System.Drawing.Size(213, 23);
this.TxtHotKey1.TabIndex = 0;
this.TxtHotKey1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.TxtHotKey1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TxtHotKey1_KeyDown);
this.BtnTest.Location = new System.Drawing.Point(155, 162);
this.BtnTest.Name = "BtnTest";
this.BtnTest.Size = new System.Drawing.Size(193, 66);
this.BtnTest.TabIndex = 0;
this.BtnTest.Text = "Test";
this.BtnTest.UseVisualStyleBackColor = true;
this.BtnTest.Click += new System.EventHandler(this.button1_Click);
//
// FormMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(482, 315);
this.Controls.Add(this.TxtHotKey1);
this.ClientSize = new System.Drawing.Size(564, 390);
this.Controls.Add(this.BtnTest);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "FormMain";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "KeyGo!";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormMain_FormClosed);
this.Load += new System.EventHandler(this.FormMain_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox TxtHotKey1;
private System.Windows.Forms.Button BtnTest;
}
}

View File

@ -2,60 +2,82 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace KeyGo
{
public partial class FormMain : Form
{
static readonly string _DataFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeyGo", "HotKey.xml");
readonly KeyGo _KeyGo;
public FormMain()
{
InitializeComponent();
_KeyGo = LoadHotKeyItems(_DataFilePath);
_KeyGo.FormHandle = Handle;
_KeyGo.RegAllKey();
}
void ProcessHotkey(int hotKey_id)
{
//if (hotKey_id == 100)
// MessageBox.Show("Test");
}
private void TxtHotKey1_KeyDown(object sender, KeyEventArgs e)
{
TxtHotKey1.Text = e.Modifiers.ToString();
Console.WriteLine($"down\t{e.KeyData}");
}
private void FormMain_Load(object sender, EventArgs e)
{
//AppHotKey.RegKey(Handle, 100, AppHotKey.KeyModifiers.Ctrl, Keys.W);
}
#region IO
private KeyGo LoadHotKeyItems(string xmlFilePath)
{
try
{
return KeyGo.LoadXml(xmlFilePath);
}
catch (Exception ex)
{
MessageBox.Show("载入数据文件异常:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return new KeyGo();
}
private void SaveHotKeyItems(KeyGo data)
{
try
{
data.SaveXml(_DataFilePath);
}
catch (Exception ex)
{
MessageBox.Show("保存数据文件异常:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
{
//AppHotKey.UnRegKey(Handle, 100);
_KeyGo.UnRegAllKey();
}
#region
private const int WM_HOTKEY = 0x312;
protected override void WndProc(ref Message m)
@ -64,10 +86,27 @@ namespace KeyGo
switch (m.Msg)
{
case WM_HOTKEY:
ProcessHotkey(m.WParam.ToInt32());
_KeyGo.ProcessHotkey(m.WParam.ToInt32());
break;
}
}
#endregion
private void button1_Click(object sender, EventArgs e)
{
//_KeyGo.Items.Add(new HotKeyItem
//{
// ProcessName = "QQ",
// StartupPath = "",
// HotKey = "Ctrl+Q",
// Enabled = true,
// TriggerCounter = 0,
// CreationTime = DateTime.Now,
// LastModifiedTime = DateTime.Now,
//});
//SaveHotKeyItems(_KeyGo);
//new FormHotKey().ShowDialog();
}
}
}

127
KeyGo/FormProcessSelector.Designer.cs generated Normal file
View File

@ -0,0 +1,127 @@

namespace KeyGo
{
partial class FormProcessSelector
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.BtnCancel = new System.Windows.Forms.Button();
this.BtnAccept = new System.Windows.Forms.Button();
this.BtnRefresh = new System.Windows.Forms.Button();
this.CmbProcesses = new System.Windows.Forms.ComboBox();
this.LblInfo = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// BtnCancel
//
this.BtnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.BtnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.BtnCancel.Location = new System.Drawing.Point(397, 44);
this.BtnCancel.Name = "BtnCancel";
this.BtnCancel.Size = new System.Drawing.Size(75, 23);
this.BtnCancel.TabIndex = 5;
this.BtnCancel.Text = "取消";
this.BtnCancel.UseVisualStyleBackColor = true;
//
// BtnAccept
//
this.BtnAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.BtnAccept.Location = new System.Drawing.Point(316, 44);
this.BtnAccept.Name = "BtnAccept";
this.BtnAccept.Size = new System.Drawing.Size(75, 23);
this.BtnAccept.TabIndex = 4;
this.BtnAccept.Text = "确定";
this.BtnAccept.UseVisualStyleBackColor = true;
this.BtnAccept.Click += new System.EventHandler(this.BtnAccept_Click);
//
// BtnRefresh
//
this.BtnRefresh.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.BtnRefresh.Location = new System.Drawing.Point(397, 12);
this.BtnRefresh.Name = "BtnRefresh";
this.BtnRefresh.Size = new System.Drawing.Size(75, 23);
this.BtnRefresh.TabIndex = 7;
this.BtnRefresh.Text = "刷新";
this.BtnRefresh.UseVisualStyleBackColor = true;
this.BtnRefresh.Click += new System.EventHandler(this.BtnRefresh_Click);
//
// CmbProcesses
//
this.CmbProcesses.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CmbProcesses.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.CmbProcesses.FormattingEnabled = true;
this.CmbProcesses.Location = new System.Drawing.Point(12, 12);
this.CmbProcesses.Name = "CmbProcesses";
this.CmbProcesses.Size = new System.Drawing.Size(379, 25);
this.CmbProcesses.TabIndex = 6;
//
// LblInfo
//
this.LblInfo.AutoSize = true;
this.LblInfo.Location = new System.Drawing.Point(9, 47);
this.LblInfo.Name = "LblInfo";
this.LblInfo.Size = new System.Drawing.Size(0, 17);
this.LblInfo.TabIndex = 8;
//
// FormProcessSelector
//
this.AcceptButton = this.BtnAccept;
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.BtnCancel;
this.ClientSize = new System.Drawing.Size(484, 79);
this.Controls.Add(this.LblInfo);
this.Controls.Add(this.BtnRefresh);
this.Controls.Add(this.CmbProcesses);
this.Controls.Add(this.BtnCancel);
this.Controls.Add(this.BtnAccept);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FormProcessSelector";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "请选择进程";
this.Load += new System.EventHandler(this.FormProcessSelector_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button BtnCancel;
private System.Windows.Forms.Button BtnAccept;
private System.Windows.Forms.Button BtnRefresh;
private System.Windows.Forms.ComboBox CmbProcesses;
private System.Windows.Forms.Label LblInfo;
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
namespace KeyGo
{
public partial class FormProcessSelector : Form
{
public FormProcessSelector()
{
InitializeComponent();
}
public Process SelectedItem { get; private set; }
private void FormProcessSelector_Load(object sender, EventArgs e)
{
LoadProcessesInfo();
}
private void BtnRefresh_Click(object sender, EventArgs e)
{
LoadProcessesInfo();
}
private class VOProcess
{
public string Text { get; set; }
public Process Process { get; set; }
}
private void LoadProcessesInfo()
{
var processes = Process.GetProcesses().Where(p => p.MainWindowHandle != IntPtr.Zero);
CmbProcesses.BeginUpdate();
CmbProcesses.DataSource = processes.Select(p => new VOProcess { Text = $"{p.ProcessName} | {p.MainWindowTitle}", Process = p }).ToList();
CmbProcesses.DisplayMember = "Text";
CmbProcesses.EndUpdate();
}
private void BtnAccept_Click(object sender, EventArgs e)
{
if (CmbProcesses.SelectedItem is VOProcess p)
{
SelectedItem = p.Process;
DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show("未选择进程", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

77
KeyGo/HotKeyItem.cs Normal file
View File

@ -0,0 +1,77 @@
using System;
using System.Xml.Serialization;
namespace KeyGo
{
/// <summary>
/// 热键项
/// </summary>
public class HotKeyItem
{
/// <summary>
/// Gets or sets the hot key identifier.
/// </summary>
/// <value>
/// The hot key identifier.
/// </value>
[XmlIgnore]
public int HotKeyID { get; set; }
/// <summary>
/// Gets or sets the name of the process.
/// </summary>
/// <value>
/// The name of the process.
/// </value>
public string ProcessName { get; set; }
/// <summary>
/// Gets or sets the startup path.
/// </summary>
/// <value>
/// The startup path.
/// </value>
public string StartupPath { get; set; }
/// <summary>
/// Gets or sets the hot key.
/// 组合键之间使用+隔开,例如:"Ctrl+Shift+W"
/// </summary>
/// <value>
/// The hot key.
/// </value>
public string HotKey { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="HotKeyItem"/> is enabled.
/// </summary>
/// <value>
/// <c>true</c> if enabled; otherwise, <c>false</c>.
/// </value>
public bool Enabled { get; set; }
/// <summary>
/// Gets or sets the trigger counter.
/// </summary>
/// <value>
/// The trigger counter.
/// </value>
public int TriggerCounter { get; set; }
/// <summary>
/// Gets or sets the creation time.
/// </summary>
/// <value>
/// The creation time.
/// </value>
public DateTime CreationTime { get; set; }
/// <summary>
/// Gets or sets the last modified time.
/// </summary>
/// <value>
/// The last modified time.
/// </value>
public DateTime LastModifiedTime { get; set; }
}
}

199
KeyGo/KeyGo.cs Normal file
View File

@ -0,0 +1,199 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace KeyGo
{
public class KeyGo
{
static int _RegMaxID;
[XmlIgnore]
public IntPtr FormHandle { get; set; }
public List<HotKeyItem> Items { get; set; } = new List<HotKeyItem>();
#region FILE IO
/// <summary>
/// Loads the XML.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns></returns>
public static KeyGo LoadXml(string filePath)
{
KeyGo data = null;
if (File.Exists(filePath))
{
XmlSerializer formatter = new XmlSerializer(typeof(KeyGo));
using (var stream = File.OpenRead(filePath))
{
if (stream.Length > 0)
{
data = formatter.Deserialize(stream) as KeyGo;
}
}
}
return data;
}
/// <summary>
/// Saves the XML.
/// </summary>
/// <param name="filePath">The file path.</param>
public void SaveXml(string filePath)
{
if (!File.Exists(filePath))
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
XmlSerializer formatter = new XmlSerializer(typeof(KeyGo));
using (var stream = File.Create(filePath))
{
formatter.Serialize(stream, this);
}
}
#endregion
/// <summary>
/// Processes the hotkey.
/// </summary>
/// <param name="hotKey_id">The hot key identifier.</param>
public void ProcessHotkey(int hotKey_id)
{
var hotkey = Items.Find(k => k.HotKeyID == hotKey_id);
if (hotkey != null)
{
++hotkey.TriggerCounter;
MessageBox.Show($"ID:{hotkey.HotKeyID}\nKeys:{hotkey.HotKey}\nProcessName:{hotkey.ProcessName}\nStartupPath:{hotkey.StartupPath}", "HotKey", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
#region HotKey Register
/// <summary>
/// Regs all key.
/// </summary>
public void RegAllKey()
{
foreach (var item in Items)
{
if (!item.Enabled)
continue;
try
{
RegKey(item);
}
catch (Exception)
{
// 忽视异常外部通过ID是否被设置判断执行结果
}
}
}
/// <summary>
/// Uns the reg all key.
/// </summary>
public void UnRegAllKey()
{
foreach (var item in Items)
{
try
{
UnRegKey(item);
}
catch (Exception)
{
// 忽视异常外部通过ID是否被设置判断执行结果
}
}
}
/// <summary>
/// 注册热键 - 成功后,会设置 HotKeyID
/// </summary>
/// <param name="item">The item.</param>
/// <exception cref="ArgumentNullException">
/// item
/// or
/// HotKey - 热键不能为空!
/// </exception>
/// <exception cref="InvalidOperationException">
/// 功能键不能为空!
/// or
/// 快捷键不能为空!
/// </exception>
public void RegKey(HotKeyItem item)
{
if (item is null)
throw new ArgumentNullException(nameof(item));
if (string.IsNullOrWhiteSpace(item.HotKey))
throw new ArgumentNullException(nameof(item.HotKey), "热键不能为空!");
// 如果注册过该热键ID不为0。卸载热键会将ID置零。
if (item.HotKeyID != 0)
return;
int id = Interlocked.Increment(ref _RegMaxID);
var keys = item.HotKey.Split('+');
Keys keyCode = Keys.None;
AppHotKey.KeyModifiers keyModifiers = AppHotKey.KeyModifiers.None;
foreach (var key in keys)
{
switch (key.ToLower())
{
case "ctrl":
keyModifiers |= AppHotKey.KeyModifiers.Ctrl;
break;
case "shift":
keyModifiers |= AppHotKey.KeyModifiers.Shift;
break;
case "alt":
keyModifiers |= AppHotKey.KeyModifiers.Alt;
break;
case "win":
keyModifiers |= AppHotKey.KeyModifiers.WindowsKey;
break;
default:
keyCode = (Keys)Enum.Parse(typeof(Keys), key);
break;
}
}
if (keyModifiers == AppHotKey.KeyModifiers.None)
throw new InvalidOperationException("功能键不能为空!");
if (keyCode == Keys.None)
throw new InvalidOperationException("快捷键不能为空!");
AppHotKey.RegKey(FormHandle, id, keyModifiers, keyCode);
item.HotKeyID = id;
}
/// <summary>
/// 注销热键 - 完成后,会清零 HotKeyID
/// </summary>
/// <param name="item">The item.</param>
/// <exception cref="ArgumentNullException">item</exception>
public void UnRegKey(HotKeyItem item)
{
if (item is null)
throw new ArgumentNullException(nameof(item));
if (item.HotKeyID == 0)
return;
AppHotKey.UnRegKey(FormHandle, item.HotKeyID);
item.HotKeyID = 0;
}
#endregion
}
}

View File

@ -46,18 +46,39 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AppControl.cs" />
<Compile Include="AppHotKey.cs" />
<Compile Include="FormHotKey.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FormHotKey.Designer.cs">
<DependentUpon>FormHotKey.cs</DependentUpon>
</Compile>
<Compile Include="FormMain.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FormMain.Designer.cs">
<DependentUpon>FormMain.cs</DependentUpon>
</Compile>
<Compile Include="FormProcessSelector.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FormProcessSelector.Designer.cs">
<DependentUpon>FormProcessSelector.cs</DependentUpon>
</Compile>
<Compile Include="KeyGo.cs" />
<Compile Include="HotKeyItem.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="FormHotKey.resx">
<DependentUpon>FormHotKey.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FormMain.resx">
<DependentUpon>FormMain.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FormProcessSelector.resx">
<DependentUpon>FormProcessSelector.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
@ -80,5 +101,8 @@
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,16 +1,15 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("KeyGo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyDescription("通过注册热键 启动/切换到/最小化 预设应用的小工具")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KeyGo")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyCopyright("Copyright © 2021 jie65535")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]