However (you know this is coming), look at your task manager, easy task comes with large memory consumption, especially for 4K transparent window. 100+ MB ram are wasted for just showing an empty, transparent window! That’s unacceptable. A year ago, you might be right saying “Who cares about RAM, they are cheap as hell”, but check out the price they’ve grown over this year, they are expensive as hell now.
Fun fact of WPF transparent window
RAM usage increase as window size enlarge
Win32 window has no such problem
Wait, what? The larger the window is, the more RAM it consumes? Hmmmmm… this looks familiar, just like a Bitmap. For now, we don’t know how WPF handles transparent window, but the symptom shows that it’s like using the whole screen as a bitmap and the window updating itself with portion of that bitmap, making it “transparent”. What a smart move… Back in the days when WPF was first released, low screen resolution was the main stream. Even today, most laptops still are shipping with a monitor of 1366*768 (ridiculous, right?). Let’s despite the nonsense the OEM told us and think about program running in computers with higher screen resolution.
RAM is not free, do not waste it
Obviously, costing 100+ mb of ram for showing a transparent window in 4K is unacceptable, especially compared with Win32 transparent window, which costs only 10+ mb. The gap between them makes WPF look dump. Enough complaining, what can we do about it? I don’t want to write UI code with GDI using C++, that’s inefficient and not modern, plus, no one would abandon their beautiful, easy to maintain xaml UI code for this.
Hosting WPF content in Win32 Window
Well, indeed, no one would rewrite their UI code for just about 90mb of RAM. Compared with the work needed to rewrite C++ UI code, the RAM consumption gap seems acceptable (#smile face). But please remember, we can always host WPF content in win32 window. Let say, we want to create a full screen notification dialog with semi-transparent background and apaque notication content in the center. To avoid the WPF ram problem, we create a semi-transparent window using win32:
WPF does not register to these messages on the applications MainWindow, but through a hidden windows named “SystemResources…” which is created for each application instance. So handling those messages on the MainWindow (which would be easy) does not help here.
public staticvoid HandleDeviceChangedWM()
// hook into internal class SystemResources to keep it from updating the TabletDevices on system events
object hwndWrapper = GetSystemResourcesHwnd();
if (hwndWrapper != null)
// invoke hwndWrapper.AddHook( .. our method ..)
var internalHwndWrapperType = hwndWrapper.GetType();
// if the delegate is already set, we have already added the hook.
if (_handleAndHideMessageDelegate == null)
// create the internal delegate that will hook into the window messages
// need to hold a reference to that one, because internally the delegate is stored through a WeakReference object
var internalHwndWrapperHookDelegate = internalHwndWrapperType.Assembly.GetType("MS.Win32.HwndWrapperHook");
var handleAndHideMessagesHandle = typeof(WPFTouchUtil).GetMethod(nameof(HandleAndHideMessages), BindingFlags.Static | BindingFlags.NonPublic);
WPF has an extensible pixel shader API, along with some build in effects. This allows developers to really add some very unique effects to their UI. In Direct3D when you apply a shader to an existing texture, it’s very typical to use an intermediate rendertarget…after all you can’t sample from a texture you are writing to! WPF does this also, but unfortunately it will create a totally new texture EACH FRAME and destroy it when it’s done. Creating and destroying GPU resources is one of the slowest things you can do on a per frame basis. I wouldn’t even typically do this with system memory allocations of that size. There would be a considerable performance increase on the use of shaders if somehow these intermediate surfaces can be reused. If you’ve ever wondered why you get noticeable CPU usage with these hardware accelerated shaders, this is why.