Перетаскивание окна WPF / Перемещение границы - PullRequest
1 голос
/ 20 февраля 2009

просто любопытно, знаете ли вы какой-либо способ установки границы перетаскивания для окна?

Было бы неплохо иметь следующие свойства:

Me.MinLeft = 10
Me.MinTop = 10
Me.MaxLeft = 150
Me.MaxTop = 150

Это готовые свойства, кстати , которые было бы неплохо иметь.

Я знаю, что, возможно, мог бы установить таймер на срабатывание каждые 10 секунд и проверить левую и верхнюю части, а затем переместить его обратно, если он закончился. Но было бы более элегантно, если бы окно действовало так, как будто оно врезалось в стену и не могло идти дальше, например, двигаясь к краю экрана или что-то подобное.

Редактировать: Кажется, где-то есть некоторая путаница, смысл, который я пытаюсь подчеркнуть, в абзаце выше, перетаскивание, а не изменение размера.

Ответы [ 4 ]

3 голосов
/ 22 февраля 2009

Вот «волшебство», необходимое для создания этой функциональности, все, что вам нужно сделать, это установить метод Window_SourceInitialized на событие SourceInitialized окна и вставить логику там, где находится большой комментарий.

Я собрал этот код из нескольких источников, чтобы в нем могли быть некоторые синтаксические ошибки.

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;
}
2 голосов
/ 21 марта 2010

Поскольку я не сомневаюсь, что ответ Нира потратит немного времени на его реализацию, я смог сделать то, что хотел, немного более элегантно с этим кодом:

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 Sub

Это привело к тому, что перетаскиваемое окно оставалось в пределах основного экрана (всего окна), но вы могли легко изменить границы на любые нужные вам значения.

0 голосов
/ 20 февраля 2009

Возможно, вы могли бы обработать PreviewMouseMove (либо событие, либо переопределить соответствующий защищенный метод) и установить e.Handled = true всякий раз, когда движение мыши заставит окно выйти за пределы области, которую вы хотите ограничить к.

Это кажется наиболее логичным, WPF-подобным способом сделать это.

0 голосов
/ 20 февраля 2009

Для этого есть окно зависимостей для окна WPF.

Вот они:

  • Window.MaxWidth
  • Window.MaxHeight

Эти свойства будут ограничивать размер окна, как и форма WinForm.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...