添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Hello,

we have a Host Delphi App, which is compiled with Delphi 10.3.3.
In the manifest we have defined our app to be dpi aware: ‘Per Monitor V2’.
I examine the process using Task Manager, our app has the DPI-Awarness set to ‘Per-Monitor (v2)’.

Also in Delphi, when we move our app to a monitor that uses a different DPI scale the Dpi, the WM_DPICHANGED event is triggered.

WPF also offers a similar event: Window.DpiChanged. If I create a WPF window from within a Hydra .NET plugin and subscribe to this event, the event is never fired. We target .NET 4.8.

Also it seems that the Window/VisualPlugin are always using the DPI of the primary monitor.

For example my primary monitor is scaled at 150%. When I move the plugin to a monitor scaled at 100% (96 dpi), the plugin/window is too big. It remains scaled at 1.5.

We do not call any of the SetProcessDPIAware api’s. We just rely on the manifest.

Do you have any guidance on how to deal with high dpi scenarios for WPF Visual Plugins?

Is there DpiChanged event supposed to be triggered?

Thank you!

.NET Fx documentation is a bit vague (to say the least) on use cases like the one used in Hydra.

How exactly does your manifest look like? Do you load your WPF plugin in the default app domain or in a custom one?

@antonk
Here is the relevant part of our manifest:

 <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
         xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true/PM</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor, System</dpiAwareness>
    </asmv3:windowsSettings>
  </asmv3:application>

We load our plugin in the default app domain.

Also we did test a standalone wpf with our manifest, and it worked as expected. That is why I don’t think that the manifest would have anything to do with it.

Thank you!

Hello

We are investigating is it possible to propagate manifest settings to a child-process like hosted .NET AppDomain.

However there are entries like these ones in the .NET Framework 4.8 Release Notes so it can be even a bug in the .NET Framework itself:

  • Fixed WPF issue of not creating correctly-size rendertarget for mixed-mode child windows. Under certain circumstances, per-monitor DPI aware applications that host WPF based controls or plugins were not rendering the WPF window fully [646801, wpfgfx_v0400.dll, Bug, Build:3646
    *Fixed the issue of WPF Windows not scaling correctly. WPF windows that are parented under native HWND’s, including Windows Forms (using ElementHost), will correctly react to DPI changes and scale themselves appropriately when the dpiAwareness element in the application manifest is updated to “PerMonitorV2” value. [478267, PresentationCore.dll,wpfgfx_v0400.dll, Feature, Build:3673]]
  • When WPF is run in Per-Monitor Aware mode, controls hosted within HwndHost are not sized correctly after DPI changes (for e.g., when moving applications from one monitor to another). This fix ensures that controls hosted so are sized appropriately. On .NET Framework Versions 4.7.2 and older, applications must opt in to enable the fix by setting the AppContext switch ““Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater”” to ““false””. This switch can be set either in the registry or in the application - see the documentation for AppContext (https://msdn.microsoft.com/en-us/library/system.appcontext(v=vs.110).aspx). [646805, PresentationFramework.dll;PresentationCore.dll;WindowsBase.dll, Bug, Build:3673]
  • Hello @antonk,

    have you been able to make some progress?
    Would you mind sharing your findings so far?

    Thank you!

    Hello @antonk, hello @Santiago_Burbano,
    did you found a solution for this? At the moment I have to turn off DIP awareness because it doesn’t work on multiple screens with different dpi scaling. However, this makes the application look very blurry.

    many thanks!!

    Did you try to call the following Win API method in plugin (this is Elements syntax)?

      NativeMethods = static class
      public
        [System.Runtime.InteropServices.DllImport("SHCore.dll", SetLastError := true)]
        class method SetProcessDpiAwareness(awareness: PROCESS_DPI_AWARENESS): Boolean; external;
      PROCESS_DPI_AWARENESS = enum(
        Process_DPI_Unaware = 0,
        Process_System_DPI_Aware = 1,
        Process_Per_Monitor_DPI_Aware = 2
                  

    @antonk

    @lober found the following, from https://github.com/microsoft/WPF-Samples/tree/master/PerMonitorDPI

    WindowsForms Apps (NOT SUPPORTED)

    The scenario where a WindowsForms app hosts WPF via ElementHost does not currently support Per Monitor DPI. We’ll consider doing work in the future here, but it likely will require additional features from the Windows team.

    I do not think it is very likely that Per Monitor DPI support will be added to WindowsForms apps hosting WPF user controls via ElementHost.

    The other option, is that you provide a ‘native’ WPF Visual Plugin implementation that does not requiere the use of WinFroms + ElementHost.

    Then it should work fine, and it will solve so many problems.

    I understand it is convenient to use one implementation to support both WinFrorms and WPF, but unfortunately that prevents WPF user controls from being Per Monitor Dpi Aware.

    Please let me know what your thoughts are.

    Thank you!

    Santiago_Burbano:

    The other option, is that you provide a ‘native’ WPF Visual Plugin implementation that does not requiere the use of WinFroms + ElementHost.

    There is one blocker issue here:
    WPF controls are not ‘real’ controls. For WinAPI they are nothing more than a pictures drawn by WPF.
    This essentially means that they have no Handle. And no Handle means that they cannot be embedded into a host window.
    Thus a wrapper element is required.

    Hello, it is clearly stated in your [read.me ](https://github.com/microsoft/W

    Hello,

    I have uploaded a modified version of the Visualizer Sample Project.

    You will find a Visual Studio solution and a Delphi Project.

    The Delphi Project generates the Delphi Host App.
    This App hosts a WPF Visual Plugin and also a non visual plugin.

    The Visual Studio Solution consists of two projects:

    A class library (Visualizer.dll) which contains the Visual and Non-Visual Plugins as well as a dialog (WndTest) for testing the Window.DpiChanged event.

    A simple WPF Application that references the Visualizer class library. This application only has a button
    monitor.
    This works as expected.

    However if you run the Delphi Host App [VisualizerHost.exe] (which references the same Visualizer.dll) and display the Dpi Changed Test Window, dragging the dialog to another monitor does not trigger the DpiChanged event.
    We do not understand why.
    This also happens if the WPF Dialog is created from within a non-visual plugin.

    DelphiHostApp706×575 57 KB

    The process awarness for the hydra plugins was set to: Process_Per_Monitor_DPI_Aware.

    Delphi WPF.zip (1.2 MB)

    @antonk
    Thanks for the feedback.
    But I am pretty much in the dark. Is this something you will continue looking into?
    Just a guess, maybe having Hydra Binaries that target .NET 4.8 could help?

    We need to develop a few WPF plugins for our Delphi Host App, but at the moment this issue is preventing us from moving forward.

    Santiago_Burbano:

    Just a guess, maybe having Hydra Binaries that target .NET 4.8 could help?

    Check the runtime used by your plugin at runtime. It will be the latest varsion of .NET Framework installed on your host. Thanks to the architecture used by .NET Framework Hydra plugins always use the latest available .NET versions.

    Santiago_Burbano:

    But I am pretty much in the dark. Is this something you will continue looking into?

    Yes. However at the moment we are kind of lost too. This requires way deeper investigation in areas that are not even covered with proper docs. F.e. how exactly WPF application handles the DPI change message sent to it by Windows?
    Note that when plugin asks WinAPI about its DPI support it reports that PerMonitor DPI support is enabled. But somehow this support is not propagated to WPF display system.