Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GetClientRect returns scaled dimensions?

I'm calling GetClientRect via pinvoke in C# to get dimensions of a panel (on WindowsForm) I'm using as DirectX render target area. I would've thought that WinAPI gives me the unscaled (i.e. returned values should be the same regardless of Windows display DPI settings) dimensions, but it appears to give me the scaled one instead (at least on Windows 8.1 as I have not tested it on other OSes).

The ClientRectangle property also returns the same scaled dimensions as GetClientRect. This remains the same when I've changed the form AutoScaleMode to none.

Is that the expected behavior with GetClientRect? If so, how do I get the unscaled dimensions?

EDIT: This only affects Windows 8.1. Tested it on Windows 7 and GetClientRect returns the unscaled dimensions!

like image 990
Zach Saw Avatar asked Oct 20 '22 03:10

Zach Saw


1 Answers

There's no advantage to P/Invoking GetClientRect. You get exactly the same thing by querying the ClientRectangle property.

And yes, either one of those is going to return the size of the client area in physical pixels, which is apparently not what you want.

You are probably looking for the ID2D1RenderTarget::GetSize method, which returns the size of the render target in device-independent pixels (DIPs).

If you must convert physical pixels (e.g., from mouse events) then you can use something like ID2D1Factory::GetDesktopDpi to get the current scaling factors, which you can use to convert physical pixels into DIPs.

The reason you're seeing different behavior in Windows 8.1 is probably the result of changes to the way it handles DPI scaling. You may find that indicating your application is DPI-aware is an easier solution than futzing with the above. That will stop the UI from being automatically scaled to match the current DPI settings. You do this by adding the following to the application's manifest:

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

From Visual Studio, right-click on the project and click "Add" -> "New Item". Choose the "Application Manifest File" and add the above code.

Related reading: Writing DPI-Aware Desktop and Win32 Applications

like image 130
Cody Gray Avatar answered Oct 24 '22 02:10

Cody Gray