Cross-Platform GUI Programming with wxWidgets

Normally, wxWidgets sends an event to the window (or other event handler) that generated it. If it's a command event, it might work its way up the window hierarchy before being processed (see Appendix H, "How wxWidgets Processes Events," for details). For example, clicking on a copy toolbar button will cause the toolbar event table to be searched, then the frame that contains it, and then the application object. Although this may work fine if you support only one kind of copy command, there is a problem if you also want the copy command to apply both to your main editing window (say a drawing application) and to any focused text controls in the main window, for example. The text controls will never get copy commands from the toolbar button (or menu item) because it is wired to a custom event handler. In this case, it would be more appropriate to send the command to the focused control first. Then, if the focused control implements this command (such as wxID_COPY), it will be processed. If it doesn't, then the command will rise up the window hierarchy until it gets to the custom wxID_COPY event handler. The end result will be a more natural way of working, with commands applying to the data that the user is currently editing.

We can override the main frame's ProcessEvent function to catch command events and redirect them to the focused control (if any), as follows:

bool MainFrame::ProcessEvent(wxEvent& event) { static wxEvent* s_lastEvent = NULL; // Check for infinite recursion if (& event == s_lastEvent) return false; if (event.IsCommandEvent() && !event.IsKindOf(CLASSINFO(wxChildFocusEvent)) && !event.IsKindOf(CLASSINFO(wxContextMenuEvent))) { s_lastEvent = & event; wxControl *focusWin = wxDynamicCast(FindFocus(), wxControl); bool success = false; if (focusWin) success = focusWin->GetEventHandler() ->ProcessEvent(event); if (!success) success = wxFrame::ProcessEvent(event); s_lastEvent = NULL; return success; } else { return wxFrame::ProcessEvent(event); } }

Currently, this is most useful when the focused control is a wxTextCtrl because for this control (on most platforms), wxWidgets supplies standard UI update and command handlers for common commands, including wxID_COPY, wxID_CUT, wxID_PASTE, wxID_UNDO, and wxID_REDO. However, you can always implement these handlers for arbitrary controls in your application or subclasses of existing wxWidgets controls such as wxStyledTextCtrl (see examples/chap20/pipedprocess for a wxStyledTextCtrl implementation enhanced in this way).

    Категории