C# Scaling UserControl content to match users Dpi/

2019-01-14 13:47发布

How do I get my OwnerDrawn UserControl to respect the users dpi (96/120/xxx) and/or font-size (normal, large, extra large)?

Some people suggest to use the DpiX and DpiY properties on a Graphics object, but that doesn't seem to to anything in my control (i.e. they are always set to 96, regardless of which font-size or dpi I choose).

There is another similar question here on StackOverflow where it suggests to use the AutoScale properties, but the suggested solutions don't really do anything either.

Is there no way of doing this in .NET except for relying on WPF?

2条回答
叛逆
2楼-- · 2019-01-14 14:28

You would need to set the AutoScaleMode property of the UserControl to AutoScaleMode.Dpi, and not set the AutoScale property to true. If you do, it will reset the AutoScaleMode back to None. The AutoScale property is obsolete and is there only for backwards compatibility (see the Important Note in this MSDN article).

Also, in Windows Vista/7, unless you explicitly specify that your application is DPI-aware, Windows will emulate a default DPI environment so that your application renders with 96 DPI, then scale the resulting bitmap to the appropriate size. To avoid that, you can alter your application manifest to inform Windows that you are in fact DPI aware - see the Using manifest to declare DPI awareness section in this article.

查看更多
你好瞎i
3楼-- · 2019-01-14 14:28

I have the same problem, I tried using GetDC + GetDeviceCaps + ReleaseDC, except using Graphics worked, atleast on Vista32. I am not experienced with DPI yet, but nobody had answered this and at least this might be helpful for others.

Check out Creating a DPI-Aware Application. This mention why it might always return 96 regardless of actual DPI setting.

Quote from above link:

DPI scaling in a Win32 application

In Win32 applications, do the following:

  • Use the SetProcessDPIAware function to cancel dpi scaling.
  • When sizing drawn interface elements, use physical measurements, such as centimeters. By using physical dimensions rather than pixels, you ensure consistent sizing on all types of displays.
  • To get the system dpi setting, use the CDC::GetDeviceCaps function with the LOGPIXELSX flag. If you do not cancel dpi scaling, this call returns the default value of 96 dpi.
  • Use the GetSystemMetrics function to get preferred sizes of user interface elements, such as window borders. When dpi scaling is disabled, the measurement values that are returned for interface elements are scaled to the selected dpi setting. If dpi scaling is active, the function returns measurements based on 96 dpi, regardless of the system dpi setting.

Answered from: About DPI Issue

Sample code rewritten with using-statement (original source):

float dpiX = 96, dpiY = 96;
using(Graphics graphics = this.CreateGraphics())
{
    dpiX = graphics.DpiX;
    dpiY = graphics.DpiY;
}
查看更多
登录 后发表回答