简体   繁体   中英

Is there a way in Windows that can get the correct rectangle for the foreground application with DPI awareness?

Hi all I am working on a project to track the location of the current active window user is working on. It works great on single display or displays with uniform DPI settings. But it doesn't work on monitors with different DPIs/scale factors.

The phenomenon is that the application, which written in WinForms, is able to get the correct rectangle for the windows on the same screen as the application locates. It can't get the correct one for other applications.

The method I used is https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowrect to get the rectangle by handle.

The .NET Framework version I used to build is 4.7

I have already set DPI awareness in app.manifest like this, and used

[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>

Here I provide an example. Let's say there are only two monitors, first one with DPI 100%, the second with DPI 150%. The application is on the monitor with 100% DPI. For the windows on the 100% DPI monitor, the coordinates on foreground application rectangle is correct.

But for the windows on the 150% DPI, it won't give me the correct one, the coordinates I see is looking something like the application calculate the coordinates in 100%, the same as the screen application locates is using.

"per monitor DPI awareness" is introduced in Windows 8.1, if your windows version is older than 8.1, then you have nothing to do with that.

If windows version >=8, then according to the document , <dpiAware>true</dpiAware> only set the value of PROCESS_SYSTEM_DPI_AWARE in your application. To enable PROCESS_PER_MONITOR_DPI_AWARE : <dpiAware>true/PM</dpiAware>

And other reference: High DPI support in Windows Forms

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM