Writing GUI apps is painful everywhere, and has been for years.
I remember the half-baked transition from Windows Forms to WPF, which was then taken-over by the Windows Phone initiative, which was also extremely painful and half-baked.
There's a reason electron is so popular, despite all the complaints about it as a platform. Don't blame the electron devs, blame Microsoft for completely failing to support their own platform. That lack of long-term support and consistency extends to a ton of areas in the Windows world, not just GUI development.
The lack of windows support for windows GUI's on windows is mind blowing. I remember absolutely whipping up Visual Basic line of business apps using the form designer in Visual Studio and data bound controls etc. If you wanted more there was MFC (with MTL developed by some insiders I guess at microsoft)
The absolute insanity of going to WPF (wasn't data binding via reflection -> these apps got horribly sluggish!) then to UWP (monster controls for touch I guess?) is honestly mind blowing. The emphasis on Universal Windows Platform as "the future" of app development is absurd. Every time the design language behind this infects another settings app in windows we LOSE functionality! Can you even have more than one settings window open anymore with the new and improved UWP?
Then there is WinUI? Then there is MAUI? THen there is blazor on the desktop?
Has Microsoft confused you yet? They've confused me. Each of these introduced as the best thing since sliced bread, and back with tooling with broken forms designers and more.
The problem with all of these technologies is that they were invented by different divisions of Microsoft to do different things. That, and Microsoft chasing the Next Big Thing.
What we consider to be "Win32 apps" are built with a framework in USER.dll, which is half reimplementation of the classic MacOS Toolbox API and half a pure-C object oriented class system. It's been here since the beginning, and is the lowest common denominator for getting anything on screen. Every other toolkit eventually opens a USER window, attaches the appropriate window class and wndprocs to it, and then yields CPU control to an event loop that, among other things, contains a Windows USER message pump.
USER, being an object-oriented, pure-C[0] API, is infamously verbose to work with. The "200 line Hello World" example everyone passed around back in the 90s is specifically that verbose because of all the bookkeeping you have to do for USER's sake. It is possible to build USER apps that work well, but it puts a lot of onus on the programmer. Even things like high-DPI support[1] or resizable windows are a pain in the ass because they all have to be implemented manually.
Microsoft's original answer for "USER is too hard" was to adopt Visual Basic or MFC as you mentioned. AFAIK .NET WinForms was also a wrapper around USER. This is why Windows had a cohesive visual appearance all the way through to Windows 7, because everything was just developer-friendly wrappers around common controls. Even third-party widget toolkits could incorporate those controls as subwindows as needed[2].
The problem with USER is that it was built for multiple windows and applications that render (using the CPU!) to a shared surface representing the final visible image. Modern toolkits instead have multiple separate surfaces and draw on them as needed before presenting a final image to a compositor that then mixes other windows together to get a final image. Windows Vista onward has the compositor, but the UI toolkits also need to be surface-aware instead of chucking a bunch of subwindows at DWM at the last minute.
WPF is the first attempt at a modern UI toolkit. Relative to USER resources are replaced with XAML and window classes replaced with... well, actual language classes. Except it was developed by the DevTools division (aka DevDiv), and only ran on .NET with managed code. If you had a native application or just didn't want to pay the cost of having a CLR VM, tough.
Then the iPhone launched. And the iPad launched. The thing is, good tablet UI needs GPU-acceleration up and down the stack, so Microsoft shat themselves, gave the Windows division (aka WinDiv) the keys to the castle, and they completely rewrote WPF in C++ with some fancy language projections. That became "Metro" in Windows 8, then "Modern UI" after a trademark dispute. Microsoft wanted Windows 8 to be a tablet OS, damn it, with full-screen only apps and no third-party app distribution.
And then most people just bought Surface tablets, opened the Desktop "app", and used the same USER apps they were used to, complaining about the Start Screen along the way. So Microsoft pivoted back to a normal desktop with Modern UI apps, which are now called UWP apps, and there's a whole bunch of new glue APIs to let you stick XAML subwindows inside of USER or just use UWP outside of AppX packages, which is what Windows 8 should have done, and now everything is just a mess. WinUI 3 is just an upgrade to the XAML library that UWP apps use, but it sounds like Yet Another Toolkit. MAUI is some kind of meta-toolkit like the old AWT on Java.
At some level, I can explain this, but it's not reasonable. There is no "native" UI toolkit or consistent look-and-feel on Windows anymore. I suspect this, more than anything else, is the reason why Windows killed Aero blur-behind everywhere, and why Electron apps are so damned popular now. HTML and CSS are almost as old as USER, but with consistent engineering support and developer experience.
USER is an enhanced clone of the MacOS API, so it's natural to see what Apple did when confronted with the same problems. MacOS didn't have an object system at all, you just threw a bunch of controls onto a list and the system rendered them. That (along with user mode applications) was actually one of the reasons why they bought NeXT. OSX's AppKit toolkit shipped with compatibility bridges for Toolbox apps, but it was still about as advanced as USER was when it came to GPU usage, given that it was built around the same era as Windows, just for beefier hardware.
So what did Apple do? They made AppKit speak layers. They wrote a whole new compositing system called CoreAnimation to do in-process compositing, with all the common controls knowing how to manage it and layer-unaware third-party controls just doing whatever made sense. And this itself was a trojan horse for UIKit: the compositing library had been written to support a touch tablet demo that was later rolled into the Purple project to produce the iPhone. Y'know, the thing that actually kicked Microsoft's ass so much they decided to fracture their development ecosystem into 40 different UI toolkits with confusing names. In comparison, on modern macOS the big split comes from SwiftUI and Catalyst, but those are both wrappers around AppKit controls rather than ground-up rewrites of UI toolkits nobody dares touch.
[0] Or possibly Pascal, given the MacOS heritage
[1] The correct way to do high-DPI is for the windowing toolkit to work exclusively in virtual coordinates. Physical device coordinates and their derivatives should be converted away from at the earliest possible convenience and converted back into as late as possible. At a minimum, no user-facing APIs should use physical coordinates.
USER does not do this, even though there's an option to make it do this, which has worked wonders on every non-DPI-aware app I've thrown at it.
[2] Or, alternatively, implement their own. My favorite story about this is Internet Explorer, which ships with it's own implementations of common controls specifically just so that HTML form elements don't have to hold an HWND each and can share the parent window.
AppX packages got a bad rep as well for a couple of reasons. Lots of new footguns when dealing with them or trying to remove them for imaging / mass deployment scenarios.
The first introduction to AppX was often a metric load of crap on the machine - see below for a sample of the type of AppX stuff that was the first introduction to AppX for some folks which were often low effort marketing type stuff.
> Writing GUI apps is painful everywhere, and has been for years.
Disagree. GUI development on Apple platforms using either UIKit or Appkit is something I've always found expressive, simple, and fun. SwiftUI is a different beast, but to say it's painful everywhere is not accurate.
Windows Forms (C#) is basically a continuation of Visual Basic, it's not very painful at all. The only painful bits are when you need to lock a bitmap and deal with raw pointers, and you need to use the "unsafe" keyword.
To me, Windows Forms is where MS should have stayed. I don't want XAML to compile to C# code, and I don't want to be forced into using their MVVM system. I just want to be able to put boxes on the screen and fill them with text, then handle user interactions with callbacks. Basically, vanilla javascript but in C#
Flutter is actually quite nice and works well on desktop too. If Google continues to develop it I could see it becoming the first choice for a lot of developers.
Oddly AppKit seems to be one of the most stable desktop frameworks I have worked with. They've made breaking changes, sure, but they haven't been rewriting, and rewriting, and rewriting the same stuff for the last decade and a half.
The situation on Windows these days feels like... cognitive dissonance. If given a Windows app assignment today, I'd pick WinForms if less complicated, WPF if a larger project.
I remember the half-baked transition from Windows Forms to WPF, which was then taken-over by the Windows Phone initiative, which was also extremely painful and half-baked.
There's a reason electron is so popular, despite all the complaints about it as a platform. Don't blame the electron devs, blame Microsoft for completely failing to support their own platform. That lack of long-term support and consistency extends to a ton of areas in the Windows world, not just GUI development.