Question

In my application, I get the screen resolution with this code:

SystemInformation.PrimaryMonitorSize

And I get the DPI with this code:

    using (Graphics g = Graphics.FromHdc(NativeMethods.GetDC(IntPtr.Zero)))
    {
        dpiX = g.DpiX;
        dpiY = g.DpiY; 
    }

This works fine in most situations. But when the code runs on a Vista machine with Aero turned on, and the user has set the monitor to use a high DPI, bizarre results come back.

Lets say the user has set the machine to run at 1024 x 768 and has the DPI at 144, the code above will return a resolution of 683 x 512 and a DPI of 96.

However, if Aero is turned off, the results come back as I would expect them. What is Aero doing and how can I get the true resolution and DPI?

Was it helpful?

Solution

You need to declare your application as DPI-aware, either in the manifest (preferred), or by using SetProcessDPIAware Win32 API function. Because so many applications are not written properly, Vista added "DPI virtualization", which lets applications pretend that they're working with a "standard" 96dpi screen, and then does the scaling itself - DWM, being a compositing window manager, can do the scaling. If your application handles varying DPI properly, you have to say so explicitly.

On a side note, you shouldn't muck with HWND_DESKTOP (which is what (HWND)0 is). When compositing ("Aero") is off, it does indeed represent the physical screen, so if you get its DC and draw on it, you draw directly into the framebuffer. With a compositing window manager, this is impossible by definition. I'm not sure if this affects DPI measurement, but it might be a better idea to use the DC for your application window instead anyway - it won't hurt/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top