Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets...

28

Transcript of Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets...

Page 1: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,
Page 2: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

Getting StartedThe structure of a simple wxWidgets

program,

Look at where and how a wxWidgets application starts and ends,

how to show the main window, and

how to react to commands from the user.

Page 3: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

A SMALL WXWIDGETS SAMPLEThe minimal wxWidgets application shows a

main window (a wxFrame) with a menu bar and status bar.

The menus allow you to show an “about box” or quit the program.

Shows some of the basic principles of wxWigets Application

Page 4: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

Minimal Application

Page 5: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE APPLICATION CLASS Every wxWidgets application defines an application class deriving from

wxApp.

There is only one instance of it, and this instance represents the running application.

The class should define an OnInit function that will be called when wxWidgets is ready to start running your code (equivalent to main or WinMain when writing a C or Win32 application).

Here is the smallest application class declaration you can sensibly write:

// Declare the application class class MyApp : public wxApp { public: // Called on application startup virtual bool OnInit(); };

Page 6: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE APPLICATION CLASS The implementation of OnInit usually

creates at least one window, interprets any command-line arguments, sets up data for the application, and performs any other initialization tasks required for the application.

If the function returns true, wxWidgets starts the event loop that processes user input and runs event handlers as necessary.

If the function returns false, wxWidgets will clean up its internal structures, and the application will terminate.

A simple implementation of OnInit might look like this:

