I have built a WPF application which has a window that can be docked to the edges of the desktop. I use the SHAppBarMessage
WIN32 API to perform the docking functions.
Under Windows 8.1, I've noticed that when docked, the window is only reserving half the width it needs. My code gets the PresentationSource
object from the window being docked and then gets the TransformToDevice Matrix
object:
PresentationSource source = PresentationSource.FromVisual( window );
Matrix TransformToDevice = source.CompositionTarget.TransformToDevice;
I then use the Matrix
to transform the window's ActualHeight
and ActualWidth
to device coordinates before computing the size of the region on the desktop to reserve for the window:
Size windowSize = (Size) source.CompositionTarget.TransformToDevice.Transform( new Vector( appbarWindow.ActualWidth, appbarWindow.ActualHeight ) );
All of this code works as long as the display is in 100% DPI mode, but problems rise when you change the DPI setting. In higher DPI settings ( that is, DPI > 100% ), the area being reserved for the window on the desktop is narrower than the window.
In my debugging, I placed a breakpoint on the line that computes the window size above. I've found that in the 100% DPI setting, the transform Matrix
is the Identity matrix. But after changing the DPI setting, the Matrix
is unchanged!
I thought that this transform matrix would change if the DPI settings changed? If they don't, how do I get a transform that takes the DPI settings into effect? Is there a method that I am supposed to call when the DPI settings change? And if so, how do I get notification of the DPI Setting change? I have code that is called when the SystemEvents.DisplaySettingsChanged
event is raised, and it is getting called when the DPI settings change. But the transforms are always the Identity Matrix
. Shouldn't they change? How do I get the correct transform matrix?
I've found out that the short answer to my question is "no." Windows 8.1 added a new kind of DPI awareness called per-monitor DPI awareness. The WPF code is not per-monitor DPI aware. It turns out you have to handle per-monitor DPI awareness differently from system DPI awareness, which WPF has built-in.