im developing a WPF application targeting .NET Framework 4.7.1. I disabled dpi scaling for the main window by applying a scale transform to the main window (see attached property code below).
This works well for the main window but it does not work for any other windows created by the application (like ContextMenus or other Popups). I tried all answers from this question to disable DPI awareness for the application:
- Added the
[assembly: System.Windows.Media.DisableDpiAwareness]
attribute. - Created an
app.manifest
file and disabled dpi scaling in there. - Changed the compatibility settings of the executable to disable dpi scaling.
but none of them worked for me.
The only solution I can think of is to apply the trick with the LayoutTransfrom to the popup window as well. To do that, I tried the following:
I created an attached property that applies the layout transform to a given window:
public class DPIScalingBehavior
{
private class Win32
{
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
VERTRES = 10,
LOGPIXELSX = 88,
LOGPIXELSY = 90,
DESKTOPVERTRES = 117,
}
}
public static readonly DependencyProperty DisableDPIScalingProperty =
DependencyProperty.RegisterAttached(
"DisableDPIScaling",
typeof(bool),
typeof(Window),
new PropertyMetadata(false, OnDisableDpiScalingChanged));
public static void SetDisableDPIScaling(DependencyObject dpo, bool disableDPIScaling)
{
dpo.SetValue(DisableDPIScalingProperty, disableDPIScaling);
}
public static bool GetDisableDPIScaling(DependencyObject window)
{
return (bool)window.GetValue(DisableDPIScalingProperty);
}
private static void OnDisableDpiScalingChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs args)
{
var disableDPIScaling = (bool)args.NewValue;
if (disableDPIScaling)
{
var window = dpo as Window;
if (window != null)
{
var scaleFactor = GetDPIScaleFactor();
var scaleTransform = new ScaleTransform(scaleFactor, scaleFactor);
window.SetValue(Window.LayoutTransformProperty, scaleTransform);
}
}
}
private static double GetDPIScaleFactor()
{
// Monitor DPI
var g = Graphics.FromHwnd(IntPtr.Zero);
var desktop = g.GetHdc();
// System Settings DPI
var Xdpi = Win32.GetDeviceCaps(desktop, (int)Win32.DeviceCap.LOGPIXELSX);
return 96d / Xdpi; // 1.25 = 125%
}
}
Then i created an implicit style in App.xaml
that sets this attached property.
<Style TargetType="Window">
<Setter Property="b:DPIScalingBehavior.DisableDPIScaling" Value="True" />
</Style>
But the style does not get picked up by the popup windows.
Do you have an idea how to disable dpi scaling for a WPF ContextMenu?