Welcome to MSDN Blogs Sign in | Join | Help

Ivo Manolov's Blog

Windows Presentation Foundation (WPF) and Win32 Programming
UI Scaling (UI Zooming) with WPF

WPF enables the application developer to apply arbitrary transforms to every UI element. This can be used to create dynamically scalable/zoomable UIs, enabling the end-user to scale the user interface of the application.

Pulling off a dynamically scalable/zoomable UI is prohibitively difficult (and thus practically impossible) to do in classic Win32 (and by extension - WinForms) and DHTML as well as other popular GUI toolkits such as AWT, Swing, QT, etc. It is, however, remarkably easy to do in WPF. Here’s how:

1.       First, you need to give to the user a way to control the scale factor. A Slider control is the natural choice for that

<Slider

    x:Name="uiScaleSlider"

    ToolTip="Determines the UI scale factor."

    Value="1" Minimum="0.1" Maximum="4"

    ...

/>

 

2.       Next, define a LayoutTransform for the FrameworkElement you intend to scale (this is typically the top-level panel that contains all of your UI). The LayoutTransform needs to be a ScaleTransform.

 

3.       Bind the scale factor of the ScaleTransform to the value of the slider control.

<DockPanel Grid.Column="0" Grid.ColumnSpan="2" LastChildFill="True">

    <DockPanel.LayoutTransform>

        <ScaleTransform 

            CenterX="0" CenterY="0"

            ScaleX="{Binding ElementName=uiScaleSlider,Path=Value}"

            ScaleY="{Binding ElementName=uiScaleSlider,Path=Value}"

        />

    </DockPanel.LayoutTransform>

    ...

</DockPanel>

 

4.       Finally, provide a way for the user to reset the scaling factor back to 1 or 100%. One way to do that is to do that is to define a double-click handler for your Scale control, which resets the scale factor:

public partial class Window1 : System.Windows.Window

{

    public Window1()

    {

        InitializeComponent();

        uiScaleSlider.MouseDoubleClick +=

            new MouseButtonEventHandler(RestoreScalingFactor); 

    }

 

    void RestoreScalingFactor(object sender, MouseButtonEventArgs args)

    {

        ((Slider)sender).Value = 1.0; 

    }

}  

 

Here are the results:

image

Note that because of the use of LayoutTransform, the original layout of the window is preserved. All of elements of the UI are within reach and completely usable regardless of the current scale factor.

Adding mouse wheel support

Several existing WPF applications (e.g. Microsoft Expression Blend) already expose such UI scaling capability. Some use the mouse wheel to control the scale factor.

Here’s one possible strategy of using the mouse-wheel. Let’s assume the following UI contract:

Gesture

UI meaning

CTRL + Wheel up

Scale up (i.e. zoom in)

CTRL + Wheel down

Scale down (i.e. zoom out)

CTRL + Wheel click

Restore scaling factor to 100%

 

We just intercept the appropriate events in the OnPreviewMouseWheel and OnPreviewMouseDown methods of the main window as follows:

public partial class Window1 : System.Windows.Window

{

    public Window1()

    {

        ...

    }

 

    ...

 

    protected override void OnPreviewMouseWheel(MouseWheelEventArgs args)

    {

        base.OnPreviewMouseWheel(args);

        if (Keyboard.IsKeyDown(Key.LeftCtrl) ||

            Keyboard.IsKeyDown(Key.RightCtrl))

        {

            uiScaleSlider.Value += (args.Delta > 0) ? 0.1 : -0.1;

        }

    }

 

    protected override void OnPreviewMouseDown(MouseButtonEventArgs args)

    {

        base.OnPreviewMouseDown(args);

        if (Keyboard.IsKeyDown(Key.LeftCtrl) ||

            Keyboard.IsKeyDown(Key.RightCtrl))

        {

            if (args.MiddleButton == MouseButtonState.Pressed)

            {

                RestoreScalingFactor(uiScaleSlider, args);

            }

        }

    }

}

Published Friday, October 05, 2007 12:32 PM by ivom

Filed under: ,

Attachment(s): ScalableUI.zip

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# MSDN Blog Postings &raquo; UI Scaling (UI Zooming) with WPF @ Friday, October 05, 2007 4:39 PM

PingBack from http://msdnrss.thecoderblogs.com/2007/10/05/ui-scaling-ui-zooming-with-wpf/

MSDN Blog Postings » UI Scaling (UI Zooming) with WPF

# UI Scaling (UI Zooming) with WPF @ Saturday, October 13, 2007 11:39 AM

WPF enables the application developer to apply arbitrary transforms to every UI element. This can be

Noticias externas

# re: UI Scaling (UI Zooming) with WPF @ Sunday, October 21, 2007 3:32 PM

Eye, I agree it is easier but watch the cut-off of 100% CPU utilisation be so painfully slow..

WPF needs performance work people, I don't know how many times that needs to be said to realise it will fail because it is so pathetic in rendering.

Go native if you have to achieve it but please do not advocate it is without a major, design fault so far: requiring a CrayT90000

rq

# re: UI Scaling (UI Zooming) with WPF @ Sunday, October 21, 2007 10:55 PM

RQ,

On my laptop (Inspiron 6000 with 2 GB RAM, 2.13 GHz single-core CPU and a Radeon X300 video card), I cannot get to 100% CPU utilization. The base CPU utilization I start from (when I start the application and leave it be, alongside the other 65 processes I have running on my machine) is about 15%. Vigorous re-scaling of the UI only gets me as high as about 75% CPU utilization. So the CPU utilization in this particular scenario is not that bad (at least on my laptop) given the fact that the layout transforms trigger both re-rendering and recalculation of the layout. The "perceived performance" (which arguably is more important than any measured perf, although there are exceptions) is pretty good too -- the UI scaling feature in the attached sample is very usable from that point of view.

This of course is not to say that there is no perf work ahead of us. Performance is one of the things we take really seriously (we have a dedicated performance team and performance lab, most of the feature teams have specific performance work-items, we have automated performance tests we run daily, etc., etc.) and we are constantly investing in it. We have done a lot of performance work for the upcoming .NET 3.5 release, specifically around rendering, but also to improve cold-start perf, data-binding perf, etc. I will publish details on what’s new in the 3.5 release one of these days.

The managed-vs-unmanaged call is something that is debated within Microsoft too and is something that unfortunately tends to take religious proportions way too often . Having worked with both managed and unmanaged code, my personal opinion is that  any system of sufficient complexity is bound to face performance challenges. These challenges cannot be overcome by switching from C# to C++/assembly/etc. They can only be overcome by ensuring that performance is an ongoing investment, something that is constantly thought about, measured, etc. at all stages of the development of the product. Incidentally, the same thing applies to other “fundamentals”. There are for example folks who think that unmanaged code is inherently insecure and that using managed code automatically guarantees high levels of security.

Anyways, I diverge. We know that we have some performance work ahead of us and we are investing there heavily. Thanks for your response and thanks for caring!  It’s great that you guys are “keeping us honest” and challenging us constantly so that we can continuously improve the product. Keep the feedback coming!

Thanks:

Ivo

ivom

# re: UI Scaling (UI Zooming) with WPF @ Monday, January 07, 2008 7:16 AM

Thanks. I'm just starting to use WPF for some real world apps and your notes helped me to get a zoomable UI up and running in seconds.

Andrew Jones

# re: UI Scaling (UI Zooming) with WPF @ Wednesday, December 03, 2008 8:47 AM

I'm having a canvas in a scrollviewer, like the code below. The scaling works brilliantly when zooming in, when zooming out my canvas is getting smaller. I would like my canvas to keep filling the scrollviewer but the elements on the canvas to become smaller.

Do you have any hint on how to achieve this?

Thanks!

       <ScrollViewer x:Name="TheScrollViewer" Grid.Row="0" CanContentScroll="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">

           <Canvas x:Name="ScheduleCanvas" Width="{Binding ElementName=TheScrollViewer, Path=ActualWidth}" Height="{Binding ElementName=TheScrollViewer, Path=ActualHeight}">

               <Canvas.LayoutTransform>

                   <ScaleTransform CenterX="0" CenterY="0">

                       <ScaleTransform.ScaleX>

                           <Binding Mode="Default" Path="Value" ElementName="ZoomSlider"/>

                       </ScaleTransform.ScaleX>

                       <ScaleTransform.ScaleY>

                           <Binding Mode="Default" Path="Value" ElementName="ZoomSlider"/>

                       </ScaleTransform.ScaleY>

                   </ScaleTransform>

               </Canvas.LayoutTransform>

           </Canvas>

       </ScrollViewer>

Scaler

# re: UI Scaling (UI Zooming) with WPF @ Tuesday, April 21, 2009 2:32 PM

Great example, exactly what I was looking for!

Thanks

Louis Abbott

# re: UI Scaling (UI Zooming) with WPF @ Monday, May 11, 2009 4:06 AM

That's a great article, many thanks. Lets say we have a large area for interface, is it possible to zoom out or zoom in to where mouse pointer is?

Bogac Guven

# re: UI Scaling (UI Zooming) with WPF @ Monday, May 11, 2009 4:50 AM

I've found this article which achieves a similar result. Because I don't have Visual Studio at work   I can't play with its source code:

http://compilewith.net/2008/06/wpf-zoom-decorator-part1.html

You can see a part of the code in the link above. One thing is interesting, which is related to the question I've asked previously:

<ContentPresenter RenderTransformOrigin="0.5,0.5">

I guess by reading mouse position and giving it to RenderTransformOrigin in each render, zooming to/from mouse pointer position can be achieved.

I'm a WPF newbie so I don't know if it is feasible for your code Ivo.

Thanks

Bogac Guven

# re: UI Scaling (UI Zooming) with WPF @ Saturday, June 13, 2009 3:29 PM

話題の小向美奈子ストリップを隠し撮り!入念なボディチェックをすり抜けて超小型カメラで撮影した神動画がアップ中!期間限定配信の衝撃的映像を見逃すな

小向美奈子

Leave a Comment

(required) 
required 
(required) 
Page view tracker