Introduction
As a Windows developer you’ve considered creating a graphical user interface (GUI). The inevitable question that comes up is: which Windows GUI technology should I use?
I tried to answer that question myself, and thought surely everyone is still using Windows API (ye olde Win32 API) with GDI/GDI+! Right? No? Oh, let’s see what there is now… WinUI, WPF, WinForms, UWP, .NET MAUI, oh my, the list goes on. Why did these all come about?
A difficult part of getting started with modern Windows GUI development and picking a Windows UI technology today is naming Microsoft has created around their APIs. Naming, re-naming, re-defining, deprecating, and obsoleting, make things complicated over the long history of Windows development. I will try to demystify the terms Microsoft has made with with some history and context. In the future, we can get into how to create our first ‘Hello World’ application.
I will be focusing on Windows operating system, and not the entire Windows devices ecosystem. I won’t get into alternatives to the native Microsoft solutions but there is Electron, CEF, Qt, Unity, and ImGUI to name a few.
GUI Naming Convention
Graphical User Interface (GUI) can also be referred to as:
- user interface or UI
- UI framework
- UI technology
Graphical subsystem or user experience (UX) framework terms can be used but have different meanings. Any of these terms can in some way be compared to each other. The term UI technology (bucketing framework, API) being the broad category things can be put into.
The prefix or adjective use to describe the application’s type (e.g., “Win32” in Win32 application) is usually the majority API, framework, or even language used for the application. However, this distinction is not always perfect and sometimes can lead to confusion. For example, a Windows API application can also use Windows RunTime, it can be a console application or a Win32 (GUI) application. The thing to keep in mind is if an application is called a certain way, it may have more APIs, frameworks, and languages involved.
Windows API
In the mid-80s, Microsoft created the original Windows API for Windows 1.0. The Windows API refers to the collection of functions to interact with the Microsoft Windows operating system. The Windows API contains categories of functions such as: basic/core services (e.g., file system, processes, threads), advanced services (e.g., registry, services, account management), network services, Graphics Device Interface (GDI), and User Interface. Over time, new functionality has been added to the Windows API along with new versions of the Windows operating system.
The C language was the choice for the API because it was accessible from other languages. The Windows API made sense as a flat non-hierarchical C-style API. As time went on, the number of functions with lack of consistent naming and grouping (e.g., C++ namespaces) made the Windows API dated. Later, newer APIs used Component Object Model (COM) to improve on these issues.
The part of Windows API we are interested in is the graphical user interface, but the Windows API provides more categories and interactions to the Windows operating system than user interface.
Windows API is the bedrock of the other APIs (e.g., Windows RunTime). The Windows API has yet to be replaced but extended as necessary with new operating systems. Replacing the Windows API would break legacy support. Replacing the Windows API might be done one day, but as of now as new layers and components are added, they still use the Windows API under the hood.
Windows API Naming Convention
The Windows API is referred to by a few different names:
- Windows API or WinAPI
- Win32 API or Win32
- Classic Windows API, Traditional Windows API
The name Win32 API came and stuck because of the Windows 95 and Windows 98 era of 32-bit Windows to differentiate it from 16-bit era Windows API. Later on, with Windows 64-bit, the name “Win32 API” doesn’t make sense in modern reference but you’ll see it being used today including by Microsoft. Now “Win32 API” refers to both 32-bit and 64-bit Windows1.
In discussion of UI development, something that uses the Win32 API directly will usually be referred as:
- Win32 app
- Win32 desktop app
- classic desktop app
- classic Windows application
- Windows desktop application
Win32 API - User Interface
The user interface part of Windows API is responsible for creating and managing windows (e.g., CreateWindow
), receive keyboard and mouse input, and providing basic controls. Controls are graphical widgets. Buttons, scroll bars, status bars, progress bars, toolbars, and tabs are examples considered controls.
The Windows API functionality can be found in user32.dll
, common control library comctl32.dll
, common dialog box library comdlg32.dll
, and shell shell32.dll
.
Win32 API - User Interface naming convention
I’ve seen a few times where the Windows API user interface is called “Windows USER”. The only place I found Windows USER being used was in the file description of user32.dll
as Multi-User Windows USER API Client DLL. I think Windows API, Win32 API, user32.dll
, and Windows USER are interchangeable.
Win32 API - Graphics Device Interface
The Graphics Device Interface (GDI) is responsible for representing graphical objects and transmitting them to output devices (e.g., the monitor). Apps interact with the GDI for drawing lines, curves, fonts, and colors.
Later Windows XP added GDI+ which added more features. Then in Windows Vista GDI and GDI+ applications run on the new compositing engine known as Desktop Window Manager (DWM) which is hardware-accelerated.
Component Object Model
In the early 90s, Object Linking and Embedding (OLE) came from the need for different Office programs to include objects from each others programs (e.g., embedding an Excel chart in Word). OLE evolved from Dynamic Data Exchange (DDE) which was inter-process communication (IPC). Later, Component Object Model (COM) evolved from OLE.
Fun fact: Initially, COM was called OLE 2. 1
In 1993, Microsoft introduced Component Object Model (COM) to provide application binary interfaces between components. COM is Microsoft’s own standard and is used under-the-hood of many of the Microsoft APIs (e.g., example Windows Runtime).
Popular current APIs accessed through COM are: Microsoft Media Foundation (replacing DirectShow), DirectX, DirectComposition, Windows Imaging Component (WIC), and Background Intelligent Transfer Service (BITS).
Windows SDK has an OLE/COM viewer called oleview.exe
in Windows Kits\10\bin\(Windows-SDK-version)\x64
.
COM introduces two high level ideas:
- clients (e.g., applications, services) interact with objects through interfaces
- components are loaded dynamically (late binding)
Motivation for COM - What did COM try to solve?
COM is Microsoft’s approach to pragmatic software design. COM is an interpretation of the programming paradigm Object-oriented programming (OOP). OOP is based on the idea of objects which contain data (or, attributes), and, behavior (code, or, methods). OOP has many features: polymorphism, encapsulation, inheritance, and more. COM interprets encapsulation (information hiding) and inheritance in a different way than traditional OOP (and, how C++ interprets OOP).
Inheritance is a mechanism where a new class (i.e., derived class) is from another class (i.e., base class). Microsoft considered inheritance’s utility as code reuse. Other benefits of inheritance include: to build upon existing classes, to specify new implementations while maintaining existing behaviors, and to extend original code.
To improve on inheritance’s code reuse, encapsulation was to be made more strict. To achieve this improved code reuse, the COM designers split inheritance into two concepts: implementation inheritance and interface inheritance.
Implementation inheritance is what is found in a language like C++, where the implementation (or, behavior) is inherited. The issue with implementation inheritance is that it causes coupling between the base and derived class reducing the effectiveness of encapsulation of the classes.
Interface inheritance assumes that only the specification of behavior is inherited. This enables polymorphism (i.e, using a single interface to different objects).
The COM designers make the assertion if code reuse is the essential goal of inheritance (while maintaining strong encapsulation) then implementation inheritance can be dropped, while keeping interface inheritance. Encapsulation should be more strict which makes the base class opaque to the derived class. One can make the argument that the COM approach (i.e., “Component-Oriented Programming”) is more aligned with OOP than a language like C++. Within the language (e.g., C++) can still utilize implementation inheritance of the language within the component while implementing COM across different components. Brilliant!
From Essential COM 2:
Object-Oriented Programming = Polymorphism + (Some) Late Binding + (Some) Encapsulation + Inheritance
Component-Oriented Programming = Polymorphism + (Really) Late Binding + (Real, Enforced) Encapsulation + Interface Inheritance + Binary Reuse
Windows RunTime
In 2012, Windows RunTime (WinRT) was introduced as a new API with Windows 8. WinRT is “platform-agnostic component and application architecture” 3. WinRT is more actually a language-independent application binary interface (ABI) based on COM, not a runtime. A runtime being roughly the code that runs while the program is running.
The WinRT API is built on top of the COM concept while extending COM (e.g., providing type metadata as WINMD files). From design and usage of the API, WinRT was designed better than the classic Windows API functions (e.g., namespaces). WinRT is not a new native API for Windows and does not replace the classic Windows API 1. WinRT builds and expands on top of Windows API (legacy Windows binaries and APIs).
Apps written in C++, C#, and other languages can use the WinRT APIs through language projections.
WinRT is not only for building store apps. WinRT can be used to develop console applications, Win32 applications, and device drivers. Windows Store Apps can use a subset of Win32 and COM APIs (however, could fail Windows Store certification).
Technically, because WinRT is platform-agnostic it should be able to have implementations for other platforms. WinRT applications should be able to target multiple devices (e.g., Xbox, phones, tablets, laptops, and HoloLens). Although this is not clear if its facilitated by Universal Windows Platform (UWP). Also I didn’t find much documentation describing WinRT on Xbox or HoloLens. It might just be that WinRT API can be used along with those devices.
Why Windows RunTime?
Historically, Win32 API is a flat (no hierarchy) C-style API which was great for C language but not for newer languages like C# or C++, utilizing newer language features like namespaces. Windows RunTime was introduced as a language agnostic API for the OS with hierarchy (namespaces, classes) and meta data for the APIs (about the classes/members) allowing language projections (e.g., C++, C#, JS).
Naming Conventions
Windows Runtime applications technically don’t have a specific name, as they are just the API and not the platform or framework which applications are created with. However, this hasn’t prevented people associating WinRT tightly with UWP.
Which probably caused coupling of WinRT and Universal Windows Platform (UWP) apps. WinRT can work along with an application that uses Win32 API and in console applications too.
C++ Language Projection: What is C++/WinRT?
C++/WinRT is the latest and Microsoft recommended Windows RunTime C++ language projection 4. C++/WinRT is a standard C++17 (modern C++) language project for the Windows Runtime for C++. C++/WinRT is a header-only library. Just another standard C++ library, cool!
For C++, Microsoft wants developers to use C++/WinRT rather than directly the Windows API. C++/WinRT ships with Windows SDK version 10.0.17134.0
(Windows 10, version 1803
).
How is C++/WinRT better than C++/CX?
C++/WinRT replaces C++/CX and the Common Language Infrastructure (CLI) (i.e., C++/CLI). C++/CX used non-standard data types, non-standard keywords, hat pointers, ref classes. C++/WinRT is superior in all design ways and should be used over the C++/CX if possible. The two can be mixed but it is recommended to keep everything in C++/WinRT.
What is the difference between C++/WinRT and C++/CX?
C++/CX uses the Common Language Infrastructure (CLI) which is a variant of C++. C++/WinRT is simply a C++ library for WinRT. Both are a C++ language projection for WinRT.
Where are the C++/WinRT headers?
The C++/WinRT headers can be found at C:\Program Files (x86)\Windows Kits\10\Include\(Windows-SDK-version)\cppwinrt\winrt
In the headers CPPWINRT_VERSION
should be defined as >=2.0
, for example:
static_assert(winrt::check_version(CPPWINRT_VERSION, "2.0.220110.5"), "Mismatched C++/WinRT headers.");
#define CPPWINRT_VERSION "2.0.220110.5"
Universal Windows Platform
Universal Windows Platform (UWP) is a Microsoft app development platform introduced in Windows 10. The goal of UWP is to help develop applications that run on multiple platforms without having to be rewritten for each (hence the name “universal app”). UWP is one of many ways to create client applications for Windows. Universal Windows Platform utilizes Windows Runtime (WinRT) as the underlying API. UWP supports languages C++, C# (and other .NET languages), and XAML for the UI framework.
UWP introduced the concept of application container creating some of UWP app benefits as they are secure, used a common API, Microsoft Store, and used Windows RunTime5.
- Secure: UWP apps declare which device resources (e.g., microphone, location, camera, USB devices, files) and data the app accesses. The user can allow or revoke the app’s access. This is similar to how mobile apps access control. Win32 classic apps do not have these controls.
- Common API: UWP has a set of core APIs that are avaialble on all Windows devices. The core APIs will run on any device such as desktop PC, Xbox, Mixed-reality headset (e.g., HoloLens).
- Store: Microsoft Store is available on multiple devices such as PC, tablet, Xbox, HoloLens, Surface Hub, and Internet of Things (IoT) devices. Applications can also be monitzied (e.g., paid download, trials, sales, in-app purchases). Additionally, Install/uninstall without risk to the machine or incurring “machine rot”. Machine rot meaning essentially leaving files behind after uninstall or littering the computer with files that are not cleaned up.
Naming Convention
Universal Windows Platform (UWP) applications on Windows can also be referred to as:
- UWP app
- Windows Store Apps (ambiguous, as WinUI can also be on Store)
- Windows Apps (confusing with Win32 desktop apps, they too are Windows applications)
- Metro Apps (formerly)
- Modern Apps (formerly)
Windows RunTime (WinRT) vs Universal Windows Platform (UWP)
Universal Windows Platform is a collection of APIs on a broad set of platforms (e.g., Windows, Xbox), but it is not just the Windows Runtime. UWP utilizes WinRT but they are not interchangeable. UWP provides more of a platform around WinRT and can target different devices.
UWP Issues
If you want to use the latest Windows controls then the user must be on the latest version of Windows. This creates a coupling between operating system and the app. Additionally, a UWP app needs to go through the Microsoft Store. Otherwise the app has to be side-loaded (i.e., installing an app that isn’t from an official source) as a developer. Side-loading is not a reasonable request for the end-user. Finally, there are also Win32 applications, which are not supported by the Store. WinUI is Microsoft’s attempt to fix these problems.
Likely, a typical developer might not want to develop the same app for different platforms (e.g., Xbox, Windows) from all the same project as UWP provides. To get all the same layouts to work would either be much effort (close to the same effort as making separate project for each platform) or a generic looking application.
Additionally, app developers for Xbox would likely rather have it work on other consoles (e.g., Playstation, Switch), not on Windows. A Xbox developer mostly is developing a game made for the console, and the platform specific code is probably minimal compared to rest of the game. Unity and Unreal can also be left to make these abstractions rather than Microsoft.
Windows UI Library
The Windows UI Library (WinUI) is a native user experience (UX) framework for Windows desktop and UWP applications. WinUI modernizes the UI by using Fluent Design6 into all the UX (i.e., controls and styles). The dependency problem of UWP being tightly coupled with the Windows SDK and Windows version is solved with WinUI. However, this introduces the requirement of the Windows App SDK runtime files to be installed on Windows or shipped with the application.
Currently, WinUI as an ecosystem for both desktop and UWP apps – unifying Win32 app development with UWP. However, looking more closely UWP is only supported on WinUI 2.x
only with no plans to support UWP on WinUI 3.x
. So, yes, WinUI supports both desktop and UWP apps but seems UWP support ends with WinUI 2.x
. Microsoft wants the developers to either build new apps in WinUI or port existing apps (e.g., MFC, WinForms, WPF, UWP), or use new features through XAML Islands.
Microsoft recommends migrating UWP to WinUI 3, however, not all UWP features are supported in WinUI 7.
WinUI Benefits
WinUI 3 ships with the Windows App SDK decoupling itself from Windows SDK and the OS. This means the UX stack (i.e., native controls, fluent style) is completely decoupled from the OS and the Windows SDK. The latest Windows controls and style are available outside of .NET (previously, WPF and WinForms). WinUI also attempts to unify Win32 desktop applications with UWP. WinUI can also be deployed to the Microsoft Store or through the web. WinUI is also open sourced 8, with its first Github release in December 2018.
WinUI Issues
The biggest issue of WinUI currently is that it does not have all the functionality of all the previous UI frameworks Microsoft has developed. There is no XAML UI designer like for WPF 9. It is unclear right now when they will reach parity with other UI frameworks from their roadmap 10.
Windows App SDK
The Windows App SDK is a set of new components and tools that represents the next evolution in the Windows app development platform providing modern UI, APIs, and platform features.
The Windows App SDK provides a unified set of APIs and tools that can be used in a consistent way by any desktop app on Windows 11 and Windows 10 version 1809
.
Windows App SDK vs Windows SDK
The Windows App SDK does not replace the Windows SDK. Windows App SDK also does not replace existing desktop Windows app (e.g., .NET/WinForms/WPF, desktop Win32 with C++). Windows App SDK provides another way to develop apps and use existing tools and app types with a common set of APIs.
WinUI XAML vs UWP XAML
Both WinUI and UWP use similar XAML for the UI language. For simpler apps, UWP XAML can be dropped into a WinUI XAML and the UI will just work. For the code, changing the Windows.UI.*
namespace to Microsoft.UI.*
namespace is enough to change from UWP to WinUI. Generally, if the logic and UI are separated then migrating from one framework to another hopefully isn’t too difficult if the project is small enough. For large projects, XAML Islands seem to be the bridge to keep already developed applications looking modern.
WinUI vs WPF
The major advantage WinUI has with WPF is support for the new Fluent design style. However, this is alleviated with XAML Islands. The major advantage of WPF is that it is a mature UI framework technology and has a XAML designer that WinUI does not have.
Conclusions
Future of WPF, WinForms
Both WPF11 and WinForms12 are supported in the latest .NET and show activity on their repos. There doesn’t seem to be an indication that WPF and WinForms are going away with WinUI. WPF and WinForms seem to be mature UI framework technology that continue to be supported with .NET. Developers also like the Visual Studio XAML UI designer that comes with WPF. Windows App SDK can simply be added for WPF and .NET 5+ applications to get access to all the new APIs.
Future of UWP
Interpreting Microsoft’s announcement, UWP still seems to be supported. Regarding WinUI, support for UWP ends with WinUI 2.x with no plans to bring support in WinUI 3.x. If WinUI is the future of Windows application development then it can be interpreted that Microsoft will reduce its focus on UWP. Developers have further interpreted that it is only time before UWP is deprecated and obsoleted. This then makes UWP is unofficially deprecated.
Interesting quotes:
What does the Windows App SDK mean for UWP and desktop developers?
For developers using the Universal Windows Platform (UWP) project types, if you are happy with your current functionality in UWP, there is no need to migrate your project type. WinUI 2.x and the Windows SDK will continue to support UWP project types, including bug, reliability, and security fixes. In Windows, we use UWP project types for several of our own Windows apps. If you want to use the Windows App SDK or .NET 5 in your existing app, you can migrate your project to a desktop project type as described in the migration section further below.13
WinUI 3 is the next generation of Microsoft’s Windows UI library. It succeeds the UWP XAML framework as Microsoft’s actively-developed native UI platform for Windows.14
Future of native UI development on Windows
Windows App SDK seems to be a solid path in decoupling new styles and features from the Windows version moving forward. Microsoft is also making Windows App SDK the superset of both desktop and UWP development. The superset unifies the two development paths, hence name Project Reunion.
WinUI seems like a good midpoint between what Microsoft tried to do with UWP and the classic Win32 desktop application development. WinUI has been around for a while in the works.
Microsoft seems to be pushing WinUI as the future but the API is not fully realized. With the push to move developers to WinUI, it seems odd is the disparity in features, tools, and even stability between WinUI and other UI frameworks. However, maybe Microsoft is taking a lean implementation to see up take by developers. An idealistic benefit of one company controlling the UI technology is that there should be a unified vision. Microsoft is a large company with a lot of history, has not met ideal expectations. Hopefully, WinUI is that unification.
I’m not sure how to interpret the lack of commits on WinUI and Windows App SDK GitHub repos. Another UI, similar but non-Microsoft UI project, is Avalonia UI. Both WinUI and Avalonia started the roughly at the same time but Avalonia has 26k commits while WinUI and Windows App SDK combined have less than 4k. Maybe the work is occuring outside the repos in other projects.
Regardless of what happens, it seems that different approaches seem to be converging (e.g., XAML for UI, Windows Runtime to interface with the OS, COM under-the-hood) as survival of the fittest ideas.
Which UI framework to use?
-
For new Windows desktop applications:
- WinUI for line-of-business applications
- WPF for mature UI API and XAML UI designer
-
For new Windows desktop applications for Microsoft Store:
- WinUI
-
For already developed applications:
- port to WinUI if the project is small
- WPF and WinForms - XAML Islands for maintaining and modernizing large legacy applications
-
For Mult-platform apps
- Microsoft’s .NET MAUI
- Avalonia
-
Developing your own game:
- Unity or Unreal
-
Developing your own game engine in Windows:
- Win32 or WinUI. Most of the code will be in DirectX anyways
- Win32 with ImGUI
-
Windows Internals Part 1 (7th Edition) by Yosifovich, Ionescu, Russinovich, Solomon ↩︎ ↩︎ ↩︎
-
Essential COM by Don Box ↩︎
-
Introduction to C++WinRT - UWP applications Microsoft Learn ↩︎
-
What’s a Universal Windows Platform (UWP) app - UWP applications Microsoft Learn ↩︎
-
What’s supported when migrating from UWP to WinUI 3 - Windows apps Microsoft Learn ↩︎
-
GitHub - dotnetwpf WPF is a .NET Core UI framework for building Windows desktop applications. ↩︎
-
GitHub - dotnetwinforms Windows Forms is a .NET UI framework for building Windows desktop applications. ↩︎
-
Developing for Windows with the Windows App SDK · microsoftWindowsAppSDK · Discussion #1615 · GitHub ↩︎