microsoft / microsoft/PowerToys

Migrate existing WPF/WinForm utility to WinUI3

Open
#46,463 3 comments 0 reactions 1 assignee View on GitHub

@moooyo is already working on this.

Since Mar 24, 2026.

Product-FancyZones Product-General
Dominant language
C
Stars
139k
Forks
8.6k
PR merge metrics
PR metrics pending

Description

Description of the new feature / enhancement

PowerToys' utilities come from various sources and have been completed over a wide period of time, that makes our codebase have WPF, WinUI3, WinForms, C++ UI code now. This makes the new contributor more confused and hard to maintain.

WinUI 3 provides a modern UI and makes sure that our experiences fit in with the Windows 11 look and feel.

By this change, we can merge many redundant code to the same one and reduce more codebase and installed size.

Scenario when this would be used?

N/A

Supporting information

No response


Benefit

Beyond code maintainability, completing this migration measurably shrinks both the install footprint and the installer. All numbers below are measured against an installed v0.100.2 (x64) build (960 MB on disk; 271.7 MB installer).

Why there is a win

PowerToys ships a self-contained Microsoft.WindowsDesktop.App runtime (WPF + WinForms) and bundles a full copy in both runtime folders — the install root and WinUI3Apps\:

Runtime slice Per folder Contents
WPF 42.6 MB 28 DLLs — PresentationFramework/Core, wpfgfx_cor3, System.Xaml, WindowsBase, D3DCompiler_47_cor3, PenImc_cor3, ReachFramework, …
WinForms 25.1 MB 8 DLLs — System.Windows.Forms*, System.Drawing.Common, System.Private.Windows.Core, …

The WinUI3Apps\ copy exists only because shared libraries drag the WindowsDesktop runtime into otherwise-clean WinUI 3 modules — specifically Common.UI (UseWPF=true) and the WPF ICommand surface in Settings.UI.Library (both already listed below as cross-cutting blockers). Proof the runtime is bundled on demand: a pure WinUI 3 module (the migrated KBM editor) ships zero WindowsDesktop DLLs.

Estimated savings (x64)

The WindowsDesktop runtime is bundled once per runtime folder — the install root and WinUI3Apps\. The near-term win is the WinUI3Apps\ copy: every module in that folder is already WinUI 3 and only pulls WPF transitively through the shared libraries, so making Common.UI and Settings.UI.Library framework-neutral removes that whole copy. Eliminating the root copy is a longer-term goal — every remaining WPF surface that runs from the root (the in-flight module migrations plus the modules currently listed under Out of scope) has to move off WPF as well.

Milestone Installed Installer
Near-termWinUI3Apps\ drops its WPF copy, once Common.UI + Settings.UI.Library are framework-neutral ~42.6 MB (~4.4%) ~17–19 MB
Long-term — all WPF gone from both folders (every remaining WPF module in the install root migrated too) ~85 MB (~8.9%) ~30–38 MB
Ceiling — the whole WindowsDesktop runtime gone (WinForms eliminated as well, incl. the preview / thumbnail handlers) ~138 MB (~14.4%) up to ~55 MB
Third-party packages removed along the way
  • ModernWpfUIModernWpf.dll + ModernWpf.Controls.dll (~1.6 MB), FancyZones Editor only.
  • ControlzExControlzEx.dll (~0.9 MB across both folders), pulled by Common.UI.
  • Microsoft.Xaml.Behaviors.Wpf — swapped for the already-shipped Microsoft.Xaml.Behaviors.WinUI.Managed (net removal, no new payload).
  • HelixToolkit.Core.Wpf stays (STL Thumbnail is out of scope).

Notes: installer deltas are compressed estimates (managed DLLs compress ~2.3–2.9×; the WiX/CAB payload does not dedup the two identical runtime copies, so the root + WinUI3Apps\ copies are stored separately). The base .NET runtime and the WinAppSDK / WinUI 3 runtime are unaffected — both are still required after migration.


WinUI 3 migration — status & remaining work

This issue tracks moving the remaining WPF surfaces to WinUI 3.

✅ Completed
  • Image Resizer — migrated to WinUI 3 (#45288), used as the reference implementation.
  • Quick Accent — migrated to WinUI 3 (#48889 · PR #48891, merged). TransparentWindow overlay, system-theme follow, content-hugging sizing, and accent/DPI unit tests; PowerAccent.Core is now UI-framework-agnostic.
  • Color Picker — migrated to WinUI 3 (#49000 · PR #49174, merged). Full module migration covers the picking overlay, color editor, zoom magnifier, settings, and Win32 input hooks; MEF was replaced with Microsoft.Extensions.DependencyInjection.
🔄 In progress
  • Workspaces (Editor + Launcher) — #48686 · PR #48700 (supersedes the editor-only #48799; the whole module is tracked together). Blockers: transparent launch overlay, WPF Frame navigation, and the shared WorkspacesCsharpLibrary still being WPF.
  • Text Extractor (PowerOCR) — #49656 · PR #49431 (draft). Full module migration to WinUI 3, shipped from WinUI3Apps\: OCR / formatting / table analysis / selection geometry extracted into PowerOCR.Core, .resx.resw + x:Uid, MEF → Microsoft.Extensions.DependencyInjection. The three module blockers are addressed — the snipping overlay is rebuilt as one borderless topmost WindowEx per DisplayArea, the WPF CombinedGeometry selection clip is replaced with mask rectangles plus a selection Border, and mixed-DPI / negative-origin positioning is rewritten on AppWindow. Remaining: interactive multi-monitor / DPI / theme verification, the blocked PowerOCR-UITests run, and a green CI run.
  • FancyZones Editor — Niels Laute (niels9001) is currently redesigning the editor UX. The WinUI 3 migration remains tracked in #49680; the previous draft PR #49681 was closed without merging.
🧱 Cross-cutting blockers
  • Transparent / no-activate overlay gap — hits Color Picker, PowerOCR, FancyZones, and Workspaces. WPF provides it for free; WinUI 3 does not. Recommend one shared native-overlay helper instead of solving it per module.
  • Common.UI — theming depends on WPF Application/Dispatcher + ControlzEx; 40+ consumers. Must be coordinated with #48278.
  • Settings.UI.Library — exposes a WPF ICommand surface used by ~35 projects; extract a framework-neutral contract.
🚫 Out of scope
  • PowerToys Run — will not migrate. Borderless overlay + global hotkey interop and the Wox.Plugin public ABI (WPF types, used by 22+ plugins) would break the plugin ecosystem for little UI gain. Stays on WPF.
  • STL Thumbnail Provider — headless, no UI; its only WPF dependency is Media3D, which has no WinUI 3 equivalent. Stays on WPF.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.