Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF窗口拖动/移动边界_Wpf_Winforms - Fatal编程技术网

WPF窗口拖动/移动边界

WPF窗口拖动/移动边界,wpf,winforms,Wpf,Winforms,只是好奇你是否知道为窗口设置拖动边界的方法 拥有这些属性会很好: Me.MinLeft = 10 Me.MinTop = 10 Me.MaxLeft = 150 Me.MaxTop = 150 顺便说一句,这些都是虚构的财产,拥有它们会很好 我知道我可能会设置一个计时器,每10秒启动一次,检查左侧和顶部,然后在结束后将其向后移动。但如果让窗户看起来像撞到了墙,不能再往前走,比如移到屏幕边缘或类似的地方,那就更优雅了 编辑:有些地方似乎有些混乱,我想说的是在上面的段落中,拖动,而不是重新调整大小

只是好奇你是否知道为窗口设置拖动边界的方法

拥有这些属性会很好:

Me.MinLeft = 10
Me.MinTop = 10
Me.MaxLeft = 150
Me.MaxTop = 150
顺便说一句,这些都是虚构的财产,拥有它们会很好

我知道我可能会设置一个计时器,每10秒启动一次,检查左侧和顶部,然后在结束后将其向后移动。但如果让窗户看起来像撞到了墙,不能再往前走,比如移到屏幕边缘或类似的地方,那就更优雅了


编辑:有些地方似乎有些混乱,我想说的是在上面的段落中,拖动,而不是重新调整大小。

为此,WPF的窗口有一些依赖属性

这是:

Window.MaxWidth Window.MaxHeight
这些属性将约束窗口的大小,就像WinForm的表单一样。

为此,WPF的窗口有依赖属性

这是:

Window.MaxWidth Window.MaxHeight 这些属性将约束窗口的大小,就像WinForm的表单一样。

可能您可以处理事件或覆盖相应的受保护方法,并设置e.Handled=true,只要鼠标移动会导致窗口移动到要约束它的区域之外

这似乎是最符合逻辑的、类似WPF的方法。

可能您可以处理事件或覆盖相应的受保护方法,并设置e.Handled=true,只要鼠标移动会导致窗口移动到您想要约束它的区域之外


这似乎是最符合逻辑的、类似WPF的方法。

这里是创建此功能所需的魔法,您所要做的就是将Window\u 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;
}

这是创建此功能所需的魔法,只需将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

这使得被拖动的窗口保持在主屏幕的整个窗口内,但您可以轻松地将边界更改为所需的任何值。

由于我毫不怀疑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

这使得被拖动的窗口保持在整个窗口的主屏幕内,但您可以轻松地将边界更改为所需的任何值。

我指的是在屏幕周围拖动窗口,而不是重新调整其大小。考虑在屏幕上设置一个区域,窗口只允许在其中移动,即使屏幕更大。我坐在这里再次阅读这篇文章,想知道我问的问题是否错了,你怎么会认为我说的是窗口大小而不是拖动,我的问题中甚至没有提到单词size或re size…拖动边界?我认为默认情况下它是可拖动的。你想要像Windows窗体中那样的拖动控制柄吗?他想要限制窗口可以拖动的区域。我说的是在屏幕周围拖动窗口,而不是重新调整大小。考虑在屏幕上设置一个区域,窗口只允许在其中移动,即使屏幕更大。我坐在这里再次阅读这篇文章,想知道我问的问题是否错了,你怎么会认为我说的是窗口大小而不是拖动,我的问题中甚至没有提到单词size或re size…拖动边界?我认为默认情况下它是可拖动的。你想要像Windows窗体中那样的拖动句柄吗?他想要约束窗口可以拖动的区域。我以前尝试过这个,但是窗口位置更改事件发生在窗口已经在屏幕上移动之后,因此,这会产生一种不和谐的视觉效果,当窗口开始超过某个限制时,窗口会闪烁或跳跃,因为它最初被画出边界,然后重新画回你想要的地方。如何防止窗口闪烁?拖动运动不平稳。我以前试过,但窗口位置更改事件发生在窗口已经在屏幕上移动之后,因此,这会产生一种不和谐的视觉效果,当窗口开始超过某个限制时,窗口会闪烁或跳跃,因为它最初会被画出边界,然后重新画回您想要的位置。如何防止窗口闪烁 拖动运动不平滑。嗨。如果pos.flags和intSWP.NOMOVE!=0? 它应该声明为枚举,对吗?内部枚举SWP{NOMOVE=0x0002}您能给出一个工作示例吗?嗨。如果pos.flags和intSWP.NOMOVE!=0? 它应该声明为枚举,对吗?内部枚举SWP{NOMOVE=0x0002}您能给出一个工作示例吗?