AgentFire.Input.Hooks
2.0.0
dotnet add package AgentFire.Input.Hooks --version 2.0.0
NuGet\Install-Package AgentFire.Input.Hooks -Version 2.0.0
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="AgentFire.Input.Hooks" Version="2.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AgentFire.Input.Hooks --version 2.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: AgentFire.Input.Hooks, 2.0.0"
#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 AgentFire.Input.Hooks as a Cake Addin #addin nuget:?package=AgentFire.Input.Hooks&version=2.0.0 // Install AgentFire.Input.Hooks as a Cake Tool #tool nuget:?package=AgentFire.Input.Hooks&version=2.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Usage
- Instantiate your keyboard hook.
IDisposable keyboardHook = Hardware.HookKeyboard(ev => {
// Your actions against the event of RawKeyboardEvent (ev).
});
- Instantiate your mouse hook.
IDisposable mouseHook = Hardware.HookMouse(ev => {
// Your actions against the event of RawMouseEvent (ev).
});
It is that easy. Now for the "what's the catch" part:
1. You have to call the factory (Hardware.HookKeyboard()
/ Hardware.HookMouse()
) from a thread which has a running message loop
Assuming you are using WPF directly (from this example code:
private readonly IDisposable _keyboardHook;
private void OnKey(RawKeyboardEvent ev)
{
// Here you go.
}
public MainWindow()
{
InitializeComponent();
// As code is run on the app's main thread, the event's callbacks will also be called on that thread (via the Message Loop mechanism).
// InvokeAsync posts the anonymous delegate asynchronously, which is my best attempt at releasing the event's callback as fast as possible.
_keyboardHook = Hardware.HookKeyboard(ev => Dispatcher.InvokeAsync(() => OnKey(ev)));
}
protected override void OnClosed(EventArgs e)
{
// Don't forget to clean up.
_keyboardHook.Dispose();
base.OnClosed(e);
}
Assuming you are using just the WPF's engine, here is a nice way to start a new thread and the required Message Loop inside it:
private void OnMouse(RawMouseEvent ev)
{
// Here you go.
// This will run on the Message Loop's internal thread, so return as fast as possible.
}
(IDisposable mouseHookLoop, IDisposable mouseHook) = MessageLoop.Create(() => Hardware.HookMouse(OnMouse));
// Dispose of the hook when not needed anymore.
mouseHook.Dispose();
// Stop the message loop.
mouseHookLoop.Dispose();
3. Other notes
- Don't forget that Global Hooks considered a bad practice since they hurt the performance system-wide.
- Try to minimize your handler code. If you spend more than 1 ms on handling the message, consider using cross-thread message queue or posting a delegate elsewhere.
- Feedback is appreciated.
- Enjoy.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0-windows7.0 is compatible. net7.0-windows was computed. net7.0-windows7.0 is compatible. net8.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net6.0-windows7.0
- No dependencies.
-
net7.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.