我在 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   回答