Search code examples
c++keyboard-shortcutswxwidgetskeyboard-events

How to create a synthetic keyboard event in wxWidgets to trigger shortcuts set in a wxAcceleratorEntry?


I am using wxWebView in my application. Since this widget consumes all keyboard events internally, I have to create a synthetic keyboard event and process it. This is the code that I am using for creating a synthetic keyboard event:

        // create a synthetic keyboard event and handle it
        wxKeyEvent keyEvent( wxEVT_KEY_DOWN );
        keyEvent.SetEventObject( ctrl_ );
        auto key = url.substr( keyCodePrefix_.length() );
        if( key == "Escape" )
          keyEvent.m_keyCode = WXK_ESCAPE;
        else if( key == "F1" )
          keyEvent.m_keyCode = WXK_F1;
        else
          keyEvent.m_keyCode = WXK_NONE; 
        ctrl_->ProcessWindowEvent( keyEvent );

As you could see, I only handle Escape and F1 keys for now. The type of keyboard event that I am using is wxEVT_KEY_DOWN. Everything works fine. According to the doc, the keyboard is processed in the widget then is sent to the application. However it does not trigger the shortcuts are set in the parent window ( that contains wxWebView widget ) via wxAcceleratorTable.

How should I create a keyboard event that trigger shortcuts in my accelerator table?

I tried to set the type of keyboard event to wxEVT_CHAR but it also did not work.

Update: my event handler is like below:

class MyApp : public wxApp
{
  public:
    MyApp();
    bool OnInit() override;
    // ...

    bool ProcessEvent(wxEvent& event) override
    {
      if( event.GetEventType() == wxEVT_KEY_DOWN )
      {
        wxKeyEvent& ke = (wxKeyEvent&)event;
        if( ke.GetKeyCode() == WXK_ESCAPE )
        {
         // handle keyboard event
        }
        event.Skip(); // this does not help!
      }
      return wxApp::ProcessEvent( event );
    }

    // ...    
    DECLARE_EVENT_TABLE()
};

Solution

  • I used sendInput function of Win32 to create a synthetic key down event. It is exactly emulating keyboard events which means it triggers the shortcuts in accelerator table. Also be noticed that the keyboard event goes to the focused widget.

        INPUT inputs[ 2 ] = {};
        ZeroMemory( inputs, sizeof( inputs ) );
        auto key = url.substr( keyCodePrefix_.length() );
        if( key == "Escape" )
        {
          // key down
          inputs[ 0 ].type = INPUT_KEYBOARD;
          inputs[ 0 ].ki.wVk = VK_ESCAPE;
          // key up
          /*inputs[ 1 ].type = INPUT_KEYBOARD;
          inputs[ 1 ].ki.wVk = VK_ESCAPE;
          inputs[ 1 ].ki.dwFlags = KEYEVENTF_KEYUP;*/
        }
        else if( key == "F1" )
        {
          // key down
          inputs[ 0 ].type = INPUT_KEYBOARD;
          inputs[ 0 ].ki.wVk = VK_F1;
          // key up
          /*inputs[ 1 ].type = INPUT_KEYBOARD;
          inputs[ 1 ].ki.wVk = VK_F1;
          inputs[ 1 ].ki.dwFlags = KEYEVENTF_KEYUP;*/
        }
        SendInput( ARRAYSIZE( inputs ), inputs, sizeof( INPUT ) );