Skip to content

About

A library with a different approach to calling Win32 APIs, e,g providing reactive access to the clipboard or global hotkeys.

Topics

Resources

Stars

141 stars

Watchers

8 watching

Forks

Latest commit

 

History

779 Commits

Folders and files

Repository files navigation

Dapplo.Windows

Build Coverage Status NuGet License: MIT

Dapplo.Windows gives .NET applications on Windows access to what .NET itself doesn't cover: windows and their events, keyboard and mouse hooks, the clipboard, DPI awareness, power management, the Restart Manager, file dialogs and more. It was built for Greenshot and is split into small packages, so you only install what you use.

Documentation: https://www.dapplo.net/Dapplo.Windows/ (guides with samples and the API reference)

Requirements

  • Windows
  • .NET Framework 4.8 or .NET 10 (the packages target net480 and net10.0-windows)

Upgrading from 2.x? Version 3.0 changes many APIs on purpose: read the migration guide and the changelog.

Packages

Package NuGet What it's for Depends on (Dapplo.Windows.*)
Dapplo.Windows NuGet Window information, enumeration and manipulation, WinEvent hooks, window screenshots and icons Common, Com, DesktopWindowsManager, Gdi32, Icons, Input, Kernel32, Messages, User32
Dapplo.Windows.Automation NuGet UI Automation: scroll windows which draw their own scroll bars (browsers, WPF, Office), e.g. for a scrolling capture Dapplo.Windows, Common, Input, User32
Dapplo.Windows.Clipboard NuGet Monitor, read and write the clipboard, delayed rendering, clipboard history options Kernel32, Messages
Dapplo.Windows.Input NuGet Keyboard and mouse hooks, hotkeys and key sequences, generating input, raw input Common, Messages, User32
Dapplo.Windows.Dpi NuGet DPI calculations, DPI change handling, bitmap scaling, DPI awareness APIs Common, Gdi32, Messages, User32
Dapplo.Windows.Forms NuGet Windows Forms integration: DpiAwareForm, window messages of controls, placement Dapplo.Windows, Dpi, Messages
Dapplo.Windows.Wpf NuGet WPF integration: DPI handling, window messages, conversions, BitmapSource Dapplo.Windows, Dpi, Gdi32, Messages
Dapplo.Windows.Messages NuGet SharedMessageWindow for window messages without a window, session notifications Common
Dapplo.Windows.SystemState NuGet Prevent sleep, sleep / shut down / log off, wake timers, power events Messages
Dapplo.Windows.AppRestartManager NuGet Register for restart, answer shutdown and Restart Manager requests Messages
Dapplo.Windows.InstallerManager NuGet For installers: find, close and restart the processes which lock files -
Dapplo.Windows.Dialogs NuGet File open, file save and folder dialogs without WinForms or WPF Common
Dapplo.Windows.Icons NuGet Extract icons, write ICO and CUR files, capture the mouse cursor Common, Dpi, Gdi32, Kernel32, Messages, Shell32, User32
Dapplo.Windows.Devices NuGet Device and volume arrival / removal notifications Messages
Dapplo.Windows.DesktopWindowsManager NuGet DWM: frame bounds, cloaking, accent color, corners Common
Dapplo.Windows.Citrix NuGet Citrix session detection and client information Common
Dapplo.Windows.EmbeddedBrowser NuGet Let the WinForms WebBrowser use the installed IE version Com
Dapplo.Windows.Multimedia NuGet Play system sounds and WAV data -
Dapplo.Windows.Advapi32 NuGet Registry change notifications, logon SID -
Dapplo.Windows.User32 NuGet User32 P/Invoke: windows, displays, messages Common, Messages
Dapplo.Windows.Gdi32 NuGet GDI / GDI+ P/Invoke and safe handles Common, User32
Dapplo.Windows.Kernel32 NuGet Kernel32 P/Invoke: processes, DLL loading, package identity Common
Dapplo.Windows.Shell32 NuGet Shell32 P/Invoke: taskbar, icons Common
Dapplo.Windows.Com NuGet COM helpers Common
Dapplo.Windows.Common NuGet Shared structs (NativeRect, ...), HResult, WindowsVersion -

Only Dapplo.Windows.Forms, Dapplo.Windows.Wpf and Dapplo.Windows.EmbeddedBrowser reference Windows Forms or WPF.

Quick start

dotnet add package Dapplo.Windows
dotnet add package Dapplo.Windows.Clipboard
dotnet add package Dapplo.Windows.Input

React to 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"));

Events arrive on background threads (the hook thread or the thread of the SharedMessageWindow): keep your handlers short and use ObserveOn for UI work. Getting started explains why.

Documentation

The wiki has short versions of these pages.

Examples

  • Dapplo.Windows.Example.ConsoleDemo: keyboard hook in a console application
  • Dapplo.Windows.Example.FormsExample: DPI-aware forms, context menus and bitmap scaling, embedded browser, restart registration
  • Dapplo.Windows.Example.WpfExample: WPF window with DPI handling, keyboard hook and device notifications
  • Dapplo.Windows.Example.InstallerExample: an "installer" which closes and restarts the FormsExample with the Restart Manager
  • Dapplo.Windows.Example.DocSamples: every code sample of the documentation, compiled with each build

Building

You need the .NET 10 SDK (see global.json) on Windows.

dotnet build src/Dapplo.Windows.sln
dotnet test src/Dapplo.Windows.sln --filter "Category!=Interactive"

Tests with Category=Interactive send input, replace the clipboard or write to the registry; run them only on a machine you're not using. tools/build-runner builds and tests on a Windows machine on request, for tools which can only write files into the repository.

When you change a code sample, change it in src/Dapplo.Windows.Example.DocSamples and copy it into the markdown, see About the samples.

Releasing

Every merge to master is a release. The build computes the version with Nerdbank.GitVersioning (src/version.json: major.minor plus the number of commits since the version last changed, e.g. 3.2.1, 3.2.4, …), packs everything and then waits for approval of the NuGet environment. After approval it pushes the packages to nuget.org, creates the tag and the GitHub release and publishes the documentation and the wiki. For a new minor or major version, change version in src/version.json.

The release notes come from CHANGELOG.md. Because the patch number is only known when the release is built, write the changes of a new minor version under ## [3.2.0] (the first release of 3.2 uses it), and later fixes under ## [Unreleased]. A section with the exact version (## [3.2.4]) always wins. Without a matching section GitHub generates the notes from the merged pull requests.

Contributing

Issues and pull requests are welcome. Please add an entry to CHANGELOG.md for user-visible changes.

License

MIT, see LICENSE.

About

A library with a different approach to calling Win32 APIs, e,g providing reactive access to the clipboard or global hotkeys.

Topics

Resources

Stars

141 stars

Watchers

8 watching

Forks

Sponsor this project

Used by

Contributors

Languages