Chromium Embedded Framework bind key press

2019-05-11 04:50发布

问题:

I saw this thread on the official forum of Chromium Embedded Framework but it seems that there were no solutions given. To be honest, I'm not comfortable with C++ platform. Could you help me provide a snippet that binds CEF to the webapp.

I wanted to control the application using the default controls:

ALT+F4 - close
F5 - refresh browser

回答1:

Short Version: Implement CefKeyboardHandler, specifically OnPreKeyEvent()

ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
    const CefKeyEvent& event,
    CefEventHandle os_event,
    bool* is_keyboard_shortcut) {

    if (os_event && os_event->message == WM_SYSKEYDOWN) {
      case VK_F10: HandleF10(); break;
      case VK_F4: HandlerF4(); break; //Use GetKeyState(VK_MENU) to check if ALT is down...
    }
}

This follows the CefClient project, where ClientHandler implements CefKeyboardHandler. Check client_handler_win.cpp

Longer version follows...


Looking at this thread - Keyboard events "eaten" by browser - this stands out:

When the browser control has the focus, any keys being pressed seem to be eaten by the browser control, no matter whether they also can be handled by the browser control or not.

There are now two options:

  1. Intercept the key-press before it is sent to the CEF engine, which would require quite a little bit of digging into CEF and be platform specific.

  2. Capture the key-press using a normal Javascript event handler, and callback to C++.

  3. Intercept the key-press before the CEF engine processes it if CEF has such interfaces - this would ideally be platform independant.

Capture Keypress at Native-App level

On a windows machine, I tried searching for WM_KEYDOWN which is the usual practice in capturing key events (See Here). I was unable to get any hits on the CefClient project I was running, so this was a dead end.

Anybody with further info on this, please edit and add to this.

Capture Keypress in JS and callback to C++

Once the keypress goes into CefBrowser, we could always use Javascript to capture the keypress we want and then call an app handler, like so:

$(document).keypress(function (e) {
  ...
  NativeAppFunction();
  //Or NativeAppExtension.Function();
}

Communicating between JS and C++ is done through either V8Extensions, or by binding a Function to the CefContext. Further info at Javascript Integration

This comes with some pitfalls - your event-capturer is 'just another Javascript event handler', and with that comes all the uncertainties of when it is called (before or after other event handlers) and so on. Thankfully, CEF has a nifty little CefKeyboardHandler just to do what you want!

Intercept Keypress using CefKeyboardHandler

See cef_keyboard_handler.h - the doc for OnPreKeyEvent() says:

// Called before a keyboard event is sent to the renderer. |event| contains
// information about the keyboard event. |os_event| is the operating system
// event message, if any. Return true if the event was handled or false
// otherwise. If the event will be handled in OnKeyEvent() as a keyboard
// shortcut set |is_keyboard_shortcut| to true and return false.

From here, it's pretty straightforward. The CefEventHandle resolves to a platform specific (sadly - oh well!) standard Windows MSG. Note that Alt+F4 is a special system command:

When you press a key, the window that has keyboard focus receives one of the following messages.

WM_SYSKEYDOWN (or) WM_KEYDOWN

The WM_SYSKEYDOWN message indicates a system key, which is a key stroke that invokes a system command. There are two types of system key: ALT + any key and F10

Full text at MSDN