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}您能给出一个工作示例吗?