Я создал приложение, которое воспроизводит видео в браузере 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, но это выглядит немного странно.