2009-02-20 121 views
1

只是好奇,如果你知道任何方式來設置窗口的拖動邊界?WPF窗口拖動/移動邊界

這將是很好有這些屬性:

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

這些是由性質,順便說一句,這將是不錯的。

我知道我大概可以設置一個定時器,以便每秒鐘發射十次,然後檢查左側和頂部,然後在結束時將其移回。但是讓窗戶像撞牆一樣行動會更優雅,並且不能再往前走,就像移動到屏幕邊緣或類似物體一樣。

編輯:似乎有一些混淆的地方,我試圖做的是在上面的段落,拖動,而不是重新調整大小。

回答

2

正如我毫不懷疑,尼爾答案將工作花一點時間來實現它,我能夠做我想要多一點優雅與此代碼:

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

爲此,WPF的Window有依賴項屬性。

在這裏,他們是:

  • Window.MaxWidth
  • Window.MaxHeight

這些屬性將限制窗口的大小,就像在WinForm的表格。

+0

我在說拖動窗口周圍的窗口,而不是重新調整它的大小。想想在屏幕上設置一個區域,即使屏幕較大,也只允許窗口四處移動。像拖曳容器是我能想到的最好的。 – ScottN 2009-02-20 07:13:37

+0

我坐在這裏再讀一遍,想知道我是否問了這個問題,以及我怎麼會認爲我是在談論窗口大小而不是拖動,我甚至沒有提到「大小」或「重新大小」這個詞我的問題... – ScottN 2009-02-20 07:18:15

+0

拖動邊界?我認爲它默認是可拖動的。你想拖動像Windows窗體中的那些句柄嗎? – 2009-02-20 15:11:37

0

也許你可以處理PreviewMouseMove(事件或覆蓋相應的受保護的方法),並設置e.Handled = true,只要鼠標移動將導致窗口移動到您想約束它的區域之外。

這似乎是最合乎邏輯的WPF式的做法。

2

這是需要創建此功能的「魔術」,您只需將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; 
}