diff --git a/docs/doxygen/overviews/helloworld.h b/docs/doxygen/overviews/helloworld.h index 7a06ccf66a..8b2fefa5f7 100644 --- a/docs/doxygen/overviews/helloworld.h +++ b/docs/doxygen/overviews/helloworld.h @@ -51,24 +51,25 @@ menu and a status bar in its constructor. Also, any class that wishes to respond to any "event" (such as mouse clicks or messages from the menu or a button) must declare an event table using the macro below. -Finally, the way to react to such events must be done in "handlers". In our -sample, we react to three menu items, one for our custom menu command and two -for the standard "Exit" and "About" commands (any program should normally -implement the latter two). Notice that these handlers don't need to be neither -virtual nor public. +Finally, the way to react to such events must be done in "event handlers" which +are just functions (or functors, including lambdas if you're using C++11) +taking the @c event parameter of the type corresponding to the event being +handled, e.g. wxCommandEvent for the events from simple controls such as +buttons, text fields and also menu items. In our sample, we react to three menu +items, one for our custom menu command and two for the standard "Exit" and +"About" commands (any program should normally implement the latter two). Notice +that these handlers don't need to be neither virtual nor public. @code class MyFrame: public wxFrame { public: - MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + MyFrame(); private: void OnHello(wxCommandEvent& event); void OnExit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); - - wxDECLARE_EVENT_TABLE(); }; @endcode @@ -83,47 +84,31 @@ enum }; @endcode -Notice that you don't need to define identifiers for the "About" and "Exit". We -then proceed to actually implement an event table in which the events are -routed to their respective handler functions in the class MyFrame. - -There are predefined macros for routing all common events, ranging from the -selection of a list box entry to a resize event when a user resizes a window on -the screen. If @c wxID_ANY is given as the ID, the given handler will be -invoked for any event of the specified type, so that you could add just one -entry in the event table for all menu commands or all button commands etc. - -The origin of the event can still be distinguished in the event handler as the -(only) parameter in an event handler is a reference to a wxEvent object, which -holds various information about the event (such as the ID of and a pointer to -the class, which emitted the event). - -@code -wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(ID_Hello, MyFrame::OnHello) - EVT_MENU(wxID_EXIT, MyFrame::OnExit) - EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) -wxEND_EVENT_TABLE() -@endcode +Notice that you don't need to define identifiers for the "About" and "Exit" as +wxWidgets already predefines and the standard values such as wxID_ABOUT and +wxID_EXIT should be used whenever possible, as they can be handled in a special +way by a particular platform. As in all programs there must be a "main" function. Under wxWidgets main is -implemented using this macro, which creates an application instance and starts -the program. +implemented inside ::wxIMPLEMENT_APP() macro, which creates an application +instance of the specified class and starts running the GUI event loop. It is +used simply as: @code -wxIMPLEMENT_APP(MyApp) +wxIMPLEMENT_APP(MyApp); @endcode As mentioned above, wxApp::OnInit() is called upon startup and should be used to initialize the program, maybe showing a "splash screen" and creating the -main window (or several). The frame should get a title bar text ("Hello World") -and a position and start-up size. One frame can also be declared to be the top -window. Returning @true indicates a successful initialization. +main window (or several). As frames are created hidden by default, to allow +creating their child windows before showing them, we also need to explicitly +show it to make it appear on the screen. Finally, we return @true from this +method to indicate successful initialization: @code bool MyApp::OnInit() { - MyFrame *frame = new MyFrame( "Hello World", wxPoint(50, 50), wxSize(450, 340) ); + MyFrame *frame = new MyFrame(); frame->Show( true ); return true; } @@ -134,8 +119,8 @@ menu items as well as a status bar to be shown at the bottom of the main window. Both have to be associated with the frame with respective calls. @code -MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) - : wxFrame(NULL, wxID_ANY, title, pos, size) +MyFrame::MyFrame() + : wxFrame(NULL, wxID_ANY, "Hello World") { wxMenu *menuFile = new wxMenu; menuFile->Append(ID_Hello, "&Hello...\tCtrl-H", @@ -154,7 +139,8 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) CreateStatusBar(); SetStatusText( "Welcome to wxWidgets!" ); -} + + ... continued below ... @endcode Notice that we don't need to specify the labels for the standard menu items @@ -163,6 +149,32 @@ translated) labels and also standard accelerators correct for the current platform making your program behaviour more native. For this reason you should prefer reusing the standard ids (see @ref page_stockitems) if possible. +We also have to actually connect our event handlers to the events we want to +handle in them, by calling Bind() to send all the menu events, identified by +wxEVT_MENU event type, with the specified ID to the given function. The +parameters we pass to Bind() are + +-# The event type, e.g. wxEVT_MENU or wxEVT_BUTTON or wxEVT_SIZE or one + of many other events used by wxWidgets. +-# Pointer to the member function to call and the object to call it on. In + this case we just call our own function, hence we pass `this` for this + object itself, but we could call a member function of another object too. + And we could could also use a non-member function here, and, in fact, + anything that can be called passing it a wxCommandEvent could be used here. +-# The optional identifier allowing to select just some events of wxEVT_MENU + type, namely those from the menu item with the given ID, instead of handling + all of them in the provided handler. This is especially useful with the menu + items and rarely used with other kinds of events. + +@code + ... continued from above ... + + Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello); + Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT); + Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT); +} +@endcode + Here are the standard event handlers implementations. MyFrame::OnExit() closes the main window by calling Close(). The parameter @true indicates that other windows have no veto power such as after asking "Do you really want to close?". @@ -197,6 +209,17 @@ void MyFrame::OnHello(wxCommandEvent& event) } @endcode +@note In C++11 programs, it can be convenient to use unnamed lambdas instead of + functions for event handlers, especially when handling events from the + controls as this allows to keep the code creating the control and handling + its event together in the same place. Here, for example, we could replace + the wxID_EXIT handler with just + +@code + Bind(wxEVT_MENU, [=](wxCommandEvent&) { Close(true); }, wxID_EXIT); +@endcode + + Here is the entire program that can be copied and pasted: @code @@ -218,14 +241,12 @@ public: class MyFrame: public wxFrame { public: - MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + MyFrame(); private: void OnHello(wxCommandEvent& event); void OnExit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); - - wxDECLARE_EVENT_TABLE(); }; enum @@ -233,23 +254,17 @@ enum ID_Hello = 1 }; -wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(ID_Hello, MyFrame::OnHello) - EVT_MENU(wxID_EXIT, MyFrame::OnExit) - EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) -wxEND_EVENT_TABLE() - wxIMPLEMENT_APP(MyApp); bool MyApp::OnInit() { - MyFrame *frame = new MyFrame( "Hello World", wxPoint(50, 50), wxSize(450, 340) ); + MyFrame *frame = new MyFrame(); frame->Show( true ); return true; } -MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) - : wxFrame(NULL, wxID_ANY, title, pos, size) +MyFrame::MyFrame() + : wxFrame(NULL, wxID_ANY, "Hello World") { wxMenu *menuFile = new wxMenu; menuFile->Append(ID_Hello, "&Hello...\tCtrl-H", @@ -268,6 +283,10 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) CreateStatusBar(); SetStatusText( "Welcome to wxWidgets!" ); + + Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello); + Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT); + Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT); } void MyFrame::OnExit(wxCommandEvent& event)