/**
* Grasscutter Tools
* Copyright (C) 2023 jie65535
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
**/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
namespace GrasscutterTools.Utils
{
///
/// KeyGo 核心功能类
///
internal class KeyGo
{
public KeyGo(IntPtr formHandle)
{
FormHandle = formHandle;
}
#region Member
private static int _regMaxId;
private readonly IntPtr FormHandle;
private bool _isEnabled;
public List Items { get; set; } = new();
///
/// 全局热键是否启用
///
public bool IsEnabled
{
get => _isEnabled;
set
{
_isEnabled = value;
if (value) RegAllKey();
else UnRegAllKey();
}
}
#endregion Member
#region HotKey Register
///
/// 注册所有启用的快捷键
///
public void RegAllKey()
{
if (!_isEnabled) return;
foreach (var item in Items.Where(item => item.IsEnabled))
{
try
{
RegKey(item);
}
catch (Exception)
{
// 忽视异常,外部通过ID是否被设置判断执行结果
}
}
}
///
/// 取消所有快捷键
///
public void UnRegAllKey()
{
foreach (var item in Items)
{
try
{
UnRegKey(item);
}
catch (Exception)
{
// 忽视异常,外部通过ID是否被设置判断执行结果
}
}
}
///
/// 注册热键 - 成功后,会设置 HotKeyId
///
/// The item.
///
/// item
/// or
/// HotKey - 热键不能为空!
///
///
/// 功能键不能为空!
/// or
/// 快捷键不能为空!
///
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;
var id = Interlocked.Increment(ref _regMaxId);
var keys = item.HotKey.Split('+');
var keyCode = Keys.None;
var keyModifiers = AppHotKey.KeyModifiers.None;
foreach (var key in keys)
{
switch (key.Trim().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;
}
///
/// 注销热键 - 完成后,会清零 HotKeyId
///
/// The item.
/// item
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 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.
///
/// The hot key identifier.
public void ProcessHotKey(int hotKeyId)
{
var hotKey = Items.Find(k => k.HotKeyId == hotKeyId);
if (hotKey != null)
{
//Console.WriteLine($"ID:{hotKey.HotKeyId} Keys:{hotKey.HotKey} ProcessName:{hotKey.ProcessName}\nStartupPath:{hotKey.StartupPath}");
//++hotKey.TriggerCounter;
// 触发事件,若被外部处理,则内部不再执行
OnHotKeyTrigger(hotKey);
}
}
#endregion HotKey Trigger
#region HotKey Manager
///
/// 添加一个新热键
///
/// The item.
///
/// item
/// or
/// HotKey - 热键不能为空!
///
///
/// 功能键不能为空!
/// or
/// 快捷键不能为空!
///
public void AddHotKey(HotKeyItem item)
{
if (item is null)
throw new ArgumentNullException(nameof(item));
if (_isEnabled && item.IsEnabled)
RegKey(item);
Items.Add(item);
}
///
/// 删除一个热键
///
/// The item.
public void DelHotKey(HotKeyItem item)
{
if (item is null)
throw new ArgumentNullException(nameof(item));
if (item.HotKeyId != 0)
UnRegKey(item);
Items.Remove(item);
}
///
/// 修改热键
///
/// The item.
public void ChangeHotKey(HotKeyItem item)
{
if (item is null)
throw new ArgumentNullException(nameof(item));
// 重新注册
if (item.HotKeyId != 0)
UnRegKey(item);
if (_isEnabled && item.IsEnabled)
RegKey(item);
}
#endregion HotKey Manager
}
///
/// 热键触发事件参数
///
internal class HotKeyTriggerEventArgs
{
public HotKeyItem HotKeyItem { get; set; }
///
/// 获取或设置该事件是否已经被处理
///
///
/// true if handle; otherwise, false.
///
public bool Handle { get; set; }
}
}