Eh, WinForms did a lot to make Win32 UI accessible and usable -- especially layout and easy customization -- but I have to differ on the cross-language story. It was great, IF you were making primarily a C# program that happened to use some C/C++ components.
From the native code side, it was not so great. The .NET 2.0 CLR had very poor support for hosting from the native side and really wanted you to make a program that was .NET first, it didn't work well if you wanted something like primarily a C++ program that hosted a C# UI in the same process. Reverse P/Invoke via native exports wasn't exposed, so creating DLLs for consumption by non-.NET programs was difficult. Mixed mode debugging was and still is painful, with the debugger being glacially slow at some operations like OutputDebugString() processing and blocking some native features like data breakpoints, and the CLR eating access violation exceptions from native code so they couldn't be debugged properly. Build-mode wise, we had to ban C++/CLI assemblies depending on C# assemblies because the C# project system didn't handle incremental builds properly and forced the dependent C++ assembly to rebuild all the time.
These issues still largely exist and are an issue with WPF. It's a great UI framework, but it's unusable unless your front end is primarily a C# program.
WPF originally had two major rendering issues. One was the lack of pixel snapping support, and another was gamma correction issues during text rendering, particularly for light text on a dark background (due to an alpha correction approximation, IIRC). The two combined led to blurry text in WPF applications.
These were finally improved for WPF 4, since Visual Studio 2010 switched to it and had a near riot in the betas due to the poor rendering in the text editor.
The main reason Win32 can't handle automatic background suspension or low-power push notifications is simply that those features haven't been exposed to it. There's nothing preventing a Win32 program from receiving those types of notifications and then being force-ended by the OS if it doesn't respond in time.
When I first started porting programs to Windows ARM64, I didn't have an ARM64 device and had to test in QEMU. It ran extremely slowly, probably 1/50th of real time. All UWP programs like Calculator ran like a slug. But which programs still ran reasonably? Classic WinDbg and Task Manager. Two programs that were still plain Win32.
There are significant issues with Win32, namely its lack of a permissions and isolation and lack of hardware acceleration in the old windowing UI (User/GDI). But the idea that Win32 is inherently power inefficient is, IMO, just BS. Its roots go back to CPUs that were orders of magnitude slower than modern CPUs and there is nothing difficult about making a Win32 program that idles at 0% CPU when not in use.
The most offensive part of the Sinofsky response is this part:
> WinRT (2012) - it (or the embodiment in Windows 8) failed in the market but it also showed both the problem and potential solution to building for new markets while respecting the past
I can't express how wrong this is. WinRT was the most destructive thing that the Windows team ever did to the OS. It drove a hard stake into Windows, splitting it in half and declaring that anything previous to Windows 8, oriented toward desktop, or using primary input through mouse and keyboard over touch was dead. Microsoft basically told all existing Windows developers that if they weren't building a new, touch-oriented, mobile-style app specifically for Windows 8, they didn't matter and wouldn't get any support whatsoever, which is exactly what happened every time they broke existing desktop functionality. Calling this "respecting the past" is a crass insult and taking no responsibility for damaging the Windows development experience and accelerating development away from native Windows apps.
I think for Sinofsky the "respecting the past" refers more to WinRT was/is still just Spicy COM under the hood. Most of the article as I read it is about how .NET was a mistake for Windows UI development and a return to (Spicy) COM its savior.
That might have been more significant had the Windows Runtime not been effectively locked off to Metro-style apps. You could technically use it from a desktop app, but almost all of its functionality was only allowed within a Metro-style app, often due to requiring a core window or package identity. Even today the vast majority of useful WinRT APIs, including the entire UI system, require UWP or package identity.
Package Identity isn't that different from Signed COM Registration of the ancient past. Microsoft built up a lot of dislike from it by building it "sandbox-first", but the core of it still isn't that different from COM's ancient footpaths, at least to the COM diehards that hate .NET and didn't learn near enough from .NET's battles with the same things in terms of package signing, CAS (Code Access Security), and the GAC (Global Assembly Cache).
"Sandbox-first" even made some sense as a direction to work because it is harder to add a sandbox after the fact than to start with one, which is one of the core lessons learned from XP trying to sandbox some of the insecurities in Win32 and getting caught in a lot of complications. (The "sandbox-first" of UWP wasn't even that different under the hood from the XP "sandbox" of Folder/Registry Redirection, just a little better hardened.) Microsoft needed a lot better messaging up front if they had expected to allow more apps to leave the sandbox eventually. But Microsoft probably did believe the UWP sandbox was a better and safer experience for consumers.
But yeah, what's left of Package Identity outside of the sandbox feels like it includes several classic mistakes from .NET's CAS/GAC era, and also seems to point out that Sinofsky was wrong about WinRT "respecting the past" when it failed to learn from that era because it didn't trust .NET's history.
One significant difference is that Metro/UWP requires signing for pretty much everything. Without signing you can't have package identity, and without package identity, you can't even use the UI system. Furthermore, it requires a paid cert, which is expensive and requires publicly divulging your identity. I have major problems with this as it opens developers up to harassment. .NET at least allowed self-signed certs.
It's true that there is no great answer for how to add capabilities and sandboxing after the fact. But what Windows did was build an incredibly restrictive sandbox and then tell everyone who couldn't accommodate even one of the restrictions was "sucks to be you". The result was that developers, when confronted with "all or nothing" for Metro-style apps, were forced to choose nothing. It was also not a good look that Microsoft's own flagship applications like Visual Studio and Office did not show any progress toward adopting UWP, and in the latter case, was specifically exempted from the Windows RT restrictions to continue using Win32 on that platform.
If there had been a better strategy for easing in UWP technology, we might have seen better progress on adoption of Windows Runtime APIs and capabilities so new programs could gradually move toward the new technologies and away from HWNDs. Unfortunately, the technical barriers that were put in place between Win32 and UWP are so large that progress toward breaking them down in the Windows App SDK has been slow.
There are still some things that are still locked in the UWP world that I wish were not.
For example, Windows classic desktop apps still have no equivalent to the UWP app lifecycle. Your UWP app's processes can be suspended and resumed without you writing code to force the suspension and request when to be resumed later. Instead, you are expected to appropriately handle event notifications for suspend, resume, and the app entering and leaving background state.
This system-managed UWP app lifecycle makes life harder for UWP app authors, but I think the net win for battery life is much better for the user experience, which is why mobile apps operate the same way. Yet the docs for the Windows App SDK, which is supposed to bring the best of the UWP to desktop apps, explicitly say that WinAppSDK apps control their lifecycle just like other desktop apps, and the only power friendliness in the WinAppSDK API is voluntary (aka no one will use it). [1, 2]
I'll probably write more soon in response to other parts of the original link's comment thread. Overall, I feel like UWP is being unfairly maligned here, and that while its introduction was unforgivably arrogant, Steven Sinofsky is also right that it was daring and necessary to fix the mistakes and outdated decisions of 16-bit Windows and Win32.
Those are some good points, and I especially loved that lifecycle management in the era where I used a lot of Windows 8 apps. Even on a Desktop with apps filling up my screen still seeing some of them pinned to 0% CPU most of the time (while I'm multi-tasking) in Task Manager was a delightful magic. I also agree that was one of the best parts of the UWP sandbox and one of the biggest shames when Microsoft had to figure out how to allow sandbox breaks that they couldn't find a way to make the lifecycle and other smarts parts of the sandbox more opt-out by default rather than "opt back into the full sandbox". Of course needing to opt-out by default was one of the reasons developers hated the sandbox in the first place. It's a marketing challenge no matter how you slice it.
That relates to some of my criticism that maybe UWP could have used more .NET veterans because that was one of the problems with the CAS sandbox. For the most part the CAS sandbox was "opt-in" and yeah software developers through ego, hubris, and everything else will most often declare "my app/library is a special snowflake and needs access to everything!" So even if things opt-in to additional security controls like CAS, no one tests or builds for Production in a CAS sandbox so even things that claimed to support CAS threw runtime exceptions all over the place to the point no one could trust CAS to the point were CAS died for being practically useless overhead because no one both opted in and knew how to test it.
UWP had a lot of good ideas. It's insistence that it didn't have much to learn from .NET's mistakes was not one of them.
The place I work at tried using an SO enterprise instance and it was quite ineffective. We didn't have the toxicity of the public instance, but generally having a Q&A forum double as a knowledge base is an oddball format that doesn't work out. Adding AI integration is not likely to compensate for that.
The Windows API uses WCHAR = wchar_t, so if you use char16_t, you have to convert back and forth to avoid running afoul of strict aliasing rules. This imposes conversion costs without benefits; both using wchar_t directly or converting to/from UTF-8 are better.
Doesn't need to be inline assembly, just pre-encoded lookup tables and intrinsics-based vectorized CRC alone will add quite a lot of code. Most multi-platform CRC algorithms tend to have at least a few paths for byte/word/dword at a time, hardware CRC, and hardware GF(2) multiply. It's not really extreme optimization, just better algorithms to match better hardware capabilities.
The Huffman decoding implementation is also bigger in production implementations for both speed and error checking. Two Huffman trees need to be exactly complete except in the special case of a single code, and in most cases they are flattened to two-level tables for speed (though the latest desktop CPUs have enough L1 cache to use single-level).
Finally, the LZ copy typically has special cases added for using wider than byte copies for non-overlapping, non-wrapping runs. This is a significant decoding speed optimization.
The main thing that's hard going down this route is dark mode support. The Win32 USER and common controls just don't not support dark mode, but are actively hostile to it due to the amount of hardcoded light colors and backgrounds in the system. All of the system colors are light regardless of the dark/light system setting, highlights are hardcoded to light blue, disabled controls use a hardcoded color, half of the window messages for changing control colors are silently ignored with theming is enabled. Menus are among the more difficult to deal with as they require extensive owner draw.
On top of this, there are a small handful of system UIs that do support dark mode and make your program look inconsistent with dark mode regardless. Message boxes will switch to dark mode, and so will file dialogs -- which is a problem if you've used the Vista-style customization, as any syslinks will appear in a color of blue that's hard to read against the dark mode background.
First, dark mode is for people who set their screen brightness too high.
Second, win32 is designed with the ability to change all the default colors and you used to be able to do this by right clicking the desktop and selecting "properties". If dark mode doesn't follow this - just another symptom of Microsoft's siloing incompetence. The team that wrote dark mode may not have been aware that this feature existed because parts of the platform are so disconnected from other parts.
Dark mode for apps is a setting in the OS and a general expectation now, it's suboptimal to ship a new UI that doesn't support it. And, again, Win32 message boxes in your program will switch to dark mode whether you want them to or not.
Win32 controls ignoring system colors goes much farther back than dark mode being introduced in Windows 10. The theming engine that broke a lot of that functionality was introduced in Windows XP. Beyond that, there were always a few hardcoded colors like disabled gray text going back to Windows 95.
Dark mode ignoring Win32 system colors is not incompetence. It was _intentional_. Dark mode was introduced by the UWP side, which intentionally did not extend it to Win32. To this day, there is not even a Win32 API for desktop apps to query whether dark mode is even enabled. The official recommendation is to compute the luminance of the UWP foreground color setting:
But they had dark themes for the XP theming engine, e.g. the Zune theme, didn't they? They could make the dark mode switch to a dark theme for XP-style themed controls and configure dark colors for the Win32 system colors.
Yes, and this is also how Windows 10/11 explorer turns some parts of its UI dark like scrollbars. But notably, Microsoft refuses to officially support Explorer's dark control themes or ship a complete dark theme, and because the theming engine only loads themes signed by Microsoft, no one else can ship one either without patching the OS.
Only a very small minority of users actually care about dark mode. It is not a general expectation for software, as loud as those users may be on forums like this one.
Mobile is different from desktop. Dark mode became popular with OLED panels because on those it saves battery, and blacks actually look nice, compared to the average LCD. I use dark mode on mobile but light mode on desktop.
I'm not sure how much Android use generalizes - I prefer light mode, but I'll use dark mode for the battery savings on portable devices with OLED screens.
> First, dark mode is for people who set their screen brightness too high.
Not at all. It became popular mainly because as part of the spread of the flat UI epidemic, the previously non-optional “light mode” OS UI themes all shifted away from midtone colors to blinding stark whites. This meant that monitor brightness settings that had previously been comfortable suddenly weren’t.
On top of this, modern flat UI light mode themes consistently have poorer contrast and delineation than their dark mode counterparts, because higher contrast with darker grays makes flat white UI themes appear “dirty”. So even if the brightness isn’t an issue, your eyes have fewer visual cues to guide them.
Aside from that, on IPS panel monitors lowering brightness past a certain point also greatly lowers color vividness which looks bad, which is why some of us like to keep it maybe not maxed but a bit higher than is comfortable with light mode.
It is not. I have some issues with my eyesight and dark mode makes it easier to use a computer in some lighting conditions. So for me dark mode is an accessibility feature. And yes you could use the ugly recolor feature windows has but dark mode does the same thing and looks better most of the time cause a UI designer actually looked at it.
> dark mode is for people who set their screen brightness too high
There can be other valid perspectives than your own.
I don't think your brightness sentiment is universally shared by most people, hence the downvotes. I think this comes from one particular study that people just end up parroting, possibly via third-hand gossip.
While a sufficiently low-brightness screen might have some specific advantages to dark mode, I think the issue is more nuanced than that.
First, not everyone can set their brightness to an appropriate level.
If the user is prone to migraines or light sensitivity, light mode even at a low setting could trigger headaches.
Light mode also produces significantly more blue light, which can have health side-effects as well.
If you keep a white screen on at appropriately low brightness in a dark room, the relative difference between the screen and the surroundings is still massive. This creates pupil strain as the eye constantly adjusts. Dark mode aligns the screen's luminance closer to the room's, reducing this strain.
Dark backgrounds make colors pop more vibrantly and prevent the "washed-out" look that can happen when bright images sit on a white background. It can also reduce halos visible around bright objects in photography apps and make the UI less distracting.
For battery-powered/mobile devices, dark mode uses much less battery power on OLED screens.
Or, unless they've changed it, hardware accelerated rendering. Winforms was based on System.Drawing, which used GDI+, which was largely software rendering. This was confusing because GDI+ was not really related to GDI, which had and still does retain some hardware acceleration support. Even basic color fills start becoming an issue with a big window/monitor.
Winforms is also .NET based, so it's inaccessible if you don't want to write your UI in and take a dependency on .NET.
From the native code side, it was not so great. The .NET 2.0 CLR had very poor support for hosting from the native side and really wanted you to make a program that was .NET first, it didn't work well if you wanted something like primarily a C++ program that hosted a C# UI in the same process. Reverse P/Invoke via native exports wasn't exposed, so creating DLLs for consumption by non-.NET programs was difficult. Mixed mode debugging was and still is painful, with the debugger being glacially slow at some operations like OutputDebugString() processing and blocking some native features like data breakpoints, and the CLR eating access violation exceptions from native code so they couldn't be debugged properly. Build-mode wise, we had to ban C++/CLI assemblies depending on C# assemblies because the C# project system didn't handle incremental builds properly and forced the dependent C++ assembly to rebuild all the time.
These issues still largely exist and are an issue with WPF. It's a great UI framework, but it's unusable unless your front end is primarily a C# program.
reply