Hi everyone, just curious if you know of any way to setup a drag boundary for a window?
It would be nice to have these properties:
Me.MinLeft = 10
Me.MinTop = 10
Me.MaxLeft = 150
Me.MaxTop = 150
Those are made up properties, btw, which would be nice to have.
I know I could probably setup a timer to fire ever 10th of a second and check the left and top and then move it back if it's over. But it would be more elegant to have the window act like it hit a wall and can't go any farther, like moving to the edge of the screen or something similar.
Edit: There seems to be some confusion somewhere, the point I'm trying to make is in the paragraph above, dragging, not re-sizing.
-
There are dependency properties for WPF's Window for this purpose.
Here they are:
- Window.MaxWidth
- Window.MaxHeight
These properties will constrain the size of the Window, just like the WinForm's Form.
ScottN : I'm speaking of dragging a window around the screen, not re-sizing it. Think of setting a region on the screen the window is only allowed to move round in, even though your screen is bigger. Like a drag container is best I can think of.ScottN : I'm sitting here reading this again and wondering if I asked the question wrong and how you could think I was speaking of window size and not dragging, I don't even mention the word "size" or "re-size" in my question...eriawan : Drag boundary? I think it's by default is draggable. Do you want drag handle like the ones in the Windows Forms?Drew Noakes : He wants to constraint the area within which a window can be dragged. -
Maybe you could handle
PreviewMouseMove(either the event or override the corresponding protected method) and sete.Handled = truewhenever the mouse movement would cause the window to move outside the region you want to constrain it to.This seems like the most logical, WPF-like way of doing this.
-
Here is teh "magic" you need to create this functionality, all you have to do is set the Window_SourceInitialized method to the window's SourceInitialized event and insert you logic where the big comment is.
I combined this code from several sources, so there could be some syntax errors in it.
internal enum WM { WINDOWPOSCHANGING = 0x0046, } [StructLayout(LayoutKind.Sequential)] internal struct WINDOWPOS { public IntPtr hwnd; public IntPtr hwndInsertAfter; public int x; public int y; public int cx; public int cy; public int flags; } private void Window_SourceInitialized(object sender, EventArgs ea) { HwndSource hwndSource = (HwndSource)HwndSource.FromVisual((Window)sender); hwndSource.AddHook(DragHook); } private static IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled) { switch ((WM)msg) { case WM.WINDOWPOSCHANGING: { WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS)); if ((pos.flags & (int)SWP.NOMOVE) != 0) { return IntPtr.Zero; } Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual; if (wnd == null) { return IntPtr.Zero; } bool changedPos = false; // *********************** // Here you check the values inside the pos structure // if you want to override tehm just change the pos // structure and set changedPos to true // *********************** if (!changedPos) { return IntPtr.Zero; } Marshal.StructureToPtr(pos, lParam, true); handeled = true; } break; } return IntPtr.Zero; } -
As I have no doubt that Nir's answer will work spending a little time implementing it, I was able to do what I wanted a little bit more elegant with this code:
Private Sub myWindow_LocationChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LocationChanged Dim primaryBounds As System.Drawing.Rectangle = Windows.Forms.Screen.PrimaryScreen.Bounds Dim windowBounds As System.Drawing.Rectangle = New System.Drawing.Rectangle(CInt(Me.Left), CInt(Me.Top), CInt(Me.Width), CInt(Me.Height)) If (windowBounds.Left < 0) Then windowBounds = New System.Drawing.Rectangle(0, windowBounds.Top, windowBounds.Width, windowBounds.Height) ElseIf (windowBounds.Right > primaryBounds.Right) Then windowBounds = New System.Drawing.Rectangle(primaryBounds.Right - windowBounds.Width, windowBounds.Top, windowBounds.Width, windowBounds.Height) End If If (windowBounds.Top < 0) Then windowBounds = New System.Drawing.Rectangle(windowBounds.Left, 0, windowBounds.Width, windowBounds.Height) ElseIf (windowBounds.Bottom > primaryBounds.Bottom) Then windowBounds = New System.Drawing.Rectangle(windowBounds.Left, primaryBounds.Bottom - windowBounds.Height, windowBounds.Width, windowBounds.Height) End If Me.Left = windowBounds.Left Me.Top = windowBounds.Top End SubThis made the window being dragged stay within the primary screen (whole window), but you could easily change the bounds to whatever values you needed.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.