2009-02-20 98 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; 
}