7

I need to find out if the user's screen is set to normal 96 dpi (small size), large 120 dpi fonts, or something else. How do I do that in VB.NET (preferred) or C#?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Didier Levy
  • 3,393
  • 9
  • 35
  • 57
  • A native way (written in Delphi but only using the native Windows API): `var dc: HDC; res: integer; begin dc := GetDC(0); if dc <> 0 then try res := GetDeviceCaps(dc, LOGPIXELSX); finally ReleaseDC(0, dc) end;` – Andreas Rejbrand May 21 '11 at 15:46
  • As Andreas suggests, you can also call the Windows API functions `GetDC` and `GetDeviceCaps` in order to get this information, but you'll have to use P/Invoke to get at them from a .NET application, and there's little benefit in doing so since the `Graphics` class has already wrapped this up so nicely in managed code. – Cody Gray - on strike May 21 '11 at 15:53
  • 1
    But anyway, **thanks for [paying your taxes](http://blogs.msdn.com/b/oldnewthing/archive/2004/07/14/182971.aspx)**!! – Cody Gray - on strike May 21 '11 at 15:54

2 Answers2

13

The best way is just to let the form resize itself automatically, based on the user's current DPI settings. To make it do that, just set the AutoScaleMode property to AutoScaleMode.Dpi and enable the AutoSize property. You can do this either from the Properties Window in the designer or though code:

Public Sub New()
    InitializeComponent()

    Me.AutoScaleMode = AutoScaleMode.Dpi
    Me.AutoSize = True
End Sub

Or, if you need to know this information while drawing (such as in the Paint event handler method), you can extract the information from the DpiX and DpiY properties of the Graphics class instance.

Private Sub myControl_Paint(ByVal sender As Object, ByVal e As PaintEventArgs)
    Dim dpiX As Single = e.Graphics.DpiX
    Dim dpiY As Single = e.Graphics.DpiY

    ' Do your drawing here
    ' ...
End Sub

Finally, if you need to determine the DPI level on-the-fly, you will have to create a temporary instance of the Graphics class for your form, and check the DpiX and DpiY properties, as shown above. The CreateGraphics method of the form class makes this very easy to do; just ensure that you wrap the creation of this object in a Using statement to avoid memory leaks. Sample code:

Dim dpiX As Single
Dim dpiY As Single

Using g As Graphics = myForm.CreateGraphics()
    dpiX = g.DpiX
    dpiY = g.DpiY
End Using
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Hi, and thanks! But does the dpi relates to the screen size (X / Y) or the font size (X only available) ? In other words, can I be certain that dpiX = dpiY in all cases? Otherwise, the new font would look stretched, wouldn't it? – Didier Levy May 22 '11 at 12:15
  • @Didier: Yes, normally dpiX will be equivalent to dpiY. If not, it would look stretched. It would depend on the resolution and the user's chosen DPI settings. The default small settings have dpiX = 96 and dpiY = 96. The default large settings have dpiX = 120 and dpiY = 120. You might check out [this MSDN page](http://msdn.microsoft.com/en-us/library/dd464646.aspx) on high-DPI applications. The linked [how-to page](http://msdn.microsoft.com/en-us/library/dd464660.aspx) is excellent. – Cody Gray - on strike May 22 '11 at 13:16
4

Have a look at the DpiX and DpiY properties. For example:

using (Graphics gfx = form.CreateGraphics())
{
    userDPI = (int)gfx.DpiX;
}

In VB:

Using gfx As Graphics = form.CreateGraphics()
    userDPI = CInt(gfx.DpiX)
End Using
keyboardP
  • 68,824
  • 13
  • 156
  • 205