bool MyApp::OnInit() { // Create the main application window MyFrame *frame = new MyFrame(wxT(“Minimal wxWidgets App”)); // Show it frame->Show(true); // Start the event loop return true; }

Page 7: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE APPLICATION CLASS This creates an instance of our new class MyFrame , shows it, and

returns true to start the event loop.

Unlike child windows, top-level windows such as frames and dialogs need to be shown explicitly after creation.

The frame title is passed to the constructor wrapped in the wxT() macro.

You’ll see this used a lot in wxWidgets samples and in the library code itself— it converts string and character literals to the appropriate type to allow the application to be compiled in Unicode mode.

This macro is also known by the alias _T().

There is no run-time performance penalty for using it. (You’ll also see the underscore macro _() used to enclose strings, which tells wxWidgets to translate the string. (International Applications)

Page 8: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE APPLICATION CLASSWhere is the code that creates the instance of

MyApp? wxWidgets does this internally, but still need to

tell wxWidgets what kind of object to create.

So add a macro in your implementation file:

// Give wxWidgets the means to create a MyApp object IMPLEMENT_APP(MyApp)

Page 9: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE APPLICATION CLASSWithout specifying the class, wxWidgets would

not know how to create a new application object.

This macro also inserts code that checks that the application and library were compiled using the same build configuration,

This allows wxWidgets to report accidental mismatches that might later cause a hard-to debug run-time failure.

Page 10: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE APPLICATION CLASSWhen wxWidgets creates a MyApp object, it assigns the

result to the global variable wxTheApp.

You can use this in your application, but it would be more convenient if you didn’t have to cast the wxApp pointer to MyApp.

By inserting this macro after your application class declaration:

// Implements MyApp& wxGetApp()DECLARE_APP(MyApp)

you can then call the function wxGetApp, which returns a reference to the MyApp object.

Page 11: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

TipEven if you don’t use DECLARE_APP, you can

still use the variable wxTheApp to call wxApp functions.

This will avoid the need to include your specific application header.

It can be useful within code (such as a library) that doesn’t know about specific application classes, and to save compilation time.

Page 12: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE FRAME CLASS A frame is a top-level window that contains other windows, and usually has a title bar

and menu bar.

Here’s our simple frame class declaration that we will put after the declaration of MyApp:

// Declare our main frame class class MyFrame : public wxFrame { public: // Constructor MyFrame(const wxString& title); // Event handlers void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); private: // This class handles events DECLARE_EVENT_TABLE() };

Our frame class has a constructor, two event handlers to link menu commands to C++ code, and a macro to tell wxWidgets that this class handles events.

Page 13: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE EVENT HANDLERSAs you may have noticed, the event handler

functions in MyFrame are not virtual and should not be virtual.

How, then, are they called? The answer lies in the event table, as follows.

// Event table for MyFrameBEGIN_EVENT_TABLE(MyFrame, wxFrame)EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)EVT_MENU(wxID_EXIT, MyFrame::OnQuit)END_EVENT_TABLE()

Page 14: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE EVENT HANDLERSAn event table, placed in a class’s implementation file,

tells wxWidgets how events coming from the user or from other sources are routed to member functions.

With the event table shown previously, mouse clicks on menu items with the identifiers wxID_EXIT and wxID_ABOUT are routed to the functions MyFrame::OnQuit and MyFrame::OnAbout, respectively.

EVT_MENU is just one of many event table macros you can use to tell wxWidgets what kind of event should be routed to what function.

Page 15: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE EVENT HANDLERSThe identifiers used here are predefined by

wxWidgets, but you will often define your own identifiers, using enums, consts,or preprocessor defines.

This kind of event table is a static way of routing events, and cannot be changed at runtime.

We will see how to set up dynamic event handlers.

Page 16: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE EVENT HANDLERSThe two functions we’re using as event handlers.

void MyFrame::OnAbout(wxCommandEvent& event)

{ wxString msg; msg.Printf(wxT(“Hello and welcome to %s”), wxVERSION_STRING); wxMessageBox(msg, wxT(“About Minimal”), wxOK | wxICON_INFORMATION, this);

}

Page 17: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE EVENT HANDLERSvoid MyFrame::OnQuit(wxCommandEvent&

event){

// Destroy the frame Close();

}

Page 18: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE EVENT HANDLERSMyFrame::OnAbout shows a message box when the user

clicks on the About menu item.

wxMessageBox takes a message, a caption, a combination of styles, and a parent window.

MyFrame::OnQuit is called when the user clicks on the Quit menu item,

It calls Close to destroy the frame, triggering the shutdown of the application, because there are no other frames.

Close doesn’t directly destroy the frame—it generates a wxEVT_CLOSE_WINDOW event, and the default handler for this event destroys the frame using wxWindow::Destroy.

Page 19: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE EVENT HANDLERS There’s another way the frame can be closed and the application shut

down: the user can click on the close button on the frame, or select Close fromthe system (or window manager) menu.

How does OnQuit get called in this case?

Well, it doesn’t—instead, wxWidgets sends a wxEVT_CLOSE_WINDOW event to the frame via Close (as used in OnQuit).

wxWidgets handles this event by default and destroys the window.

The application can override this behavior and provide its own event handler—for example, if you want to ask the user for confirmation before closing.

Most applications should provide an OnExit function in its application class to clean up data structures before quitting. Note that this function is only called if OnInit returns true.

Page 20: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE FRAME CONSTRUCTOR Finally, we have the frame constructor, which implements the frame icon,

a menu bar, and a status bar.

#include “mondrian.xpm” MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY,

title) { // Set the frame icon SetIcon(wxIcon(mondrian_xpm));

// Create a menu bar wxMenu *fileMenu = new wxMenu;

// The “About” item should be in the help menu wxMenu *helpMenu = new wxMenu; helpMenu->Append(wxID_ABOUT, wxT(“&About...\tF1”), wxT(“Show

about dialog”)); fileMenu->Append(wxID_EXIT, wxT(“E&xit\tAlt-X”), wxT(“Quit this

program”));

Page 21: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

// Now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append(fileMenu, wxT(“&File”)); menuBar->Append(helpMenu, wxT(“&Help”));

// ... and attach this menu bar to the frame SetMenuBar(menuBar);

// Create a status bar just for fun CreateStatusBar(2); SetStatusText(wxT(“Welcome to wxWidgets!”)); }

Page 22: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE FRAME CONSTRUCTOR This constructor calls the base constructor with the parent

window (none, hence NULL), window identifier, and title.

The identifier argument is wxID_ANY, which tells wxWidgets to generate an identifier itself.

