Я пытаюсь понять, есть ли элегантное решение проблемы, с которой я столкнулся.

По сути, я разработал загрузочный экран-заставку без полей, который можно полностью перемещать с помощью перетаскивания. Я обнаружил, что это происходит, если экран-заставка скрывается с помощью Hide (), а затем отображает окно с помощью ShowDialog () с владельцем, установленным на экран-заставку. Вещи становятся очень глючными, но только если вы в середине перетаскивания (с нажатой левой кнопкой мыши). Вы не можете что-либо щелкнуть или переместить, даже Visual Studio перестает отвечать, если вы явно не используете Alt-Tab из приложения.

Учитывая, что я знаю, когда я собираюсь создать окно, я подумал, может быть, есть способ отменить операцию DragMove, но мне не повезло. Я понял, что DragMove является синхронным, поэтому я предполагаю, что его придется отменить из другого потока или в обратном вызове события.

Редактировать:

public partial class Window_Movable : Window
{
    public Window_Movable()
    {
        InitializeComponent();
    }

    public Boolean CanMove { get; set; } = true;

    private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (CanMove == false)
            return;

        Task.Factory.StartNew(() => {
            System.Threading.Thread.Sleep(1000);

            Dispatcher.Invoke(() => {
                Hide();
                new Window_Movable() {
                    Title = "MOVABLE 2",
                    CanMove = false,
                    Owner = this
                }.ShowDialog();
            });
        });

        DragMove();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Console.WriteLine("DING");
    }
}
2
Aderic 14 Сен 2018 в 20:41

2 ответа

Лучший ответ

У меня была такая же проблема, и я обнаружил, что проблема с методом DragMove (). https://groups.google.com/forum/#!topic/ МОФ - ученики / 7OcuXrf2whc

Для решения я решил отказаться от его использования и реализовать логику перемещения. Я объединил некоторые решения из https://www.codeproject.com/Questions/284995/DragMove- проблемно- помощь -PLS и C # WPF Перемещение окна

        private bool _inDrag;
        private Point _anchorPoint;
        private bool _iscaptured;

        private void AppWindowWindowOnMouseMove(object sender, MouseEventArgs e)
        {
            if (!_inDrag)
                return;

            if (!_iscaptured)
            {
                CaptureMouse();
                _iscaptured = true;
            }

            var mousePosition = e.GetPosition(this);
            var mousePositionAbs = new Point
            {
                X = Convert.ToInt16(_appWindowWindow.Left) + mousePosition.X,
                Y = Convert.ToInt16(_appWindowWindow.Top) + mousePosition.Y
            };
            _appWindowWindow.Left = _appWindowWindow.Left + (mousePositionAbs.X - _anchorPoint.X);
            _appWindowWindow.Top = _appWindowWindow.Top + (mousePositionAbs.Y - _anchorPoint.Y);
            _anchorPoint = mousePositionAbs;
        }

        private void AppWindowWindowOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (_inDrag)
            {
                _inDrag = false;
                _iscaptured = false;
                ReleaseMouseCapture();
            }
        }

        private void AppWindowWindowOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _anchorPoint = e.GetPosition(this);
            _anchorPoint.Y = Convert.ToInt16(_appWindowWindow.Top) + _anchorPoint.Y;
            _anchorPoint.X = Convert.ToInt16(_appWindowWindow.Left) + _anchorPoint.X;
            _inDrag = true;
        }

Провел весь вчерашний вечер и нашел более хакерское, но более функциональное решение. Которые поддерживают развернутое состояние и не требуют ручного расчета координат.

    private bool _mRestoreForDragMove;
    private void OnAppWindowWindowOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ClickCount == 2)
        {
            if (_appWindowWindow.ResizeMode != ResizeMode.CanResize &&
                _appWindowWindow.ResizeMode != ResizeMode.CanResizeWithGrip)
            {
                return;
            }

            _appWindowWindow.WindowState = _appWindowWindow.WindowState == WindowState.Maximized
                ? WindowState.Normal
                : WindowState.Maximized;
        }
        else
        {
            _mRestoreForDragMove = _appWindowWindow.WindowState == WindowState.Maximized;

            SafeDragMoveCall(e);
        }
    }

    private void SafeDragMoveCall(MouseEventArgs e)
    {
        Task.Delay(100).ContinueWith(_ =>
        {
            Dispatcher.BeginInvoke((Action)
                delegate
                {
                    if (Mouse.LeftButton == MouseButtonState.Pressed)
                    {
                        _appWindowWindow.DragMove();
                        RaiseEvent(new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left)
                        {
                            RoutedEvent = MouseLeftButtonUpEvent
                        });
                    }
                });
        });
    }

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (_mRestoreForDragMove)
        {
            _mRestoreForDragMove = false;

            var point = PointToScreen(e.MouseDevice.GetPosition(this));

            _appWindowWindow.Left = point.X - (_appWindowWindow.RestoreBounds.Width * 0.5);
            _appWindowWindow.Top = point.Y;

            _appWindowWindow.WindowState = WindowState.Normal;

            _appWindowWindow.DragMove();

            SafeDragMoveCall(e);
        }
    }

    private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _mRestoreForDragMove = false;
    }

Дело в том, чтобы отправить событие LeftMouseButtonUp после небольшой задержки, чтобы избежать блокировки от DragMove ()

Источники для последнего решения: DragMove () и развернуть C # WPF - DragMove и щелкните

2
Alexey Perkin 20 Сен 2018 в 09:00

И еще одно совершенно другое решение. Чтобы сделать окно подвижным, вы можете использовать CaptionHeight из WindowChrome. то есть

   var windowChrome = 
            WindowChrome.GetWindowChrome(appWindow.Window);
            windowChrome.CaptionHeight = MainWindowToolbar.Height;
    WindowChrome.SetWindowChrome(appWindow.Window, windowChrome);

Но вы также должны установить присоединенное свойство WindowChrome.IsHitTestVisibleInChrome="True" для всех элементов управления в окне.

1
Alexey Perkin 26 Сен 2018 в 09:47