我有一个WPF子窗口,我使用DragMove()方法允许拖动。然而,我需要仅允许在其父窗口控件的边界内拖动窗口。
有人能提供一种实现此功能的方法吗? 谢谢!
我有一个WPF子窗口,我使用DragMove()方法允许拖动。然而,我需要仅允许在其父窗口控件的边界内拖动窗口。
有人能提供一种实现此功能的方法吗? 谢谢!
有两种方法可以实现这个。
如果您处理此事件,可以将顶部或左侧更改为在所有者窗口的边界内。例如:
private void Window_LocationChanged(object sender, EventArgs e)
{
if (this.Left < this.Owner.Left)
this.Left = this.Owner.Left;
//... also right top and bottom
//
}
这篇文章写起来很简单,但它违反了最小惊讶原则,因为它没有限制拖动窗口,只是在用户松开鼠标按钮时将窗口推回原位。
使用AddHook
正如Pieter在一个类似的问题的答案中指出的那样,你可以与Windows消息交互并阻止拖动窗口。这样做的好处是限制了实际的拖动窗口。
以下是我为AddHook方法编写的示例代码。
在加载窗口时添加钩子。
//In Window_Loaded the handle is there (earlier its null) so this is good time to add the handler
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper helper = new WindowInteropHelper(this);
HwndSource.FromHwnd(helper.Handle).AddHook(HwndSourceHookHandler);
}
private IntPtr HwndSourceHookHandler(IntPtr hwnd, int msg, IntPtr wParam,
IntPtr lParam, ref bool handled)
{
const int WM_MOVING = 0x0216;
const int WM_MOVE = 0x0003;
switch (msg)
{
case WM_MOVING:
{
//read the lparm ino a struct
MoveRectangle rectangle = (MoveRectangle)Marshal.PtrToStructure(
lParam, typeof(MoveRectangle));
//
if (rectangle.Left < this.Owner.Left)
{
rectangle.Left = (int)this.Owner.Left;
rectangle.Right = rectangle.Left + (int)this.Width;
}
Marshal.StructureToPtr(rectangle, lParam, true);
break;
}
case WM_MOVE:
{
//Do the same thing as WM_MOVING You should probably enacapsulate that stuff so don'tn just copy and paste
break;
}
}
return IntPtr.Zero;
}
lParam的结构体 [StructLayout(LayoutKind.Sequential)]
//Struct for Marshalling the lParam
public struct MoveRectangle
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
最后需要注意的一点是,如果您的子窗口允许比父窗口更大,您需要想办法解决此问题。