我在 WPF 中的自定义窗口(AllowTransparency,WindowStyle=None)有问题。DragMove() 方法效果很好,但是当我最大化窗口,或者通过 Windows 7 Aero Snap 自动最大化时,这个方法根本不起作用。所以我不能用鼠标拖动来取消捕捉窗口并将它的状态返回到 WindowState.Normal。左右 Aero Snap 效果很好,我可以毫无问题地捕捉和取消捕捉窗口。但是当它最大化时,除了 Win+Down 组合之外没有任何效果。也许有人知道如何解决这个问题,或者我在哪里可以找到其他方法来使用有效的 Aero Snap 功能对自定义窗口进行适当的 DragMove?
问问题
9763 次
6 回答
16
这是我的方法。试着让它更短)))
private void InitHeader()
{
var border = Find<Border>("borderHeader");
var restoreIfMove = false;
border.MouseLeftButtonDown += (s, e) =>
{
if (e.ClickCount == 2)
{
if ((ResizeMode == ResizeMode.CanResize) ||
(ResizeMode == ResizeMode.CanResizeWithGrip))
{
SwitchState();
}
}
else
{
if (WindowState == WindowState.Maximized)
{
restoreIfMove = true;
}
DragMove();
}
};
border.MouseLeftButtonUp += (s, e) =>
{
restoreIfMove = false;
};
border.MouseMove += (s, e) =>
{
if (restoreIfMove)
{
restoreIfMove = false;
var mouseX = e.GetPosition(this).X;
var width = RestoreBounds.Width;
var x = mouseX - width / 2;
if (x < 0)
{
x = 0;
}
else
if (x + width > screenSize.X)
{
x = screenSize.X - width;
}
WindowState = WindowState.Normal;
Left = x;
Top = 0;
DragMove();
}
};
}
private void SwitchState()
{
switch (WindowState)
{
case WindowState.Normal:
{
WindowState = WindowState.Maximized;
break;
}
case WindowState.Maximized:
{
WindowState = WindowState.Normal;
break;
}
}
}
(要获得 screenSize 我使用本机方法)
于 2012-07-28T20:20:43.830 回答
13
Groaner 的解决方案无法在多个显示器设置下正常运行,尤其是在主显示器不在最左侧的情况下。
这是我基于他的解决方案,它可以正确处理单个或多个监视器设置。在此代码中,“rctHeader”是在 XAML 中定义的 Rectangle。
private bool mRestoreIfMove = false;
public MainWindow()
{
InitializeComponent();
}
private void SwitchWindowState()
{
switch (WindowState)
{
case WindowState.Normal:
{
WindowState = WindowState.Maximized;
break;
}
case WindowState.Maximized:
{
WindowState = WindowState.Normal;
break;
}
}
}
private void rctHeader_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
if ((ResizeMode == ResizeMode.CanResize) || (ResizeMode == ResizeMode.CanResizeWithGrip))
{
SwitchWindowState();
}
return;
}
else if (WindowState == WindowState.Maximized)
{
mRestoreIfMove = true;
return;
}
DragMove();
}
private void rctHeader_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
mRestoreIfMove = false;
}
private void rctHeader_MouseMove(object sender, MouseEventArgs e)
{
if (mRestoreIfMove)
{
mRestoreIfMove = false;
double percentHorizontal = e.GetPosition(this).X / ActualWidth;
double targetHorizontal = RestoreBounds.Width * percentHorizontal;
double percentVertical = e.GetPosition(this).Y / ActualHeight;
double targetVertical = RestoreBounds.Height * percentVertical;
WindowState = WindowState.Normal;
POINT lMousePosition;
GetCursorPos(out lMousePosition);
Left = lMousePosition.X - targetHorizontal;
Top = lMousePosition.Y - targetVertical;
DragMove();
}
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
}
于 2014-01-06T00:52:43.007 回答
11
在 WPF 中,我强烈建议在Window.DragMove之前恢复窗口时使用Control.PointToScreen。PointToScreen 还将处理多个监视器设置。这将简化以下内容的恢复:
private void OnMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
if( e.ClickCount == 2 )
{
if( ResizeMode != ResizeMode.CanResize &&
ResizeMode != ResizeMode.CanResizeWithGrip )
{
return;
}
WindowState = WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
else
{
mRestoreForDragMove = WindowState == WindowState.Maximized;
DragMove();
}
}
private void OnMouseMove( object sender, MouseEventArgs e )
{
if( mRestoreForDragMove )
{
mRestoreForDragMove = false;
var point = PointToScreen( e.MouseDevice.GetPosition( this ) );
Left = point.X - ( RestoreBounds.Width * 0.5 );
Top = point.Y;
WindowState = WindowState.Normal;
DragMove();
}
}
private void OnMouseLeftButtonUp( object sender, MouseButtonEventArgs e )
{
mRestoreForDragMove = false;
}
private bool mRestoreForDragMove;
于 2015-06-17T21:39:07.083 回答
7
另一个答案有点晚了,但我的代码更简单,所以我把它放在这里。左右对齐可以正常工作,但是当窗口最大化或对齐到屏幕上界并最大化时,DragMove 方法将不起作用!所以这就是我所做的:
只需在要拖动的元素上处理 Mouse_Down 事件,如下所示:
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (WindowState == WindowState.Maximized)
{
var point = PointToScreen(e.MouseDevice.GetPosition(this));
if (point.X <= RestoreBounds.Width / 2)
Left = 0;
else if (point.X >= RestoreBounds.Width)
Left = point.X - (RestoreBounds.Width - (this.ActualWidth - point.X));
else
Left = point.X - (RestoreBounds.Width / 2);
Top = point.Y - (((FrameworkElement)sender).ActualHeight / 2);
WindowState = WindowState.Normal;
}
DragMove();
}
我希望它可以帮助某人!
于 2016-09-24T08:35:33.020 回答
2
DragMove() 方法仅适用于表单的标题栏中,因此请使用:
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
public static void StartDrag(Window window)
{
WindowInteropHelper helper = new WindowInteropHelper(window);
SendMessage(helper.Handle, 161, 2, 0);
}
不要忘记添加 System.Windows.Interop
于 2019-03-21T02:26:55.707 回答
0
于 2015-01-05T10:47:53.547 回答