11

WPFのカスタムウィンドウ(AllowTransparency、WindowStyle = None)に問題があります。DragMove()メソッドは正常に機能しますが、ウィンドウを最大化するか、Windows 7 Aeroスナップによって自動的に最大化すると、このメソッドはまったく機能しません。そのため、マウスドラッグでウィンドウのスナップを解除して、その状態をWindowState.Normalに戻すことはできません。左右のエアロスナップはうまく機能し、問題なくウィンドウをスナップおよびスナップ解除できます。しかし、最大化すると、Win+Downの組み合わせ以外は機能しません。誰かがこの問題を解決する方法を知っているかもしれませんし、Aero Snap機能が機能するカスタムウィンドウの適切なDragMoveを実行する他の方法をどこで見つけることができますか?

4

6 に答える 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 に答える
0

私はこれについてブログ記事を書きました:

http://dragablz.net/2014/12/16/getting-windows-snap-to-play-with-wpf-borderless-windows/

于 2015-01-05T10:47:53.547 に答える