Windows中是否可以通过DPI感知为前景应用程序获取正确的矩形?

时间:2019-06-10 18:20:05

标签: c# wpf winforms winapi

您好,我正在做一个项目,以跟踪当前活动窗口用户正在处理的位置。它在单个显示器或具有统一DPI设置的显示器上都非常有效。但不适用于具有不同DPI /比例因子的显示器。

这种现象是,用WinForms编写的应用程序能够获取与应用程序位于同一屏幕上的窗口的正确矩形。它不能为其他应用程序提供正确的解决方案。

我使用的方法是https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowrect通过句柄获取矩形。

我以前构建的.NET Framework版本是4.7

我已经在app.manifest中设置了DPI感知,并使用

[DllImport("user32.dll"]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[DllImport("user32.dll"]
public static extern bool SetProcessDPIAware();
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <appSettings>
    <add key="ClientSettingsProvider.ServiceUri" value="" />
  </appSettings>
  <System.Windows.Forms.ApplicationConfigurationSection>
    <add key="DpiAwareness" value="PerMonitorV2" />
  </System.Windows.Forms.ApplicationConfigurationSection>
  <system.web>
    <membership defaultProvider="ClientAuthenticationMembershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
      </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
      <providers>
        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
      </providers>
    </roleManager>
  </system.web>
</configuration>

在此提供示例。假设只有两台显示器,第一台DPI为100%,第二台DPI为150%。该应用程序在具有100%DPI的监视器上。对于100%DPI监视器上的窗口,前景应用程序矩形上的坐标正确。

但是对于150%DPI上的窗口,它不会给我正确的窗口,我看到的坐标看起来像是应用程序以100%计算坐标,这与屏幕应用程序所使用的相同。

1 个答案:

答案 0 :(得分:0)

Windows 8.1中引入了“每监视器DPI感知”,如果Windows版本早于8.1,则与此无关。

如果Windows版本> = 8,则根据document<dpiAware>true</dpiAware>仅在应用程序中设置PROCESS_SYSTEM_DPI_AWARE的值。要启用PROCESS_PER_MONITOR_DPI_AWARE<dpiAware>true/PM</dpiAware>

和其他参考文献:High DPI support in Windows Forms