0

I have a physical object in the shape of a circle that measures 3 inches in diameter. My application transposes this circle shape onto the screen so the user can visually check off what they see into the application from the circle object. The problem I have is that I need the circle object to be 3 inches in diameter and appear the same size on all monitor types and all resolutions.

Is this possible? I am using WPF and have something like this already:

<Window.Resources>
    <behaviors:InchesToIndependentUnitsConverter x:Key="InchesToDeviceIndependentUnits" />
</Window.Resources>
...
<Ellipse x:Name="MyCircle" Height="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth}" Width="{Binding CircleDiameter, Converter={StaticResource InchesToDeviceIndependentUnits}}" Margin="0,0,0,20" Fill="White"  BorderBrush="Black" BorderThickness="1" VerticalAlignment="Top" HorizontalAlignment="Center"></Ellipse>
...

My inches to DIU converter looks something like this:

public class InchesToIndependentUnitsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)
    {
        int diameterDIU = 0;
        if ((double)value > 0)
        {
            using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
            {
                diameterDIU = (int)((g.DpiX / 96) * value);
            }
        }
        return diameterDIU;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo)
    {
        throw new NotImplementedException();
    }

As expected, this works very well on a say a 1920 x 1200 res monitor, but when I start to get lower, naturally everything looks bigger. I need the diameter of my <Ellipse> tag to always be 3 inches no matter what resolution the person's monitor is.

Thanks!

J-man
  • 1,743
  • 3
  • 26
  • 50
  • I haven’t used the functionality in ages, but I do believe WPF natively supports inches as a size unit. What happens if you simply set your width and height to `3in`? Note that you’ll rarely (if ever) get the size perfect, because the Windows DPI settings seldom reflect the monitor’s _actual_ resolution_. – Mike Strobel Sep 28 '17 at 14:46
  • I got excited when I read your comment because I had no idea WPF had physical UOM like that. I tried it out and it worked great on my 1920x1200 res monitor, but unfortunately didn't equal 3 inches on one with a smaller resolution – J-man Sep 28 '17 at 14:49
  • Like I said, you will rarely, if ever, get an exact match because monitors have long reported 96dpi even when the true pitch is often closer to 120dpi. Unfortunately, there is simply no way to know what the _actual_ physical pixel size is. You can get close, but you will not get exact. The sad state of affairs is that the DPI value Windows reports tends to bear little semblance to reality. – Mike Strobel Sep 28 '17 at 15:08
  • True that. As a kind of work around, I am including a slider control on my WPF window to allow the user to scale the circle to fit what they need for their device's resolution. Like you said, the DPI returned almost is always 96. Debugging I haven't seen anything other than that to this point. I'll keep poking around, but won't waste too much more effort. Thanks @Mike Strobel for your help – J-man Sep 28 '17 at 15:18

1 Answers1

1

I have good news and bad news for you.

The good news is that WPF natively supports inches as a size unit. You can simply set the Width and Height of your Ellipse to 3in, and you will get WPF's best approximation.

The bad news is that WPF translates inches to physical pixels according to the DPI settings reported by Windows, which often bear little semblance to reality. For example, Windows has long believed the display in my old ThinkPad has a pitch of 96dpi, but it is actually closer to 120dpi. Mobile screens in particular have a tendency to over- or under-report their pixel density.

There are a few unmanaged APIs available that purport to return the physical dimensions of a display, and while these might be more reliable, I suspect the results will still be hit-or-miss. The most promising seems to be using SetupAPI to locate the display’s EDID block in the registry. Might be worth a shot. If it seems reliable enough, you’ll be able to manually compute the effective DPI by dividing the horizontal and vertical pixel counts by the reported physical dimensions, performing any necessary metric-to-imperial conversions (1 in = 2.54 cm).

Mike Strobel
  • 25,075
  • 57
  • 69