簡體   English   中英

WPF窗口拖動/移動邊界

[英]WPF Window Drag/Move Boundary

只是好奇是否知道為窗口設置拖動邊界的任何方法?

具有這些屬性將是很好的:

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

這些是由屬性btw組成的 ,很高興擁有。

我知道我可能可以設置一個計時器,使其每十秒觸發一次,檢查左側和頂部,如果結束則將其移回。 但是,讓窗口像打到牆一樣,又不能走得更遠,比如移動到屏幕的邊緣或類似的東西,會更加優雅。

編輯:某處似乎有些混亂,我要說明的是在上面的段落中,拖動而不是重新調整大小。

這是創建此功能所需要的“魔術”,所有您需要做的就是將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;
}

毫無疑問,Nir的答案會花一些時間來實現它,因此我可以用以下代碼做一些我想做的事情:

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

這使被拖動的窗口停留在主屏幕(整個窗口)內,但是您可以輕松地將邊界更改為所需的任何值。

為此,WPF的窗口具有依賴項屬性。

他們來了:

  • Window.MaxWidth
  • Window.MaxHeight

這些屬性將限制Window的大小,就像WinForm的Form一樣。

也許您可以處理PreviewMouseMove (事件或重寫相應的受保護方法),並在每次鼠標移動會使窗口移至您要限制窗口的區域之外時將e.Handled = true設置。

這似乎是最符合邏輯的,類似WPF的方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM