Catching key events globally

From WxWiki

Jump to: navigation, search

Keyboard events go to the component that currently has focus and do not propagate to the parent; if you are trying to catch key events globally it can thus be a little tricky. Here are a few ways to solve this problem - keep in mind there are probably more than presented here.

Contents

[edit] Filter events

Source: http://wxforum.shadonet.com/viewtopic.php?p=66017#66017

Override wxApp::FilterEvent. This function is called early in event-processing, so you can do things like this (for F1):

snippet.cpp
int MyApp::FilterEvent(wxEvent& event)
{
    if ( event.GetEventType()==wxEVT_KEY_DOWN && ((wxKeyEvent&)event).GetKeyCode()==WXK_F1)
    {
        frame->OnHelpF1( (wxKeyEvent&)event );
        return true;
    }
 
    return -1;
}

This will work most of the time. It will fail if

  • Your application is not in the foreground. If you wish to catch keys even when your app is in the background, you will need to use platform-specific code
  • Your window-manager grabs the key for itself, in which case your app won't see it.
  • (Using wxGtk---I don't know about other platforms) the key is pressed while a modal wxDialog is showing, and the dialog doesn't have keyboard focus. The solution is to call SetFocus() on one of the dialog's children before calling ShowModal().

[edit] Recursive connect

You can recursively ->Connect() all components in a frame, therefore you will catch events no matter where the focus is.

void
MyDialog::createChilds(void)
{
  // create the childs: panels, textctrls, buttons, ...
 
  // ...
 
  /////////////////////////////////////
  // after creation:
  this->connectKeyDownEvent(this);
 
}
 
 
void
MyDialog::connectKeyDownEvent(wxWindow* pclComponent)
{
  if(pclComponent)
  {
    pclComponent->Connect(wxID_ANY,
                          wxEVT_KEY_DOWN,
                          wxKeyEventHandler(MyDialog::onKeyDown),
                          (wxObject*) NULL,
                          this);
 
    wxWindowListNode* pclNode = pclComponent->GetChildren().GetFirst();
    while(pclNode)
    {
      wxWindow* pclChild = pclNode->GetData();
      this->connectKeyDownEvent(pclChild);
     
      pclNode = pclNode->GetNext();
    }
  }
}
 
void
MyDialog::onKeyDown(wxKeyEvent& event)
{
  // do your event-processing here
 
}

Code author : clyde729 (Source : http://wxforum.shadonet.com/viewtopic.php?t=9361)

[edit] Register Hot Key

bool wxWindow::RegisterHotKey(int hotkeyId, int modifiers, int virtualKeyCode)

You can also make a hot key part of a menu item

editMenu->Append(MENU_EDIT_COPY,  _("Copy\tCtrl-C"));

[edit] Accelerator table

MyFrame::MyFrame(...) : wxFrame
{
    wxAcceleratorEntry entries[14];
    entries[0].Set(wxACCEL_CTRL, (int) 'O', MENU_LOAD_FILE);
    ...
    entries[12].Set(wxACCEL_NORMAL, WXK_SPACE, KEY_SPACE);
    entries[13].Set(wxACCEL_NORMAL, WXK_ESCAPE, KEY_ESC);
    wxAcceleratorTable accel(14, entries);
    SetAcceleratorTable(accel);
}
 
...
 
EVT_MENU(KEY_ESC,MyFrame::CheckAbort)
EVT_MENU(KEY_SPACE,MyFrame::CheckAbort)

Source : http://wxforum.shadonet.com/viewtopic.php?t=18140 Author : celstark

Personal tools