Заставить окно двигаться при перетаскивании мышью в любом месте в пределах окна? - PullRequest
0 голосов
/ 12 марта 2020

Я создал приложение, которое воспроизводит видео в браузере Webview2, установленном в WinForm. Webview2 пока официально не поддерживается в C#, я использую проект, найденный здесь

Этот элемент управления Webview2 не поддерживает создание событий мыши, они отключены в WebView2ControlBase.cs. Я не слишком уверен, почему, но я предполагаю, что это необходимо.

Моя цель для этого проекта - дать возможность дважды щелкнуть элемент управления, чтобы переключить «режим кино», где элемент управления расширяется, чтобы заполнить всю область формы, а также позволяют перемещать форму путем перетаскивания в любое место в пределах определенных границ внутри формы.

Я достиг этих целей, моя текущая реализация этого использует ловушку мыши для обнаружения событий мыши и вызова событие перетаскивания / двойного щелчка, если события произошли в границах формы и в то время, когда форма была активной.

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
    if(nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam) {
        Rectangle paddedBounds = MainWindow.Bounds;
        paddedBounds.Inflate(-50, -50); //to allow default drag behaviour on video controls
        if(paddedBounds.Contains(Cursor.Position)) {
            isMouseDown = true;
            MSLLHOOKSTRUCT MouseData = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            Offset = new Point(MouseData.pt.x - MainWindow.Location.X, MouseData.pt.y - MainWindow.Location.Y); //Offset of form location relative to where mouse was clicked
        }
    } else if(nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam) {
        if(MainWindow.ContainsFocus && isMouseDown) {
            performedDrag = true;
            MSLLHOOKSTRUCT MouseData = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            OnMouseDrag(null, new MouseEventArgs(MouseButtons.Left, 1, MouseData.pt.x, MouseData.pt.y, 0));
        }
    } else if(nCode >= 0 && MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam) {
        if(isMouseDown && MainWindow.Bounds.Contains(Cursor.Position) && MainWindow.ContainsFocus) {
            isMouseDown = false;
            MSLLHOOKSTRUCT MouseData = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            if(performedDrag) {
                performedDrag = false;
                return new IntPtr(1); //intercepts mouseup event to avoid clicking which would cause video to pause after drag
            }
            if(ClickTime == 0) { //For determining double-click to toggle cinema mode
                ClickTime = MouseData.time;
            } else {
                if(MouseData.time - ClickTime > DoubleClickTime) {
                    ClickTime = MouseData.time;
                } else {
                    OnDoubleClick(null, new MouseEventArgs(MouseButtons.Left, 1, MouseData.pt.x, MouseData.pt.y, 0));
                    ClickTime = 0;
                }
            }
        }
    }
    return CallNextHookEx(HookID, nCode, wParam, lParam);
}

И когда событие перетаскивания возбуждено: (это просто возвращает new Point(location.X - Offset.X, location.Y - Offset.Y);)

private void MainWindow_OnMouseDrag(object sender, MouseEventArgs e) {
    Location = MouseHook.OffsetLocation(e.Location);
}

Это работает несколько хорошо, но есть несколько проблем:

  • После перетаскивания при следующем щелчке мыши (будь то в моем приложении или любом другом приложении) игнорируется, поэтому требуется второй щелчок. Это связано с возвратом IntPtr (1) для игнорирования события mouseup после перетаскивания, что необходимо для предотвращения приостановки видео после перетаскивания.

  • Когда мое приложение получает фокус, иногда запускает событие перетаскивания, даже если мышь не удерживается. Не слишком уверен, что вызывает это, но я могу воспроизвести его на 100%, переместив окно в нижнюю часть рабочего стола, а затем отфокусировав его и перефокусировав его, щелкнув предварительный просмотр на панели задач.

Могли ли я внести какие-либо улучшения в свой код или в другие возможные реализации события перетаскивания, которые я мог попробовать?

Я думал, что смогу решить первую проблему, имитируя щелчок после перетаскивания, где-то, что не чтобы что-то произошло, просто чтобы снова вызвать событие mouseup, но это выглядит немного странно.

...