diff --git a/KeyGo/AppConfig.cs b/KeyGo/AppConfig.cs
new file mode 100644
index 0000000..47b6273
--- /dev/null
+++ b/KeyGo/AppConfig.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace KeyGo
+{
+ ///
+ /// 应用配置帮助类
+ ///
+ public class AppConfig
+ {
+ ///
+ /// Gets or sets a value indicating whether [power boot].
+ ///
+ ///
+ /// true if [power boot]; otherwise, false.
+ ///
+ public bool PowerBoot { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether [close to hide].
+ ///
+ ///
+ /// true if [close to hide]; otherwise, false.
+ ///
+ public bool CloseToHide { get; set; } = true;
+
+
+ ///
+ /// Loads the XML.
+ ///
+ /// The file path.
+ ///
+ public static AppConfig LoadXml(string filePath)
+ {
+ AppConfig data = null;
+ if (File.Exists(filePath))
+ {
+ XmlSerializer formatter = new XmlSerializer(typeof(AppConfig));
+ using (var stream = File.OpenRead(filePath))
+ {
+ if (stream.Length > 0)
+ {
+ data = formatter.Deserialize(stream) as AppConfig;
+ }
+ }
+ }
+ return data;
+ }
+
+ ///
+ /// Saves the XML.
+ ///
+ /// The file path.
+ public void SaveXml(string filePath)
+ {
+ if (!File.Exists(filePath))
+ Directory.CreateDirectory(Path.GetDirectoryName(filePath));
+
+ XmlSerializer formatter = new XmlSerializer(typeof(AppConfig));
+ using (var stream = File.Create(filePath))
+ {
+ formatter.Serialize(stream, this);
+ }
+ }
+ }
+}
diff --git a/KeyGo/AppControl.cs b/KeyGo/AppControl.cs
index 90fa6bd..808758f 100644
--- a/KeyGo/AppControl.cs
+++ b/KeyGo/AppControl.cs
@@ -41,7 +41,7 @@ namespace KeyGo
if (instance != null && instance.MainWindowHandle != IntPtr.Zero)
{
if (IsIconic(instance.MainWindowHandle))
- ShowWindowAsync(instance.MainWindowHandle, (int)CmdShow.Restore);
+ ShowWindow(instance.MainWindowHandle, (int)CmdShow.Restore);
SetForegroundWindow(instance.MainWindowHandle);
}
}
@@ -53,9 +53,16 @@ namespace KeyGo
public static void MinimizeWindow(Process instance)
{
if (instance != null && instance.MainWindowHandle != IntPtr.Zero)
- ShowWindowAsync(instance.MainWindowHandle, (int)CmdShow.Minimize);
+ ShowWindow(instance.MainWindowHandle, (int)CmdShow.Minimize);
}
+ ///
+ /// Determines whether [is foreground window] [the specified instance].
+ ///
+ /// The instance.
+ ///
+ /// true if [is foreground window] [the specified instance]; otherwise, false.
+ ///
public static bool IsForegroundWindow(Process instance)
{
return GetForegroundWindow() == instance.MainWindowHandle;
@@ -143,10 +150,12 @@ namespace KeyGo
}
[DllImport("User32.dll")]
- private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
+ private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
+ [DllImport("User32.dll")]
+ private static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
- private static extern bool SetForegroundWindow(System.IntPtr hWnd);
+ private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll")]
private static extern IntPtr GetForegroundWindow();
diff --git a/KeyGo/FormMain.Designer.cs b/KeyGo/FormMain.Designer.cs
index 5a7b62f..7bf56a0 100644
--- a/KeyGo/FormMain.Designer.cs
+++ b/KeyGo/FormMain.Designer.cs
@@ -35,9 +35,9 @@ namespace KeyGo
this.BtnAdd = new System.Windows.Forms.Button();
this.NotifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.TSMICloseToHide = new System.Windows.Forms.ToolStripMenuItem();
+ this.TSMIPowerBoot = new System.Windows.Forms.ToolStripMenuItem();
this.TSMIExit = new System.Windows.Forms.ToolStripMenuItem();
- this.TSMIPowerOnStartup = new System.Windows.Forms.ToolStripMenuItem();
- this.TSMICloseToMin = new System.Windows.Forms.ToolStripMenuItem();
this.FLPHotKeys.SuspendLayout();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
@@ -75,35 +75,35 @@ namespace KeyGo
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.TSMICloseToMin,
- this.TSMIPowerOnStartup,
+ this.TSMICloseToHide,
+ this.TSMIPowerBoot,
this.TSMIExit});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70);
//
+ // TSMICloseToHide
+ //
+ this.TSMICloseToHide.CheckOnClick = true;
+ this.TSMICloseToHide.Name = "TSMICloseToHide";
+ this.TSMICloseToHide.Size = new System.Drawing.Size(148, 22);
+ this.TSMICloseToHide.Text = "关闭为最小化";
+ this.TSMICloseToHide.CheckedChanged += new System.EventHandler(this.TSMICloseToHide_CheckedChanged);
+ //
+ // TSMIPowerBoot
+ //
+ this.TSMIPowerBoot.CheckOnClick = true;
+ this.TSMIPowerBoot.Name = "TSMIPowerBoot";
+ this.TSMIPowerBoot.Size = new System.Drawing.Size(148, 22);
+ this.TSMIPowerBoot.Text = "开机自启动";
+ this.TSMIPowerBoot.CheckedChanged += new System.EventHandler(this.TSMIPowerBoot_CheckedChanged);
+ //
// TSMIExit
//
this.TSMIExit.Name = "TSMIExit";
- this.TSMIExit.Size = new System.Drawing.Size(180, 22);
+ this.TSMIExit.Size = new System.Drawing.Size(148, 22);
this.TSMIExit.Text = "退出";
this.TSMIExit.Click += new System.EventHandler(this.TSMIExit_Click);
//
- // TSMIPowerOnStartup
- //
- this.TSMIPowerOnStartup.CheckOnClick = true;
- this.TSMIPowerOnStartup.Name = "TSMIPowerOnStartup";
- this.TSMIPowerOnStartup.Size = new System.Drawing.Size(180, 22);
- this.TSMIPowerOnStartup.Text = "开机自启动";
- this.TSMIPowerOnStartup.CheckedChanged += new System.EventHandler(this.TSMIPowerOnStartup_CheckedChanged);
- //
- // TSMICloseToMin
- //
- this.TSMICloseToMin.CheckOnClick = true;
- this.TSMICloseToMin.Name = "TSMICloseToMin";
- this.TSMICloseToMin.Size = new System.Drawing.Size(180, 22);
- this.TSMICloseToMin.Text = "关闭为最小化";
- this.TSMICloseToMin.CheckedChanged += new System.EventHandler(this.TSMICloseToMin_CheckedChanged);
- //
// FormMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
@@ -135,8 +135,8 @@ namespace KeyGo
private System.Windows.Forms.NotifyIcon NotifyIcon;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem TSMIExit;
- private System.Windows.Forms.ToolStripMenuItem TSMIPowerOnStartup;
- private System.Windows.Forms.ToolStripMenuItem TSMICloseToMin;
+ private System.Windows.Forms.ToolStripMenuItem TSMIPowerBoot;
+ private System.Windows.Forms.ToolStripMenuItem TSMICloseToHide;
}
}
diff --git a/KeyGo/FormMain.cs b/KeyGo/FormMain.cs
index 9bdac8a..6bd7218 100644
--- a/KeyGo/FormMain.cs
+++ b/KeyGo/FormMain.cs
@@ -8,35 +8,73 @@ namespace KeyGo
{
public partial class FormMain : Form
{
- private static readonly string _DataFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeyGo", "HotKey.xml");
+ #region 成员
+
+ private static readonly string _DataFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeyGo");
+ private static readonly string _DataFilePath = Path.Combine(_DataFolderPath, "HotKey.xml");
+ private static readonly string _AppConfigFilePath = Path.Combine(_DataFolderPath, "AppConfig.xml");
private readonly KeyGo _KeyGo;
+ private readonly AppConfig _AppConfig;
+ private readonly string _CurrentProcessName;
+ private bool _Initializing;
+
+ #endregion 成员
+
+ #region 构造
public FormMain()
{
InitializeComponent();
+ _Initializing = true;
+ // 读取程序集版本,显示到标题栏
Assembly assembly = Assembly.GetExecutingAssembly();
AssemblyName thisAssemName = assembly.GetName();
- Text += $" - {thisAssemName.Version}";
+ Text += $" - {thisAssemName.Version} - github.com/jie65535/KeyGo";
+ // 载入并初始化配置
+ _AppConfig = LoadAppConfig(_AppConfigFilePath);
+ TSMICloseToHide.Checked = _AppConfig.CloseToHide;
+ TSMIPowerBoot.Checked = _AppConfig.PowerBoot;
+ SetPowerBoot(_AppConfig.PowerBoot);
+
+ // 载入热键数据
_KeyGo = LoadHotKeyItems(_DataFilePath);
+ _KeyGo.HotKeyTriggerEvent += KeyGo_HotKeyTriggerEvent;
_KeyGo.FormHandle = Handle;
var p = Process.GetCurrentProcess();
+ _CurrentProcessName = p.ProcessName;
if (_KeyGo.Items.Count == 0)
{
_KeyGo.Items.Add(new HotKeyItem
{
- ProcessName = p.ProcessName,
+ ProcessName = _CurrentProcessName,
StartupPath = p.MainModule.FileName,
HotKey = "Ctrl+G",
});
}
_KeyGo.RegAllKey();
+ // 初始化UI
FLPHotKeys.SuspendLayout();
foreach (var item in _KeyGo.Items)
FLP_AddItem(item);
FLPHotKeys.ResumeLayout();
+
+ _Initializing = false;
+ }
+
+ #endregion 构造
+
+ #region 窗体事件
+
+ private void KeyGo_HotKeyTriggerEvent(object sender, HotKeyTriggerEventArgs e)
+ {
+ if (e.HotKeyItem.ProcessName == _CurrentProcessName)
+ {
+ ChangeVisible();
+ e.Handle = true;
+ }
}
private void FormMain_Load(object sender, EventArgs e)
@@ -44,22 +82,32 @@ namespace KeyGo
Console.WriteLine(_DataFilePath);
}
- bool isExit;
+ private bool isExit;
+
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
- if (!isExit)
+ if (!isExit && _AppConfig.CloseToHide)
{
Hide();
e.Cancel = true;
}
}
+ private void FormMain_Deactivate(object sender, EventArgs e)
+ {
+ // 如果最小化,则隐藏窗体
+ if (WindowState == FormWindowState.Minimized)
+ Hide();
+ }
+
private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
{
_KeyGo.UnRegAllKey();
SaveHotKeyItems(_KeyGo);
}
+ #endregion 窗体事件
+
#region 数据文件IO
private KeyGo LoadHotKeyItems(string xmlFilePath)
@@ -90,6 +138,36 @@ namespace KeyGo
#endregion 数据文件IO
+ #region 配置文件IO
+
+ private AppConfig LoadAppConfig(string xmlFilePath)
+ {
+ AppConfig instance = null;
+ try
+ {
+ instance = AppConfig.LoadXml(xmlFilePath);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("载入配置文件异常:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ return instance ?? new AppConfig();
+ }
+
+ private void SaveAppConfig(AppConfig config)
+ {
+ try
+ {
+ config.SaveXml(_AppConfigFilePath);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("保存配置文件异常:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ #endregion 配置文件IO
+
#region 窗体消息 热键回调
private const int WM_HOTKEY = 0x312;
@@ -107,21 +185,7 @@ namespace KeyGo
#endregion 窗体消息 热键回调
- private void BtnTest_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();
- }
+ #region 热键管理
private void BtnAdd_Click(object sender, EventArgs e)
{
@@ -162,12 +226,21 @@ namespace KeyGo
FLPHotKeys.Controls.SetChildIndex(BtnAdd, i1);
}
+ #endregion 热键管理
+
+ #region 托盘图标管理
+
private void NotifyIcon_MouseClick(object sender, MouseEventArgs e)
{
// 鼠标左键点击托盘图标才触发
if (e.Button != MouseButtons.Left)
return;
+ ChangeVisible();
+ }
+
+ private void ChangeVisible()
+ {
// 当前在前台则隐藏
if (Visible)
{
@@ -192,27 +265,38 @@ namespace KeyGo
}
}
- private void FormMain_Deactivate(object sender, EventArgs e)
- {
- // 如果最小化,则隐藏窗体
- if (WindowState == FormWindowState.Minimized)
- Hide();
- }
-
private void TSMIExit_Click(object sender, EventArgs e)
{
isExit = true;
Close();
}
- private void TSMIPowerOnStartup_CheckedChanged(object sender, EventArgs e)
+ private void TSMIPowerBoot_CheckedChanged(object sender, EventArgs e)
{
- MessageBox.Show("暂未完成", "TODO");
+ if (_Initializing)
+ return;
+ _AppConfig.PowerBoot = TSMIPowerBoot.Checked;
+ SetPowerBoot(_AppConfig.PowerBoot);
+ SaveAppConfig(_AppConfig);
}
- private void TSMICloseToMin_CheckedChanged(object sender, EventArgs e)
+ private void TSMICloseToHide_CheckedChanged(object sender, EventArgs e)
{
- MessageBox.Show("暂未完成", "TODO");
+ if (_Initializing)
+ return;
+ _AppConfig.CloseToHide = TSMICloseToHide.Checked;
+ SaveAppConfig(_AppConfig);
+ }
+
+ #endregion 托盘图标管理
+
+ ///
+ /// 设置开机自启动
+ ///
+ /// if set to true [enable].
+ private void SetPowerBoot(bool enable)
+ {
+ // TODO
}
}
}
\ No newline at end of file
diff --git a/KeyGo/KeyGo.cs b/KeyGo/KeyGo.cs
index 33b842f..20ec5c7 100644
--- a/KeyGo/KeyGo.cs
+++ b/KeyGo/KeyGo.cs
@@ -9,15 +9,21 @@ using System.Xml.Serialization;
namespace KeyGo
{
+ ///
+ /// KeyGo 核心功能类
+ ///
public class KeyGo
{
- static int _RegMaxID;
+ #region Member
+
+ private static int _RegMaxID;
[XmlIgnore]
public IntPtr FormHandle { get; set; }
public List Items { get; set; } = new List();
+ #endregion Member
#region FILE IO
@@ -59,7 +65,7 @@ namespace KeyGo
}
}
- #endregion
+ #endregion FILE IO
#region HotKey Register
@@ -84,7 +90,6 @@ namespace KeyGo
}
}
-
///
/// Uns the reg all key.
///
@@ -140,15 +145,19 @@ namespace KeyGo
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;
@@ -180,7 +189,21 @@ namespace KeyGo
item.HotKeyID = 0;
}
- #endregion
+ #endregion HotKey Register
+
+ #region HotKey Trigger
+
+ ///
+ /// 热键触发时调用
+ ///
+ public event EventHandler HotKeyTriggerEvent;
+
+ private bool OnHotKeyTrigger(HotKeyItem item)
+ {
+ var args = new HotKeyTriggerEventArgs{ HotKeyItem = item };
+ HotKeyTriggerEvent?.Invoke(this, args);
+ return args.Handle;
+ }
///
/// Processes the hotkey.
@@ -191,32 +214,41 @@ namespace KeyGo
var hotkey = Items.Find(k => k.HotKeyID == hotKey_id);
if (hotkey != null)
{
+ //Console.WriteLine($"ID:{hotkey.HotKeyID} Keys:{hotkey.HotKey} ProcessName:{hotkey.ProcessName}\nStartupPath:{hotkey.StartupPath}");
++hotkey.TriggerCounter;
-
+ // 触发事件,若被外部处理,则内部不再执行
+ if (OnHotKeyTrigger(hotkey))
+ return;
// 热键相应逻辑:
// 若应用未启动:启动应用
// 若应用未在最前:激活窗体,推到最前
// 若应用已在最前:最小化窗体
- var process = Process.GetProcessesByName(hotkey.ProcessName).Where(p => p.MainWindowHandle != IntPtr.Zero).ToArray().FirstOrDefault();
- if (process != null )
- {
- if (AppControl.IsForegroundWindow(process))
- AppControl.MinimizeWindow(process);
- else
- AppControl.ShowWindow(process);
- }
- else
+ var processes = Process.GetProcessesByName(hotkey.ProcessName);
+ if (processes == null || processes.Length < 1)
{
if (!string.IsNullOrWhiteSpace(hotkey.StartupPath) && File.Exists(hotkey.StartupPath))
Process.Start(hotkey.StartupPath);
}
-
- Console.WriteLine($"ID:{hotkey.HotKeyID} Keys:{hotkey.HotKey} ProcessName:{hotkey.ProcessName}\nStartupPath:{hotkey.StartupPath}");
+ else
+ {
+ var process = processes.Where(p => p.MainWindowHandle != IntPtr.Zero).ToArray().FirstOrDefault();
+ if (process != null)
+ {
+ if (AppControl.IsForegroundWindow(process))
+ AppControl.MinimizeWindow(process);
+ else
+ AppControl.ShowWindow(process);
+ }
+ }
}
}
+ #endregion HotKey Trigger
+
+ #region HotKey Manager
+
///
/// 添加一个新热键
///
@@ -261,5 +293,23 @@ namespace KeyGo
if (item.Enabled)
RegKey(item);
}
+
+ #endregion HotKey Manager
+ }
+
+ ///
+ /// 热键触发事件参数
+ ///
+ public class HotKeyTriggerEventArgs
+ {
+ public HotKeyItem HotKeyItem { get; set; }
+
+ ///
+ /// 获取或设置该事件是否已经被处理
+ ///
+ ///
+ /// true if handle; otherwise, false.
+ ///
+ public bool Handle { get; set; }
}
}
\ No newline at end of file
diff --git a/KeyGo/KeyGo.csproj b/KeyGo/KeyGo.csproj
index 8369c6a..23997af 100644
--- a/KeyGo/KeyGo.csproj
+++ b/KeyGo/KeyGo.csproj
@@ -69,6 +69,7 @@
+
diff --git a/KeyGo/Program.cs b/KeyGo/Program.cs
index b742d01..d9687fc 100644
--- a/KeyGo/Program.cs
+++ b/KeyGo/Program.cs
@@ -14,7 +14,10 @@ namespace KeyGo
var p = AppControl.GetCurrentRunningInstance();
if (p != null)
{
- AppControl.ShowWindow(p);
+ if (p.MainWindowHandle == IntPtr.Zero)
+ MessageBox.Show("应用已启动,无需重复运行", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ else
+ AppControl.ShowWindow(p);
}
else
{
diff --git a/KeyGo/Properties/AssemblyInfo.cs b/KeyGo/Properties/AssemblyInfo.cs
index c9a1177..957e02b 100644
--- a/KeyGo/Properties/AssemblyInfo.cs
+++ b/KeyGo/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.1.0.3")]
+[assembly: AssemblyVersion("0.1.1")]
[assembly: AssemblyFileVersion("1.0.0.0")]