FastHotKeyForWPF 2.0.1
There is a newer version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package FastHotKeyForWPF --version 2.0.1
NuGet\Install-Package FastHotKeyForWPF -Version 2.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FastHotKeyForWPF" Version="2.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add FastHotKeyForWPF --version 2.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: FastHotKeyForWPF, 2.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install FastHotKeyForWPF as a Cake Addin #addin nuget:?package=FastHotKeyForWPF&version=2.0.1 // Install FastHotKeyForWPF as a Cake Tool #tool nuget:?package=FastHotKeyForWPF&version=2.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
FastHotKeyForWPF
Quickly build global hotkeys in WPF programs
Supported [ .NET6.0 ] [ .NET8.0 ]
更新进度
<details> <summary>Version 1.1.6 已上线 ( 使用 PrefabComponent 的最后一个版本 ) </summary>
(1)提供开箱即用的圆角组件
(2)默认不使用变色效果,需要用户自定义对应函数
(3)非DeBug模式下再无注册成功与否的提示,需要用户自定义对应函数
(4)新增一个保护名单,名单中的任何热键不允许被增删改,即便这个热键没有被注册过
(5)新增静态属性,用于获取注册信息和保护名单
</details>
<details> <summary>Version 1.2.3 已上线( 使用 非MVVM 的最后一个版本 ) </summary>
修复 HotKeysBox 在 手动设置热键 时,部分情况下文本显示异常的问题 (即手动设置初始热键后,文本显示None+None而不是初始设置的热键,但鼠标进入一下框体就恢复了正常)
优化了用户控件的圆角效果,新增ActualBackground可选项
</details>
<details> <summary>Version 2.0.0 已上线 ( 2.0.1 尝试支持 .NET6.0 )</summary>
变更
1.GlobalHotKey.Add() 返回( bool,int ) ⇒ 返回注册编号 int , -1表示失败的操作
2.GlobalHotKey.EditHotKey_Keys() ⇒ GlobalHotKey.EditKeys()
3.GlobalHotKey.EditHotKey_Function() ⇒ GlobalHotKey.EditHandler()
4.GlobalHotKey.DeleteByFunction() ⇒ GlobalHotKey.DeleteByHandler()
5.[delegate KeyInvoke_Void & delegate KeyInvoke_Return] ⇒ [ delegate HotKeyEventHandler & HotKeyEventArgs ]
6.[HotKeyBox & HotKeysBox] ⇒ [HotKeyBox]
新增
1.RegisterCollection[ModelKey,NormalKey] ⇒ RegisterInfo
2.RegisterCollection[HotKeyEventHandler] ⇒ List< RegisterInfo >
3.[接口]IAutoHotKeyProperty 约束 Model、View、ViewModel
4.[接口]IAutoHotKeyUpdate 约束 ViewModel
5.[抽象基类]HotKeyModelBase 快速实现用于热键注册的UserControl的Model
6.[抽象基类]HotKeyViewModelBase 快速实现用于热键注册的UserControl的ViewModel
相比于旧版本
1.对XAML更友好
2.事件书写更符合WPF的习惯
3.更好的可拓展性
</details>
Ⅰ 引入命名空间
C#
using FastHotKeyForWPF;
XAML
xmlns:hk="clr-namespace:FastHotKeyForWPF;assembly=FastHotKeyForWPF"
Ⅱ 激活与销毁
示例. GlobalHotKey
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
GlobalHotKey.Awake();
}
protected override void OnClosed(EventArgs e)
{
GlobalHotKey.Destroy();
base.OnClosed(e);
}
重写MainWindow的OnSourceInitialized与OnClosed是推荐的做法,当然,你可以选择其它时刻激活,只要你能确保Awake()时窗口句柄已存在
Ⅲ 使用 GlobalHotKey ,注册热键
情景. 假设你定义了以下HandlerA , 并希望用户按下 [ Ctrl + F1 ] 时执行它
private void HandlerA(object sender, HotKeyEventArgs e)
{
int ID = e.RegisterInfo.RegisterID;
MessageBox.Show($"A HotKey Has Been Invoked Whose ID is {ID}");
}
示例. 使用 GlobalHotKey.Add 注册热键 [ Ctrl + F1 ] ⇒ [ HandlerA ]
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
GlobalHotKey.Awake();
GlobalHotKey.Add(ModelKeys.CTRL, NormalKeys.F1, HandlerA);
}
恭喜,你已经掌握了该库最核心的功能!
Ⅳ 使用 GlobalHotKey ,修改热键
示例1. 已知触发Keys ,修改其对应的处理函数HotKeyEventHandler
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
GlobalHotKey.Awake();
GlobalHotKey.Add(ModelKeys.CTRL, NormalKeys.F1, HandlerA);
//初始热键为 [ CTRL + F1 => HandlerA ]
GlobalHotKey.EditHandler(ModelKeys.CTRL,NormalKeys.F1, HandlerB);
//由 [ CTRL + F1 => HandlerA ] 变为 [ CTRL + F1 => HandlerB ];
}
示例2. 已知处理函数HotKeyEventHandler ,修改其对应的触发Keys
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
GlobalHotKey.Awake();
GlobalHotKey.Add(ModelKeys.CTRL, NormalKeys.F1, HandlerA);
//初始热键为 [ CTRL + F1 => HandlerA ]
GlobalHotKey.EditKeys(HandlerA, ModelKeys.CTRL, NormalKeys.Q);
//由 [ CTRL + F1 => HandlerA ] 变为 [ CTRL + Q => HandlerA ];
//注意:通常情况下,即便允许多个组合键指向同一Handler,也不建议您这么做,类库默认只修改第一个找到的Handler,意外的情况需要您手动查询并修改热键
}
Ⅴ 使用 GlobalHotKey ,删除热键
示例1.
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
GlobalHotKey.Awake();
int ID = GlobalHotKey.Add(ModelKeys.CTRL, NormalKeys.F1, HandlerA);
//初始热键为 [ CTRL + F1 => HandlerA ]
//注册成功将返回注册ID,否则返回-1
GlobalHotKey.Clear();
//删除所有热键
}
示例2.
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
GlobalHotKey.Awake();
int ID = GlobalHotKey.Add(ModelKeys.CTRL, NormalKeys.F1, HandlerA);
//初始热键为 [ CTRL + F1 => HandlerA ]
//注册成功将返回注册ID,否则返回-1
GlobalHotKey.DeleteById(ID);
GlobalHotKey.DeleteByKeys(ModelKeys.CTRL, NormalKeys.F1);
GlobalHotKey.DeleteByHandler(HandlerA);
//删除指定热键(三种方案选一个即可)
//注意:DeleteByHandler与EditKeys特性不同,它会删除所有注册了指定Handler的热键,而不是只针对第一个
}
Ⅵ 使用 RegisterCollection ,索引式地查询注册在列的热键信息 ( RegisterInfo 对象 )
介绍. RegisterInfo 包含的信息
属性 | 类型 | 含义 |
---|---|---|
RegisterID | int | 注册id,-1表示无效的注册信息 |
ModelKey | ModelKeys | 触发Key之一,支持 CTRL/ALT |
NormalKey | NormalKeys | 触发Key之一,支持 数字/字母/Fx键/方向箭头 |
Handler | delegate HotKeyEventHandler? | 处理函数 |
示例1. 根据 ID 查询注册信息
RegisterInfo Info = GlobalHotKey.Registers[2004];
示例2. 根据 Keys 查询注册信息
RegisterInfo Info = GlobalHotKey.Registers[ModelKeys.CTRL,NormalKeys.F1];
示例3. 根据 Handler 查询注册信息
List<RegisterInfo> Infos = GlobalHotKey.Registers[HandlerA];
Ⅶ 使用库提供的UserControl搭建您的热键设置界面
引入库
xmlns:hk="clr-namespace:FastHotKeyForWPF;assembly=FastHotKeyForWPF"
使用库中控件
<hk:HotKeyBox x:Name="KeyBoxA"
CurrentKeyA="LeftCtrl"
CurrentKeyB="Q"
Handler="HandlerA"
CornerRadius="15"
ActualBackground="#1e1e1e"
FixedBorderBrush="White"
FixedBorderThickness="2"
TextColor="White"
HoverTextColor="Violet"
HoverBorderBrush="Cyan"
ConnectText=" + "
ErrorText="Failed"/>
private void HandlerA(object sender, HotKeyEventArgs e)
{
int ID = e.RegisterInfo.RegisterID;
//此处可获取热键的具体信息
MessageBox.Show($"A HotKey Has Been Invoked Whose ID is {ID}");
}
Ⅷ 使用库提供的抽象基类或接口,实现属于您自己的UserControl,详情可在 SampleDemo查看
介绍1.接口的使用规范
IAutoHotKeyProperty接口必须在View与ViewModel实现
IAutoHotKeyUpdate接口必须在ViewModel实现
示例1.您对于Model层没有定制需求 ( 1次接口的手动实现 )
ViewModel
/// <summary>
/// 基于抽象基类设计 ViewModel 层 , 要求使用统一的 HotKeyBoxModel 作为 Model ( 已在基类中定义_model )
/// </summary>
public class MyHotKeyBoxViewModelA : HotKeyViewModelBase
{
public MyHotKeyBoxViewModelA()
{
_model = new HotKeyBoxModel();
}
private SolidColorBrush _fixedtransparent = Brushes.Transparent;
public SolidColorBrush FixedTransparent
{
get => _fixedtransparent;
set
{
if (_fixedtransparent != value)
{
OnPropertyChanged(nameof(FixedTransparent));
}
}
}
//…
//拓展属性,它们不存在于Model,只负责逻辑数据的处理
//例如,将【UserControl的Background】与【FixedTransparent】做【TwoWay绑定】,即可永远保持为透明
//…
//重写属性,多数情况并不需要这一步
public override void UpdateText()
{
string? PossibilityA = (CurrentKeyA == Key.LeftCtrl || CurrentKeyA == Key.RightCtrl) ? "CTRL" : null;
string? PossibilityB = (CurrentKeyA == Key.LeftAlt || CurrentKeyA == Key.RightAlt) ? "ALT" : null;
string Left = (PossibilityA == null ? string.Empty : PossibilityA) + (PossibilityB == null ? string.Empty : PossibilityB);
Text = Left + " + " + CurrentKeyB.ToString();
}
//…
//重写方法
//例如,您希望不再区分 CTRL/ALT的左右,那么您可以重写UpdateText()
}
View
<UserControl x:Class="Sample.MyHotKeyBoxA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Sample"
mc:Ignorable="d"
Height="50"
Width="300"
Background="{Binding FixedTransparent,Mode=TwoWay}"
MouseEnter="UserControl_MouseEnter"
MouseLeave="UserControl_MouseLeave">
<UserControl.DataContext>
<local:MyHotKeyBoxViewModelA x:Name="ViewModel"/>
</UserControl.DataContext>
<Grid>
<TextBox x:Name="KeyGet"
Background="{Binding FixedTransparent}"
IsReadOnly="True"
PreviewKeyDown="KeyGet_PreviewKeyDown"/>
<TextBox x:Name="ActualText"
Text="{Binding Text}"
Background="{Binding FixedTransparent}"
FontSize="30"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="Transparent"/>
</Grid>
</UserControl>
public partial class MyHotKeyBoxA : UserControl, IAutoHotKeyProperty
{
public MyHotKeyBoxA()
{
InitializeComponent();
BoxPool.Add(this, ViewModel);
//必须执行这句话才可以参与库提供的唯一热键的实现流程
}
#region 接口实现
public int PoolID { get; set; } = 0;
public Key CurrentKeyA
{
get { return (Key)GetValue(CurrentKeyAProperty); }
set { SetValue(CurrentKeyAProperty, value); }
}
public Key CurrentKeyB
{
get { return (Key)GetValue(CurrentKeyBProperty); }
set { SetValue(CurrentKeyBProperty, value); }
}
public HotKeyEventHandler? HandlerData { get; set; }
public event HotKeyEventHandler? Handler
{
add { SetValue(HandlerProperty, value); }
remove { SetValue(HandlerProperty, null); }
}
#endregion
#region 依赖属性定义
public static readonly DependencyProperty CurrentKeyAProperty =
DependencyProperty.Register(nameof(CurrentKeyA), typeof(Key), typeof(MyHotKeyBoxA), new PropertyMetadata(Key.None, OnKeyAChanged));
public static readonly DependencyProperty CurrentKeyBProperty =
DependencyProperty.Register(nameof(CurrentKeyB), typeof(Key), typeof(MyHotKeyBoxA), new PropertyMetadata(Key.None, OnKeyBChanged));
public static readonly DependencyProperty HandlerProperty =
DependencyProperty.Register(nameof(Handler), typeof(HotKeyEventHandler), typeof(MyHotKeyBoxA), new PropertyMetadata(null, OnHandlerChanged));
private static void OnKeyAChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (MyHotKeyBoxA)d;
target.ViewModel.CurrentKeyA = (Key)e.NewValue;
}
private static void OnKeyBChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (MyHotKeyBoxA)d;
target.ViewModel.CurrentKeyB = (Key)e.NewValue;
}
private static void OnHandlerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (MyHotKeyBoxA)d;
target.HandlerData = (HotKeyEventHandler)e.NewValue;
target.ViewModel.HandlerData = (HotKeyEventHandler)e.NewValue;
}
#endregion
#region 事件
private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
KeyGet.Focus();
}
private void UserControl_MouseLeave(object sender, MouseEventArgs e)
{
Keyboard.ClearFocus();
}
private void KeyGet_PreviewKeyDown(object sender, KeyEventArgs e)
{
ViewModel.UpdateText();
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
var result = KeyHelper.IsKeyValid(key);
//KeyHelper提供Key合法性检查,以确保是一个受库支持的Key
if (result.Item1)
{
if (result.Item2 == KeyTypes.ModelKey)
{
CurrentKeyA = key;
//注意这里应该向依赖属性通知更改,直接通知ViewModel会导致BoxPool功能异常
}
else if (result.Item2 == KeyTypes.NormalKey)
{
CurrentKeyB = key;
}
}
e.Handled = true;
}
#endregion
}
示例2.您需要定制Model层 ( 3~4次接口的手动实现 )
需求场景过少,示例代码将延后提交
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0-windows7.0 is compatible. net7.0-windows was computed. net8.0-windows was computed. net8.0-windows7.0 is compatible. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net6.0-windows7.0
- No dependencies.
-
net8.0-windows7.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.