Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF : Move and resize window at once time

Tags:

window

wpf

resize

In Win32 API, function SetWindowPos provided an easy way to move and resize window at once.

However, in WPF class Window doesn't have a method like SetWindowPos. So I must code like the following:

        this.Left += e.HorizontalChange;
        this.Top += e.VerticalChange;
        this.Width = newWidth;
        this.Height = newHeight;

Of course, it works well, but it's not simple. And it looks dirty.

How can i move a window and resize at once?

Is there an API?

like image 802
mjk6026 Avatar asked Feb 24 '23 06:02

mjk6026


2 Answers

I know you've already solved your problem, but I'll post a solution that I found in case it helps others.

Basically, You must declare that SetWindowsPos as an imported function from Win32 this is the signature

[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);

The function needs the hWnd of your window, in order to get it you can add an handler on the initialization of your windows (for example you could listen for the "SourceInitialized" event) and store that value in a private member of the class:

hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;

WPF manages device independent pixels, so you needs even a converter from dip to real pixel for your screen. This is done with these lines:

var source = PresentationSource.FromVisual(this);
Matrix transformToDevice = source.CompositionTarget.TransformToDevice;
Point[] p = new Point[] { new Point(this.Left + e.HorizontalChange, this.Top), new Point(this.Width - e.HorizontalChange, this.Height) };
transformToDevice.Transform(p);

Finally you can call SetWindowsPos:

SetWindowPos(this.hwndSource.Handle, IntPtr.Zero, Convert.ToInt32(p[0].X), Convert.ToInt32(p[0].Y), Convert.ToInt32(p[1].X), Convert.ToInt32(p[1].Y), SetWindowPosFlags.SWP_SHOWWINDOW);

Sources:

  • Win32 SetWindowPos
  • WPF Graphics Rendering
like image 145
FabioDch Avatar answered Feb 27 '23 12:02

FabioDch


You could wrap your code in a helper method. Just like this:

public static class WindowExtensions {
    public static void MoveAndResize( this Window value, double horizontalChange, double verticalChange, double width, double height ) {
        value.Left += horizontalChange;
        value.Top += verticalChange;
        value.Width = width;
        value.Height = height;
    }
}

So your calling code looks like this:

this.MoveAndResize( 10, 10, 1024, 768 );

I've left off namespace and using declaration, keep that in mind when copying.

Edit:

You could also use the API. Personally I stick with the managed code unless I really need to use the API. But that is up to you.

like image 29
Sascha Avatar answered Feb 27 '23 13:02

Sascha