Click here to Skip to main content
Licence CPOL
First Posted 23 Jan 2008
Views 71,196
Downloads 1,936
Bookmarked 33 times

WPF Window Resizing

By | 23 Jan 2008 | Article
An article on using UI elements to control window size
windowresize1.jpg

windowresize2.jpg

Introduction

In certain cases it may be desirable to completely replace the non-client area (title bar, title bar buttons and window borders) with a completely custom user interface. An example of such is when applying buttons that seemingly cross from non-client areas to client areas (e.g. the Start button found in Microsoft Office 2007 applications such as Microsoft Office Word). In these instances, a Windows Presentation Foundation (WPF) window may be created using no client area and the entire window recreated, gaining access to all areas of the new window as a client area.

Standard window functionality must be recreated for the user experience to remain constant. Most functionality (i.e. window move, close, maximise, restore, minimise) is easily achieved. However, window resizing by mouse drag is considerably more complex.

In this article, an approach to creating resizable windows with the standard resize drag functionality is presented. A utility library is provided which allows any WPF window to be resized via UIElements (not necessarily part of the window to be resized). The mouse pointer is adjusted to the relevant graphic automatically when the pointer is hovering over any registered window resizing control.

Using the Code

A single class called WindowResizer is included in the library, which controls all functionality to do with resizing. To use the library, it should be included and linked into the UI as follows. Note that an ideal place is the constructor for the window since, in most cases, the resize components will be available from window birth to death.

//this is the target window object for resizing
WindowResizer wr = new WindowResizer(this);

//xxxSizeGrip, where xxx corresponds to the equivilent border position
wr.addResizerRight(rightSizeGrip);
wr.addResizerLeft(leftSizeGrip);
wr.addResizerUp(topSizeGrip);
wr.addResizerDown(bottomSizeGrip);
wr.addResizerLeftUp(topLeftSizeGrip);
wr.addResizerRightUp(topRightSizeGrip);
wr.addResizerLeftDown(bottomLeftSizeGrip);
wr.addResizerRightDown(bottomRightSizeGrip);

During the call to .addResizer...(UIElement), all event handler hooks are added to the UI element. From call completion, the component will be acting as a resizing element upon the target window. The window and elements must be valid and created before the calls are made.

Two event handlers are added to each UI element to control the pointer graphic (i.e. to achieve the arrow graphics while hovering the border), MouseEnter and MouseLeave. In this release, this option is sufficient. However, in later releases this will be changed to an unmanaged call to the underlying Windows APIs to prevent the pointer changing back to the standard arrow pointer when rapidly sizing the window up. By increasing the mouse polling speed (and hence making the resize operations more rapidly starting) this effect is reduced, although it is noticeable. A starting point for research to solve this effect would be investigation of user32.dll.

This problem is made significantly complex due to the different handling of mouse move events and mouse positioning. Under .NET 2.0, Cursor.GetPosition(...) returned the position of the mouse relative to the specified component. However, under .NET 3.5, this has changed to the position of the mouse relative to the component, but clamped to the bounds of the component. For example, given that a component has a horizontal screen position of 100 pixels, a width of 200 pixels and a mouse screen position of 500 pixels, .NET 2.0 would return a relative position to the component of 400 pixels. However, .NET 3.5 returns a relative position of just 200 pixels.

A similar effect is found when using Cursor.GetPosition(...). The returned value is clamped to the relative bounds of the component. The solution to this is to get the absolute screen position via a user32.dll call. Specifically, the following code must be added and polled routinely (20 millisecond delay between polls) while dragging the mouse:

[DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetCursorPos(out PointAPI lpPoint);

private struct PointAPI
        {
            public int X;
            public int Y;
        }

The GetCursorPos() method is polled via the following call:

PointAPI p = new PointAPI();
GetCursorPos(out p);

Using user32.dll is just one way of obtaining mouse position data outside the bounds of a WPF window. It is possible to use DirectInput and obtain a Microsoft.DirectX.DirectInput.Device. However, the mouse position is not reported rather than the mouse movement (i.e. 2 right, 10 down). Extreme care must be taken when using this form of input, as the position data generated may not correspond to the same resolution as the screen (i.e. 10 right from DirectInput may not correspond to 10 screen pixels right).

Points of Interest

All other window functionality is easily implemented and mostly a case of using Grid layout to position correctly. A close button is implemented via a button click handler and Window.Close(). Maximise, restore and minimise are implemented via Window.WindowState, and window dragging is implemented via MoveDrag() on the MouseDown or MouseLeftButtonDown UIElement handler. Curiously, no ResizeDrag() is available currently.

History

Version 1.0.0.0 (January 23, 2008) Basic mouse drag functionality with auto cursor icon changing.

Contributors

Grateful thanks to Mike for his work on user32.dll.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Derek Bartram

Software Developer
Rail Research UK
United Kingdom United Kingdom

Member

I originally studied for a masters in engineering of software engineering at The University of Birmingham during 2000-2004, of which I received a 2:1. I continued at Birmingham University working with Civil Engineering and Rail Research UK where I am currently in my final year of a 3 year PhD project developing a Computational Intelligent Approach to Railway Intervention Planning. Although my work has a significant focus on railway engineering and associated practices much of my work is with data mining (on SQL Server 2008) and computational intelligence (CI) techniques. My key areas of expertise in CI are clustering algorithms (including Rival Penalised Competitive Learning) and evolutionary algorithms.
 
Outside of my formal work I enjoy testing the latest technologies such as .NET 3.5 and the many frameworks of which it comprises (mainly WPF). I have several projects on the go including a .NET and DirectX port of Quake 3 and many utility libraries. I also maintain an extensive website coded in Cold Fusion which is regularly updated; more information is available about me there.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
AnswerChange suggestion PinmemberMartin HuHn3:57 1 Aug '11  
GeneralMy vote of 3 PinmemberStewBob8:20 2 Nov '10  
GeneralNice Resizer PinmemberMember 429695222:17 21 Oct '10  
GeneralA resize megamix! Pinmemberjp chow10:58 8 May '09  
GeneralRebuilt and this doesn't work right PinmemberCynisterSix11:47 3 Apr '09  
GeneralThere's built-in functionality PinmemberStanislav Kniazev4:42 30 Dec '08  
GeneralRe: There's built-in functionality PinmemberCynisterSix12:20 3 Apr '09  
GeneralRe: There's built-in functionality PinmemberStanislav Kniazev23:59 3 Apr '09  
GeneralRe: There's built-in functionality PinmemberEshva3:24 8 Feb '10  
GeneralMy version of Stanislav's solution PinmemberEshva3:44 8 Feb '10  
GeneralRe: My version of Stanislav's solution PinmemberM0nsign0r4:01 16 Nov '11  
GeneralMy vote of 2 PinmemberJared Thirsk18:26 12 Dec '08  
GeneralMy vote of 1 PinmemberStanislav Kniazev2:35 24 Nov '08  
QuestionCan this be applied to Listbox Item Pinmemberanjali Batra2:00 19 Sep '08  
AnswerRe: Can this be applied to Listbox Item PinmemberDerek Bartram2:10 19 Sep '08  
GeneralCrashes when resizing using the top left corner Pinmemberdaveoggy6:13 19 Jun '08  
GeneralRe: Crashes when resizing using the top left corner PinmemberDerek Bartram2:07 20 Jun '08  
GeneralRe: Crashes when resizing using the top left corner PinmemberJonathan Schmidt3:43 3 Oct '10  
Generalchoppy resize PinmemberMember 18980394:42 30 Jan '08  
GeneralRe: choppy resize PinmemberDerek Bartram16:33 30 Jan '08  
GeneralRe: choppy resize PinmemberDerek Bartram13:45 4 Feb '08  
GeneralRe: choppy resize PinmemberDerek Bartram10:47 22 Mar '08  
Bitmap Effects on an element results in all sub elements being software renderer = BAD performance

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120529.1 | Last Updated 23 Jan 2008
Article Copyright 2008 by Derek Bartram
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid