heltonbiker
heltonbiker

Reputation: 27575

Is it possible to display a WPF Control in real-world, device-independent units? Milimeters, for example?

I am designing a product emulator in WPF. Our company sells a handheld electronic medical device, and we'd like to experiment with user interaction with a "virtual", skinned (sort of) GUI to represent buttons and leds.

Is there a way to "force" WPF to display stuff with its real-world dimension on the screen (by getting monitor dpi information, or something like this)?

As another example, suppose I can layout a plastic, standard-sized Credit Card using WPF controls (DockPanels, Labels, Canvases, etc.), could I consistently display it with the dimensions of a real credit card, across different desktops/laptops?

UPDATE:

I've found a clever way to design in "real milimeters" by using a ViewBox as the LayoutRoot of my window. Size of anything inside can be "designed in milimeters", and will be displayed in physical size PROVIDED that I can get the right pixel size for the ViewBox. And THAT remain a certain mistery:

Upvotes: 1

Views: 237

Answers (1)

heltonbiker
heltonbiker

Reputation: 27575

I "sort of" solved the problem with the following strategy:

  • My MainWindow has a ViweBox as LayoutRoot, and its Child is some container control (Border in this case) which represent the physical object;
  • The ViewBox and everything inside it is defined as if WPF units were milimeters. So, if the product has a physical Width of 68mm, the Width property of the container control is 78. Everything else that is nested inside is treated as if WPF units were actual milimeters;
  • The ViewBox has its Width and Height bounded to the Height and Width of the container control using a ValueConverter which multiplies by (96/25.4);
  • Since everything inside a viewbox is scaled to fit (ViewBox.Stretch=Uniform), the value converter just resizes the viewbox, and the rest of layout redimensioning is achieved by the ViewBox embedded rendering transform (that I assume to be efficient enough).

My XAML:

<Window.Resources>
    <local:PixelsToMilimeters x:Key="SizeConverter"/>       
</Window.Resources>

<Viewbox x:Name="LayoutRoot" Stretch="Uniform"
    Width="{Binding Width, ElementName=Case, Converter={StaticResource SizeConverter}}"
    Height="{Binding Height, ElementName=Case, Converter={StaticResource SizeConverter}}">
    <Border x:Name="Case" Width="108" Height="68">
    (...)

My code-behind:

    (...)
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (double)value * (96/25.4);
    }
    (...)

Of course the "how can I be sure that DPI is actually 96?" is not solved, but that could be encapsulated, and the final result is close enough to the expected one, for my purposes.

Upvotes: 1

Related Questions