Как отобразить диалог поиска в элементе управления WebView2?

У меня есть старое приложение C ++ MFC, обновленное для использования элемента управления веб-браузера WebView2 на основе Edge. В противном случае у меня все работает нормально, одна из оставшихся проблем — открытие в нем диалогового окна «Найти» через пункт меню «Редактировать-Найти» основного приложения MFC или через Ctrl + F (который также перехватывается фреймворком MFC). Что у меня сейчас есть:

m_webView->ExecuteScript(L"window.find(\"\", 0, 0, 0, 0, 0, 1);");

где m_webView — указатель на ICoreWebView2 интерфейс.

Проблема в том, что иногда он вызывает диалоговое окно «Найти», иногда — нет. Иногда это происходит после обновления страницы, иногда нет. Когда я закрываю диалоговое окно «Найти» из креста, он обычно отказывается открывать его снова.

Как я могу заставить его вести себя правильно? Может быть, есть способ, который не требует использования Javascript?

Обновление: похоже, это сработало только в том случае, если нажатие клавиши Ctrl + F каким-то образом было отправлено непосредственно в элемент управления WebView2, минуя MFC. Похоже, что указанная выше строка Javascript никогда не работала. Так, может быть, есть способ имитировать Ctrl + F для элемента управления WebView2?

Похоже на проблему управления фокусом — какой бы элемент управления в MFC был последним в фокусе, получает последовательность Ctrl + F.   —  person Paavo    schedule 02.07.2021

Правильно, в основном это была проблема с фокусом, обработчик событий GotFocus иногда перемещал фокус с элемента управления webview2. Тем не менее, похоже, нет способа заставить работать пункт меню «Правка-Найти». Да, я знаю, что меню сейчас не в моде …   —  person Paavo    schedule 02.07.2021

См. также:  Почему git не может видеть мое удаленное репо, которое, как я уверен, существует?
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 2
  1. Paavo

    AFAIK, WebView2 в настоящее время не поддерживает вызов или иное управление поиском в диалоговом окне страницы. Вы также можете обратиться к этой теме. На GitHub есть похожая ветка, и официальный представитель не дал решения.

    Вы можете использовать сочетание клавиш Ctrl + F непосредственно в элементе управления WebView2 или оставить отзыв об этой проблеме на странице отзывов о WebView2. Спасибо за понимание.

  2. Paavo

    Как ответил @ yu-zhou, официального способа сделать то, что я хотел, пока нет. На данный момент я вернулся к программной эмуляции Ctrl + F для элемента управления WebView2, но результат не так хорош. Для протокола я все еще представляю его здесь:

    Во-первых, пользователь должен хотя бы один раз щелкнуть элемент управления webview2, чтобы я мог записать его HWND в обработчике событий GotFocus, зарегистрированном с помощью add_GotFocus ():

    void MyHtmlView::OnGotFocus() {
        if (!m_webview2_hwnd) {
            m_webview2_hwnd = ::GetFocus();
        }
    }
    

    Теперь, когда я хочу вызвать панель поиска программно, мне нужно убедиться, что правильное окно сфокусировано, и отправить ему клавишу Ctrl + F. Увы, похоже, что элемент управления проверяет состояние клавиши Ctrl асинхронно, поэтому это становится немного сложнее, мне нужно изменить состояние клавиатуры для потока и добавить дополнительный обработчик событий для его последующего восстановления. После некоторых проб и ошибок я достиг этого (для краткости проверки ошибок опущены):

    void MyHtmlView::Find() {
    
        if (::GetFocus()!=m_webview2_hwnd) {
            ::SetFocus(m_webview2_hwnd);
        }
    
        std::uint8_t state[256];
        ::GetKeyboardState(state);
        bool restoreCtrlState = false;
        if ((state[VK_CONTROL] & 0x80)==0) {
            // Ctrl key is currently not pressed.
            // Mark it pressed.
            state[VK_CONTROL] |= 0x80;
            ::SetKeyboardState(state);
            restoreCtrlState = true;
        }
    
        std::thread auxThread([this, restoreCtrlState]() {
            ::SendMessage(m_webview2_hwnd, WM_KEYDOWN, 'F', 1);
            ::SendMessage(m_webview2_hwnd, WM_KEYUP, 'F', 1);
            if (restoreCtrlState) {
                ::PostMessage(m_hWnd, WM_COMMAND, ID_RESTORE_CONTROL_STATE, 0);
            }
        });
        auxThread.detach();
    }
    
    // This needs to be registered to handle ID_RESTORE_CONTROL_STATE
    void HtmlView::OnRestoreCtrlState() {
        std::uint8_t state[256];
        ::GetKeyboardState(state);
        if ((state[VK_CONTROL] & 0x80)!=0) {
            state[VK_CONTROL] &= ~0x80;
            ::SetKeyboardState(state);
        }
    }
    

    Излишне говорить, что этот хак может легко перестать работать, если они что-то изменят в реализации webview2.

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: