⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tevent.tex

📁 很牛的GUI源码wxWidgets-2.8.0.zip 可在多种平台下运行.
💻 TEX
📖 第 1 页 / 共 2 页
字号:
\section{Event handling overview}\label{eventhandlingoverview}Classes: \helpref{wxEvtHandler}{wxevthandler}, \helpref{wxWindow}{wxwindow}, \helpref{wxEvent}{wxevent}\subsection{Introduction}\label{eventintroduction}Before version 2.0 of wxWidgets, events were handled by the applicationeither by supplying callback functions, or by overriding virtual memberfunctions such as {\bf OnSize}.From wxWidgets 2.0, {\it event tables} are used instead, with a few exceptions.An event table is placed in an implementation file to tell wxWidgets how to mapevents to member functions. These member functions are not virtual functions, butthey are all similar in form: they take a single wxEvent-derived argument, and have a void returntype.Here's an example of an event table.\begin{verbatim}BEGIN_EVENT_TABLE(MyFrame, wxFrame)  EVT_MENU    (wxID_EXIT, MyFrame::OnExit)  EVT_MENU    (DO_TEST,   MyFrame::DoTest)  EVT_SIZE    (           MyFrame::OnSize)  EVT_BUTTON  (BUTTON1,   MyFrame::OnButton1)END_EVENT_TABLE()\end{verbatim}The first two entries map menu commands to two different member functions. TheEVT\_SIZE macro doesn't need a window identifier, since normally you are onlyinterested in the current window's size events.The EVT\_BUTTON macro demonstrates that the originating event does not have tocome from the window class implementing the event table -- if the event sourceis a button within a panel within a frame, this will still work, because eventtables are searched up through the hierarchy of windows for the command events.In this case, the button's event table will be searched, then the parentpanel's, then the frame's.As mentioned before, the member functions that handle events do not have to bevirtual. Indeed, the member functions should not be virtual as the eventhandler ignores that the functions are virtual, i.e. overriding a virtualmember function in a derived class will not have any effect. These memberfunctions take an event argument, and the class of event differs according tothe type of event and the class of the originating window. For size events, \helpref{wxSizeEvent}{wxsizeevent} is used. For menu commands and mostcontrol commands (such as button presses), \helpref{wxCommandEvent}{wxcommandevent} is used. When controls get morecomplicated, then specific event classes are used, such as \helpref{wxTreeEvent}{wxtreeevent} for events from \helpref{wxTreeCtrl}{wxtreectrl} windows.As well as the event table in the implementation file, there must also be aDECLARE\_EVENT\_TABLE macro somewhere in the class declaration. For example:{\small%\begin{verbatim}class MyFrame : public wxFrame{public:  ...  void OnExit(wxCommandEvent& event);  void OnSize(wxSizeEvent& event);protected:  int       m_count;  ...  DECLARE_EVENT_TABLE()};\end{verbatim}}%Note that this macro may occur in any section of the class (public, protectedor private) but that it is probably better to insert it at the end, as shown,because this macro implicitly changes the access to protected which may bequite unexpected if there is anything following it.Finally, if you don't like using macros for static initialization of the eventtables you may also use \helpref{wxEvtHandler::Connect}{wxevthandlerconnect} toconnect the events to the handlers dynamically, during run-time. See the\helpref{event sample}{sampleevent} for an example of doing it.\subsection{How events are processed}\label{eventprocessing}When an event is received from the windowing system, wxWidgets calls \helpref{wxEvtHandler::ProcessEvent}{wxevthandlerprocessevent} on the firstevent handler object belonging to the window generating the event.It may be noted that wxWidgets' event processing system implements somethingvery close to virtual methods in normal C++, i.e. it is possible to alterthe behaviour of a class by overriding its event handling functions. Inmany cases this works even for changing the behaviour of native controls.For example it is possible to filter out a number of key events sent by thesystem to a native text control by overriding wxTextCtrl and defining ahandler for key events using EVT\_KEY\_DOWN. This would indeed preventany key events from being sent to the native control - which might not bewhat is desired. In this case the event handler function has to call Skip()so as to indicate that the search for the event handler should continue.To summarize, instead of explicitly calling the base class version as youwould have done with C++ virtual functions (i.e. {\it wxTextCtrl::OnChar()}),you should instead call \helpref{Skip}{wxeventskip}.In practice, this would look like this if the derived text control onlyaccepts 'a' to 'z' and 'A' to 'Z':{\small%\begin{verbatim}void MyTextCtrl::OnChar(wxKeyEvent& event){    if ( isalpha( event.KeyCode() ) )    {       // key code is within legal range. we call event.Skip() so the       // event can be processed either in the base wxWidgets class       // or the native control.       event.Skip();    }    else    {       // illegal key hit. we don't call event.Skip() so the       // event is not processed anywhere else.       wxBell();    }}\end{verbatim}}%The normal order of event table searching by ProcessEvent is as follows:\begin{enumerate}\itemsep=0pt\item If the object is disabled (via a call to \helpref{wxEvtHandler::SetEvtHandlerEnabled}{wxevthandlersetevthandlerenabled})the function skips to step (6).\item If the object is a wxWindow, {\bf ProcessEvent} is recursively called on the window's\rtfsp\helpref{wxValidator}{wxvalidator}. If this returns true, the function exits.\item {\bf SearchEventTable} is called for this event handler. If this fails, the baseclass table is tried, and so on until no more tables exist or an appropriate function was found,in which case the function exits.\item The search is applied down the entire chain of event handlers (usually the chain has a lengthof one). If this succeeds, the function exits.\item If the object is a wxWindow and the event is set to set to propagate (in the library onlywxCommandEvent based events are set to propagate), {\bf ProcessEvent} is recursively appliedto the parent window's event handler. If this returns true, the function exits.\item Finally, {\bf ProcessEvent} is called on the wxApp object.\end{enumerate}{\bf Pay close attention to Step 5.}  People often overlook or getconfused by this powerful feature of the wxWidgets event processingsystem.  To put it a different way, events set to propagate (\helpref{See: wxEvent::ShouldPropagate}{wxeventshouldpropagate})(most likely derived either directly or indirectly from wxCommandEvent)will travel up the containment hierarchy from child to parent until the maximal propagation level is reached or an event handler is found thatdoesn't call \helpref{event.Skip()}{wxeventskip}.Finally, there is another additional complication (which, in fact, simplifieslife of wxWidgets programmers significantly): when propagating the commandevents upwards to the parent window, the event propagation stops when itreaches the parent dialog, if any. This means that you don't risk to getunexpected events from the dialog controls (which might be left unprocessed bythe dialog itself because it doesn't care about them) when a modal dialog ispopped up. The events do propagate beyond the frames, however. The rationalefor this choice is that there are only a few frames in a typical applicationand their parent-child relation are well understood by the programmer while itmay be very difficult, if not impossible, to track down all the dialogs whichmay be popped up in a complex program (remember that some are createdautomatically by wxWidgets). If you need to specify a different behaviour forsome reason, you can use \helpref{SetExtraStyle(wxWS\_EX\_BLOCK\_EVENTS)}{wxwindowsetextrastyle} explicitly to prevent the events from being propagated beyond the given windowor unset this flag for the dialogs which have it on by default.Typically events that deal with a window as a window (size, motion,paint, mouse, keyboard, etc.) are sent only to the window.  Eventsthat have a higher level of meaning and/or are generated by the windowitself, (button click, menu select, tree expand, etc.) are commandevents and are sent up to the parent to see if it is interested in theevent.Note that your application may wish to override ProcessEvent to redirect processing ofevents. This is done in the document/view framework, for example, to allow event handlersto be defined in the document or view. To test for command events (which will probablybe the only events you wish to redirect), you may use \helpref{wxEvent::IsCommandEvent}{wxeventiscommandevent} for efficiency, instead of using the slower run-time type system.As mentioned above, only command events are recursively applied to the parents eventhandler in the library itself. As this quite often causes confusion for users,here is a list of system events which will NOT get sent to the parent's event handler:\begin{twocollist}\itemsep=0pt\twocolitem{\helpref{wxEvent}{wxevent}}{The event base class}\twocolitem{\helpref{wxActivateEvent}{wxactivateevent}}{A window or application activation event}\twocolitem{\helpref{wxCloseEvent}{wxcloseevent}}{A close window or end session event}\twocolitem{\helpref{wxEraseEvent}{wxeraseevent}}{An erase background event}\twocolitem{\helpref{wxFocusEvent}{wxfocusevent}}{A window focus event}\twocolitem{\helpref{wxKeyEvent}{wxkeyevent}}{A keypress event}\twocolitem{\helpref{wxIdleEvent}{wxidleevent}}{An idle event}\twocolitem{\helpref{wxInitDialogEvent}{wxinitdialogevent}}{A dialog initialisation event}\twocolitem{\helpref{wxJoystickEvent}{wxjoystickevent}}{A joystick event}\twocolitem{\helpref{wxMenuEvent}{wxmenuevent}}{A menu event}\twocolitem{\helpref{wxMouseEvent}{wxmouseevent}}{A mouse event}\twocolitem{\helpref{wxMoveEvent}{wxmoveevent}}{A move event}\twocolitem{\helpref{wxPaintEvent}{wxpaintevent}}{A paint event}\twocolitem{\helpref{wxQueryLayoutInfoEvent}{wxquerylayoutinfoevent}}{Used to query layout information}\twocolitem{\helpref{wxSetCursorEvent}{wxsetcursorevent}}{Used for special cursor processing based on current mouse position}\twocolitem{\helpref{wxSizeEvent}{wxsizeevent}}{A size event}\twocolitem{\helpref{wxScrollWinEvent}{wxscrollwinevent}}{A scroll event sent by a scrolled window (not a scroll bar)}\twocolitem{\helpref{wxSysColourChangedEvent}{wxsyscolourchangedevent}}{A system colour change event}\end{twocollist}In some cases, it might be desired by the programmer to get a certain numberof system events in a parent window, for example all key events sent to, but notused by, the native controls in a dialog. In this case, a special event handlerwill have to be written that will override ProcessEvent() in order to passall events (or any selection of them) to the parent window.\subsection{Events generated by the user vs programmatically generated events}\label{progevent}While generically \helpref{wxEvents}{wxevent} can be generated both by useractions (e.g. resize of a \helpref{wxWindow}{wxwindow}) and by calls to functions(e.g. \helpref{wxWindow::SetSize}{wxwindowsetsize}), wxWidgets controlsnormally send \helpref{wxCommandEvent}{wxcommandevent}-derived events only forthe user-generated events. The only {\bf exceptions} to this rule are:\begin{twocollist}\itemsep=0pt\twocolitem{\helpref{wxNotebook::AddPage}{wxnotebookaddpage}}{No event-free alternatives}\twocolitem{\helpref{wxNotebook::AdvanceSelection}{wxnotebookadvanceselection}}{No event-free alternatives}\twocolitem{\helpref{wxNotebook::DeletePage}{wxnotebookdeletepage}}{No event-free alternatives}\twocolitem{\helpref{wxNotebook::SetSelection}{wxnotebooksetselection}}{Use \helpref{wxNotebook::ChangeSelection}{wxnotebookchangeselection} instead, as \helpref{wxNotebook::SetSelection}{wxnotebooksetselection} is deprecated}\twocolitem{\helpref{wxTreeCtrl::Delete}{wxtreectrldelete}}{No event-free alternatives}\twocolitem{\helpref{wxTreeCtrl::DeleteAllItems}{wxtreectrldeleteallitems}}{No event-free alternatives}\twocolitem{\helpref{wxTreeCtrl::EditLabel}{wxtreectrleditlabel}}{No event-free alternatives}\twocolitem{All \helpref{wxTextCtrl}{wxtextctrl} methods}{\helpref{wxTextCtrl::ChangeValue}{wxtextctrlchangevalue} can be used insteadof \helpref{wxTextCtrl::SetValue}{wxtextctrlsetvalue} but the other functions,such as \helpref{Replace}{wxtextctrlreplace} or \helpref{WriteText}{wxtextctrlwritetext} don't have event-free equivalents}\end{twocollist}% VZ: it doesn't work like this, but just in case we ever reenable this%     behaviour, I leave it here%% \subsection{Redirection of command events to the window with the focus}% % The usual upward search through the window hierarchy for command event% handlers does not always meet an application's requirements. Say you have two% wxTextCtrl windows in a frame, plus a toolbar with Cut, Copy and Paste% buttons. To avoid the need to define event handlers in the frame% and redirect them explicitly to the window with the focus, command events% are sent to the window with the focus first, for% menu and toolbar command and UI update events only. This means that% each window can handle its own commands and UI updates independently. In% fact wxTextCtrl can handle Cut, Copy, Paste, Undo and Redo commands and UI update% requests, so no extra coding is required to support them in your menus and% toolbars.\subsection{Pluggable event handlers}\label{pluggablehandlers}In fact, you don't have to derive a new class from a window classif you don't want to. You can derive a new class from wxEvtHandler instead,defining the appropriate event table, and then call\rtfsp\helpref{wxWindow::SetEventHandler}{wxwindowseteventhandler} (or, preferably,\rtfsp\helpref{wxWindow::PushEventHandler}{wxwindowpusheventhandler}) to make thisevent handler the object that responds to events. This way, you can avoida lot of class derivation, and use the same event handler object tohandle events from instances of different classes. If you ever have to call a window's event handlermanually, use the GetEventHandler function to retrieve the window's event handler and use thatto call the member function. By default, GetEventHandler returns a pointer to the window itselfunless an application has redirected event handling using SetEventHandler or PushEventHandler.One use of PushEventHandler is to temporarily or permanently change thebehaviour of the GUI. For example, you might want to invoke a dialog editorin your application that changes aspects of dialog boxes. You cangrab all the input for an existing dialog box, and edit it `in situ',before restoring its behaviour to normal. So even if the applicationhas derived new classes to customize behaviour, your utility can indulgein a spot of body-snatching. It could be a useful technique for on-linetutorials, too, where you take a user through a serious of steps anddon't want them to diverge from the lesson. Here, you can examine the eventscoming from buttons and windows, and if acceptable, pass them through tothe original event handler. Use PushEventHandler/PopEventHandlerto form a chain of event handlers, where each handler processes a differentrange of events independently from the other handlers.\subsection{Window identifiers}\label{windowids}\index{identifiers}\index{wxID}Window identifiers are integers, and are used touniquely determine window identity in the event system (though you can use itfor other purposes). In fact, identifiers do not need to be uniqueacross your entire application just so long as they are unique within aparticular context you're interested in, such as a frame and its children. Youmay use the {\tt wxID\_OK} identifier, for example, on any number of dialogs so

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -