mirror of
https://github.com/jie65535/KeyGo.git
synced 2025-06-02 17:39:13 +08:00
1. 增加 窗口控制帮助类
2. 增加 热键编辑窗体 3. 增加 进程选择窗体 4. 增加 KeyGo核心功能类 5. 实现 热键信息到XML文件IO 6. 实现 热键注册与注销相关操作
This commit is contained in:
parent
da0a4032b9
commit
723a9f16f5
143
KeyGo/AppControl.cs
Normal file
143
KeyGo/AppControl.cs
Normal 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);
|
||||
}
|
||||
}
|
@ -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
196
KeyGo/FormHotKey.Designer.cs
generated
Normal 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
62
KeyGo/FormHotKey.cs
Normal 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
123
KeyGo/FormHotKey.resx
Normal 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>
|
28
KeyGo/FormMain.Designer.cs
generated
28
KeyGo/FormMain.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
127
KeyGo/FormProcessSelector.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
56
KeyGo/FormProcessSelector.cs
Normal file
56
KeyGo/FormProcessSelector.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
120
KeyGo/FormProcessSelector.resx
Normal file
120
KeyGo/FormProcessSelector.resx
Normal 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
77
KeyGo/HotKeyItem.cs
Normal 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
199
KeyGo/KeyGo.cs
Normal 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
|
||||
}
|
||||
}
|
@ -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>
|
@ -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("")]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user