The base constructor creates the actual window associated with the C++ instance—another way to achieve this is to call the default constructor of the base class, and then explicitly call wxFrame::Create from within the MyFrame constructor.

Small bitmaps and icons can be implemented using the XPM format on all platforms.

SetIcon line creates an icon on the stack using the C++ variable mondrian_xpm defined in mondrian.xpm, and associates it with the frame.

Page 23: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE FRAME CONSTRUCTORMenu items are added using the identifier (such as the

standard identifier wxID_ABOUT), the label to be displayed, and a help string to be shown on the status bar.

Within each label, a mnemonic letter is marked by a preceding ampersand, and an accelerator is preceded by the tab character (\t). A mnemonic is the letter a user presses to highlight a particular item when the menu is displayed.

An accelerator is a key combination (such as Alt+X) that can be used to perform that action without showing the menu at all.

The last thing that the constructor does is to create a status bar with two fields at the bottom of the frame and set the first field to the string “Welcome to wxWidgets!”

Page 24: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

THE WHOLE PROGRAMNormally, we have a separate header file and

implementation file, but for such a simple program, we can put it all in the same file.

Page 25: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

// Name: minimal.cpp // Purpose: Minimal wxWidgets sample // Author: You #include “wx/wx.h”

class MyApp : public wxApp { public: // Called on application startup virtual bool OnInit(); }; // Declare our main frame class class MyFrame : public wxFrame { public: // Constructor MyFrame(const wxString& title); // Event handlers void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); private: // This class handles events DECLARE_EVENT_TABLE() };

Page 26: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

// Implements MyApp& GetApp() DECLARE_APP(MyApp) // Give wxWidgets the means to create a MyApp object IMPLEMENT_APP(MyApp) // Initialize the application bool MyApp::OnInit() { // Create the main application window MyFrame *frame = new MyFrame(wxT(“Minimal wxWidgets App”)); // Show it frame->Show(true); // Start the event loop return true; } // Event table for MyFrame BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) EVT_MENU(wxID_EXIT, MyFrame::OnQuit) END_EVENT_TABLE() void MyFrame::OnAbout(wxCommandEvent& event) { wxString msg; msg.Printf(wxT(“Hello and welcome to %s”), wxVERSION_STRING);

Page 27: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

wxMessageBox(msg, wxT(“About Minimal”), wxOK | wxICON_INFORMATION, this); } void MyFrame::OnQuit(wxCommandEvent& event) { // Destroy the frame Close(); } #include “mondrian.xpm” MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title) { // Set the frame icon SetIcon(wxIcon(mondrian_xpm)); // Create a menu bar wxMenu *fileMenu = new wxMenu; // The “About” item should be in the help menu wxMenu *helpMenu = new wxMenu; helpMenu->Append(wxID_ABOUT, wxT(“&About...\tF1”),wxT(“Show about dialog”)); fileMenu->Append(wxID_EXIT, wxT(“E&xit\tAlt-X”),wxT(“Quit this program”)); // Now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append(fileMenu, wxT(“&File”)); menuBar->Append(helpMenu, wxT(“&Help”)); // ... and attach this menu bar to the frame SetMenuBar(menuBar); // Create a status bar just for fun CreateStatusBar(2); SetStatusText(wxT(“Welcome to wxWidgets!”)); }

Page 28: Getting Started The structure of a simple wxWidgets program, Look at where and how a wxWidgets application starts and ends, how to show the main window,

PROGRAM FLOW This is how the application starts running:

1. Depending on platform, the main, WinMain, or equivalent function runs (supplied by wxWidgets, not the application). wxWidgets initializes its internal data structures and creates an instance of MyApp.

2. wxWidgets calls MyApp::OnInit, which creates an instance of MyFrame.

3. The MyFrame constructor creates the window via the wxFrame constructor and adds an icon, menu bar, and status bar.

4. MyApp::OnInit shows the frame and returns true.

5. wxWidgets starts the event loop, waiting for events and dispatching them to the appropriate handlers.

The application terminates when the frame is closed, when the user either selects the Quit menu item or closes the frame via standard buttons or menus (these will differ from one platform to the next).