Repository navigation
Getting Started
github-actions[bot] edited this page Sep 30, 2026
·
2 revisions
Full version: Getting started in the documentation.
- Windows
- .NET Framework 4.8 or .NET 10 (
net480andnet10.0-windows)
Install the package for the feature you need, the Home page lists them with their dependencies.
dotnet add package Dapplo.Windows # windows and window events
dotnet add package Dapplo.Windows.Clipboard # clipboard
dotnet add package Dapplo.Windows.Input # keyboard and mouse hooks
dotnet add package Dapplo.Windows.Dpi # DPI awareness (plus .Forms or .Wpf)List the visible application windows:
// using Dapplo.Windows.Desktop;
foreach (var window in InteropWindowQuery.GetVisibleApplicationWindows())
{
Console.WriteLine($"{window.GetCaption()} - {window.GetClassname()} at {window.GetInfo().Bounds}");
}Get told when a window title changes:
// using Dapplo.Windows.Desktop; using System.Reactive.Linq;
IDisposable subscription = WinEventHook.WindowTitleChangeObservable()
.Subscribe(info =>
{
var window = InteropWindowFactory.CreateFor(info.Handle);
Console.WriteLine($"Title changed: {window.GetCaption(forceUpdate: true)}");
});Log the text that is copied to the clipboard:
// using Dapplo.Windows.Clipboard; using System.Reactive.Linq;
IDisposable subscription = ClipboardNative.OnUpdate
.Where(info => info.FormatIds.Contains((uint)StandardClipboardFormats.UnicodeText))
.Throttle(TimeSpan.FromMilliseconds(100))
.Subscribe(info =>
{
using var clipboard = ClipboardNative.Access();
Console.WriteLine($"Copied: {clipboard.GetAsUnicodeString()}");
});A global hotkey:
// using Dapplo.Windows.Input.Enums; using Dapplo.Windows.Input.Keyboard; using System.Reactive.Linq;
// Ctrl+Shift+S anywhere in Windows. The handler runs on the hook thread, ObserveOn moves the work to the UI thread.
IDisposable subscription = KeyboardHook.KeyboardEvents
.Where(new KeyCombinationHandler(VirtualKeyCode.Control, VirtualKeyCode.Shift, VirtualKeyCode.KeyS))
.ObserveOn(SynchronizationContext.Current)
.Subscribe(_ => Console.WriteLine("Ctrl+Shift+S pressed"));-
Subscribing installs, disposing removes. Hooks and registrations exist while you're subscribed. Keep the
IDisposableand dispose it. -
Events arrive on background threads. Window messages (clipboard, power, session, devices, WinEvents, raw input)
arrive on the thread of the SharedMessageWindow, keyboard and mouse events on the hook thread. Keep
OnNextshort and useObserveOnfor UI or slow work. -
Answer synchronously. Set
Handled/ResultinsideOnNext, before anyObserveOn,Throttleorawait. -
A failing subscriber doesn't break the others. Its exception ends only its own subscription and is published on
SubscriberErrors.
// Hooks and registrations are made when you subscribe, and removed when you dispose the subscription
IDisposable subscription = ClipboardNative.OnUpdate.Subscribe(info => { });
// ...
subscription.Dispose();
// Clipboard access is a lock for all applications: hold it briefly and always dispose it
using (var clipboard = ClipboardNative.Access())
{
// ...
}