Есть два способа сделать это.
Использование LocationEnded
Если вы обрабатываете это событие, вы можете изменить Top или Left набыть в пределах окна владельца.например,
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
Как отмечает Питер в ответ на аналогичный вопрос, который вы можете взаимодействовать с сообщениями 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);
}
В вашем обработчике вы хотите искать только перемещение или перемещение сообщения.Затем вы прочитаете прямоугольник lParam и увидите, выходит ли он за пределы.Если это так, вам нужно изменить значения прямоугольника lParam и вернуть его обратно.Заметьте, для краткости, я сделал только левую.Вам все равно нужно будет написать правый, верхний и нижний регистры.
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;
}
Последнее замечание, которое вам необходимо выяснить, что делать, если вашему дочернему окну разрешено быть больше родительского окна.