我的自定义窗口(AllowTransparency,WindowStyle = None)在WPF中有问题。 DragMove()方法效果很好,但是当我最大化窗口,或者它通过Windows 7 Aero Snap自动最大化时,此方法根本不起作用。所以我无法用鼠标拖动来取消窗口并将其状态返回到WindowState.Normal。左右Aero Snap工作正常,我可以快速捕捉和取消窗口。但是当它最大化时,除了Win + Down组合之外没有任何作用。也许有人知道如何解决这个问题,或者我在哪里可以通过工作的Aero Snap功能找到其他方法来自定义窗口的DragMove?
答案 0 :(得分:14)
这是我的方法。尝试缩短)))
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,我使用本机方法)
答案 1 :(得分:12)
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;
}
}
}
答案 2 :(得分:7)
在WPF中,我强烈建议您在Control.PointToScreen之前恢复窗口时使用Window.DragMove。 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;
答案 3 :(得分:3)
另一个答案有点晚了,但我的代码更简单,所以我把它放在这里。 正如你所做的那样,左右对齐的工作正常,但是当窗口最大化或捕捉到上部屏幕边界并最大化时,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();
}
我希望它有所帮助!
答案 4 :(得分:0)
答案 5 :(得分:0)
DragMove()方法仅在表单的标题栏中起作用,因此请使用:
"Limit (cost=25.62..1349.23 rows=206 width=202) (actual time=0.359..0.359 rows=0 loops=1)"
" -> Nested Loop (cost=25.62..1349.23 rows=206 width=202) (actual time=0.357..0.357 rows=0 loops=1)"
" Join Filter: (notifications.device_id = devices.id)"
" -> Nested Loop (cost=25.33..1258.73 rows=206 width=206) (actual time=0.357..0.357 rows=0 loops=1)"
" -> Hash Join (cost=25.04..61.32 rows=206 width=52) (actual time=0.043..0.172 rows=193 loops=1)"
" Hash Cond: (notifications.event_id = events.id)"
" -> Index Scan using idx_notifications_status on notifications (cost=0.42..33.87 rows=206 width=16) (actual time=0.013..0.100 rows=193 loops=1)"
" Index Cond: (status = 'pending'::notification_status)"
" Filter: (region = 'ap-southeast-2'::text)"
" -> Hash (cost=16.50..16.50 rows=650 width=40) (actual time=0.022..0.022 rows=34 loops=1)"
" Buckets: 1024 Batches: 1 Memory Usage: 14kB"
" -> Seq Scan on events (cost=0.00..16.50 rows=650 width=40) (actual time=0.005..0.014 rows=34 loops=1)"
" -> Index Scan using idx_device_endpoints_device_id on device_endpoints (cost=0.29..5.80 rows=1 width=154) (actual time=0.001..0.001 rows=0 loops=193)"
" Index Cond: (device_id = notifications.device_id)"
" -> Index Scan using devices_pkey on devices (cost=0.29..0.43 rows=1 width=4) (never executed)"
" Index Cond: (id = device_endpoints.device_id)"
" Filter: (device_id ~ '[0-9a-f].*'::text)"
"Planning time: 0.693 ms"
"Execution time: 0.404 ms"
不要忘记添加System.Windows.Interop