Есть ли способ отключить масштабирование для всех приложений WPF, даже если окна имеют некоторый масштаб на монитор или масштаб всей системы? - PullRequest
0 голосов
/ 05 апреля 2019

Мне нужно иметь окна WPF, которые всегда имеют размер 1: 1 с физическими пикселями (DPI всегда равен 96), и к этому времени я не нашел способа сделать это: манифест приложения или методы API для осведомленности бесполезны, они просто изменение способов масштабирования контента: в виде растрового изображения или в приложении. Мне нужно, чтобы приложение всегда имело фиксированную 100% шкалу, даже если системные настройки составляют 200% на монитор или на всю систему. Ребята, вы знаете, как можно помочь?

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

Для тех, кто будет искать подобное решение:

Я не нашел способа заставить приложение не масштабироваться вместе с операционной системой, но нашел, как сохранить масштаб 1: 1.

Первое, что вам нужно сделать, это определить, что приложение поддерживает dpi, поэтому оно будет масштабироваться не системой, а самим приложением. Вот код app.manifest:

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
    </windowsSettings>
  </application>
</assembly>

Тогда вы сможете получить текущий масштаб для визуала:

double xScale = PresentationSource.FromVisual(someVisual).CompositionTarget.TransformToDevice.M11;
double yScale = PresentationSource.FromVisual(someVisual).CompositionTarget.TransformToDevice.M22;

И затем вы можете привязать преобразование макета к элементу управления (изображение в моем случае), чтобы отменить эффект масштабирования:

<Image.LayoutTransform>
    <ScaleTransform ScaleX="{Binding ElementName=_this, Path=ScaleX}"
                    ScaleY="{Binding ElementName=_this, Path=ScaleY}" />
</Image.LayoutTransform>

Обратите внимание, что пропорции должны быть инвертированы, поэтому ScaleX и ScaleY будут иметь следующие значения:

ScaleX = 1 / scaleX;
ScaleY = 1 / scaleY;
1 голос
/ 07 апреля 2019

Насколько я знаю, вы можете отключить все автоматическое масштабирование, объявив True/PM в манифесте приложения, что означает, что приложение берет на себя полную ответственность за масштабирование, а затем игнорирует сообщение WM_DPICHANGED, когда оно приходит.

<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
  </windowsSettings>
</application>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        var source = PresentationSource.FromVisual(this) as HwndSource;
        source?.AddHook(WndProc);
    }

    private const int WM_DPICHANGED = 0x02E0;

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_DPICHANGED)
        {
            handled = true;
        }
        return IntPtr.Zero;
    }
}

Я не совсем уверен, может ли пользователь изменить это поведение при любых настройках ОС.

...