Chapter 4 Window Basics

In this chapter, we’ll first look at the main elements of a window before describing the window classes that are most commonly used in applications. These elements will almost certainly be familiar from other programming you’ve done or from applications you’ve used. Despite the differences between systems, the available controls are surprisingly similar in functionality, with wxWidgets handling nearly all of the differences. Remaining differences are usually handled using optional platform-specific window styles.

Anatomy of a Window

Naturally, you know what a window is, but for a full understanding of how to use the wxWidgets API, it’s good to have a grasp of the window model that wxWidgets uses. This differs in small respects from the window model used on each individual platform. Figure 4-1 shows the basic elements of a window.

Figure 4-1 The elements of a window

The elements of a window

The Concept of a Window

A window is any rectangular area with a common set of properties: it can be resized, it can paint itself, it can be shown and hidden, and so on. It may contain other windows (such as a frame with menu bar, toolbar, and status bar), or no child windows (such as a static text control). Normally, a window that you see on the screen in a wxWidgets application has a corresponding object of the wxWindow class or derived class, but this is not always the case: for example, the drop-down list in a native wxComboBox is not usually modeled with a separate wxWindow.

Client and Non-Client Areas

When we refer to the size of a window, we normally include the outer dimensions, including decorations such as the border and title bar. When we refer to the size of the client area of a window, we mean the area inside the window that can be drawn upon or into which child windows may be placed. A frame’s client area excludes any space taken by the menu bar, status bar, and toolbar.

Scrollbars

Most windows are capable of showing scrollbars, managed by the window rather than added explicitly by the application. The client area is then reduced by the space used by the scrollbars. For optimization, only windows that have the wxHSCROLL and wxVSCROLL style are guaranteed to own their own scrollbars. More information on scrolling can be found later in this chapter when we discuss wxScrolledWindow.

Caret and Cursor

A window can have a wxCaret (for displaying the current text position) and a wxCursor (for displaying the current mouse position). When the mouse enters a window, wxWidgets automatically displays the cursor that has been set for the window. When a window receives the focus, the caret (if any) will be shown at its current position, or at the mouse position if the focus was a result of a mouse button click.

Top-Level Windows

Windows are broadly divided into top-level windows (wxFrame, wxDialog, wxPopup) and other windows. Only top-level windows may be created with a NULL parent, and only top-level windows have delayed destruction (they are not deleted until idle time, when all other events have been processed). Except for pop-up windows, top-level windows can have decorations such as title bars and close buttons and can normally be dragged around the screen and resized, if the application allows it.

Coordinate System

The coordinate system always has (0, 0) at the top-left corner, and window dimensions are in pixels. The origin and scale can be changed for a device context that is used to paint on the window. For more on device contexts, see Chapter 5, “Drawing and Printing.”

Painting

When a window needs to be painted, it receives two events, wxEVT_ERASE_BACKGROUND to paint the background, and wxEVT_PAINT to paint the foreground. Ready-to-use classes such as wxButton paint themselves, but to create your own special window class, you will need to handle these events. You can optimize painting by getting the update region (the part that needs refreshing) from the window.

Color and Font

Every window has background and foreground color settings that can be used to determine the background color and (less commonly) foreground color. The default background erase handler uses the window’s background color, or if none has been set, the appropriate color or texture for the current color scheme or theme. A window also has a font setting, which may or may not be used depending on the kind of window.

Window Variant

On Mac OS X, a window has the concept of window variant, whereby it can be shown in a selection of sizes: wxWINDOW_VARIANT_NORMAL (the default), wxWINDOW_VARIANT_SMALL, wxWINDOW_VARIANT_MINI, or wxWINDOW_VARIANT_LARGE. Changing to a smaller variant is useful when you have a lot of information to convey and limited space, but it should be used in moderation. Some applications use the small variant throughout.

Sizing

When a window is resized, either by the application or by the user, it receives a wxEVT_SIZE event. If the window has children, they will need to be positioned and sized appropriately, and the recommended way is to use sizers, as discussed in Chapter 7, “Window Layout Using Sizers.” Most stock windows have a notion of a default size and position if you pass them wxDefaultSize or wxDefaultPosition (or -1 as an individual size or position value). To this end, each control implements DoGetBestSize, which returns a reasonable default size based on the control content, current font, and other factors.

Input

Any window can receive input from the mouse at any time, unless another window has temporarily captured the mouse or the window is disabled. Only the window with the current focus can receive keyboard input. An application can set the window focus itself; wxWidgets also sets the focus to a window when the user clicks on it. The wxEVT_SET_FOCUS event is sent to a window that is receiving the focus; wxEVT_KILL_FOCUS is sent when the focus is moving to a different window. See Chapter 6, “Handling Input,” for more details on handling input.

Idle Time Processing and UI Updates

All windows are (unless otherwise specified) recipients of idle events (wxEVT_IDLE), which are sent when all other events have been processed, specified with the EVT_IDLE(func) macro. For more information, see “Idle Time Processing” in Chapter 17, “Writing Multithreaded Applications.”

A special kind of idle time processing is user interface updating, in which all windows can specify a function that updates the window’s state. This function is called periodically in idle time. In the descriptions of events that follow, EVT_UPDATE_UI(id, func) is usually omitted for brevity. User interface updating is covered in Chapter 9, “Creating Custom Dialogs.”

Window Creation and Deletion

In general, windows are created on the heap with new, but see Chapter 15, “Memory Management, Debugging, and Error Checking,” for details and exceptions. Most window classes allow creation either in one or two steps. wxButton has typical constructor signatures:

wxButton();
wxButton(wxWindow* parent,
    wxWindowID id,
    const wxString& label = wxEmptyString,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize,
    long style = 0,
    const wxValidator& validator = wxDefaultValidator,
    const wxString& name = wxT("button"));

The following example of one-step construction takes advantage of all the constructor’s default values:

wxButton* button  = new wxButton(parent, wxID_OK);

Unless the window is a frame or dialog, you must pass a non-NULL parent window to the constructor. This will automatically add the child window to the parent, and when the parent is destroyed, the children will also be destroyed. As we’ve seen previously, you pass a standard or user-defined identifier to the window for the purposes of uniquely identifying it. You can also pass wxID_ANY, and wxWidgets will generate a suitable identifier (a negative value, to differentiate it from user-defined or standard identifiers). You can pass a position and size to the window, a validator, if appropriate (see Chapter 9), a style (see the following), and a string name. You can pass an arbitrary string to the name parameter, or ignore it; it is rarely used now but was introduced to allow window customization under Xt and Motif, which require controls to be identified by name.

With two-step construction, you use the default constructor and then call Create, which has the same signature as the full constructor. For example, to create a button in two steps:

wxButton* button  = new wxButton;
button->Create(parent, wxID_OK);

Only when you call Create is the underlying window created, and a wxEVT_CREATE event sent to the window in case it needs to do further processing at this point.

Why would you want to use two-step construction? One reason is that you may want to delay full creation of the window until it’s really required. Another is to set some properties of the window before Create is called, especially if those properties are used within the Create call. For example, you may want to set the wxWS_EX_VALIDATE_RECURSIVELY extra style (which must be set with SetExtraStyle). In the case of a dialog, this style is used from within its Create function when initial validation takes place, so if you need it, it’s important to set it before the dialog is created.

When you create a wxWindow, or any non-top-level derived window class, it is always in a visible state—so if the parent is visible at the time of creation, the window will also be visible. You can then use Show(false) to hide it if required. This is different from wxDialog and wxFrame, which are initially created in a hidden state to enable the application to lay out the controls without initial flicker, before showing with Show or (for modal dialogs) ShowModal.

Windows are deleted by calling Destroy (for top-level windows) or delete (for child windows), and the wxEVT_DESTROY event is sent just before the actual window is destroyed. In fact, child windows are deleted automatically, so it is rare to delete them explicitly.

Window Styles

A window has a style and an extra style. Window styles are a concise way to specify alternative behavior and appearances for windows when they are created. The symbols are defined in such as way that they can be combined in a “bit-list” using the C++ bitwise-or operator. For example:

wxCAPTION ¦ wxMINIMIZE_BOX ¦ wxMAXIMIZE_BOX ¦ wxTHICK_FRAME

The wxWindow class has a basic set of styles, such as border styles, and each derived class may add further styles. The “extra” style accommodates values that cannot fit into the style value.

A Quick Guide to the Window Classes

The rest of this chapter provides you with enough detailed information about the most commonly used window classes for you to apply them to your own applications. However, if you are reading this book for the first time, you may want to skip ahead to Chapter 5 and browse the window descriptions later.

Here’s a summary of the classes we cover, to help you navigate this chapter. For other window classes, see Chapter 12, “Advanced Window Classes,” and Appendix E, “Third-Party Tools for wxWidgets.”

Base Window Classes

These base classes implement functionality for derived concrete classes.

Image   wxWindow. The base class for all windows.

Image   wxControl. The base class for controls, such as wxButton.

Image   wxControlWithItems. The base class for multi-item controls.

Top-Level Windows

Top-level windows usually exist independently on the desktop.

Image   wxFrame. A resizable window containing other windows.

Image   wxMDIParentFrame. A frame that manages other frames.

Image   wxMDIChildFrame. A frame managed by a parent frame.

Image   wxDialog. A resizable window for presenting choices.

Image   wxPopupWindow. A transient window with minimal decoration.

Container Windows

Container windows manage child windows.

Image   wxPanel. A window for laying out controls.

Image   wxNotebook. A window for switching pages using tabs.

Image   wxScrolledWindow. A window that scrolls children and graphics.

Image   wxSplitterWindow. A window that manages two child windows.

Non-Static Controls

These controls can be edited by the user.

Image   wxButton. A push-button control with a text label.

Image   wxBitmapButton. A push-button control with a bitmap label.

Image   wxChoice. A drop-down list of choices.

Image   wxComboBox. An editable field with a list of choices.

Image   wxCheckBox. A control representing a check box, on or off.

Image   wxListBox. A list of selectable string items.

Image   wxRadioBox. A grid of radio buttons.

Image   wxRadioButton. A control resembling a radio button, on or off.

Image   wxScrollBar. A scrollbar control.

Image   wxSpinButton. Arrows for incrementing/decrementing values.

Image   wxSpinCtrl. A text field and spin button for editing integers.

Image   wxSlider. A control for changing a value within a given range.

Image   wxTextCtrl. A single- or multiple-line text entry field.

Image   wxToggleButton. A button that can be toggled on and off.

Static Controls

These controls present information and cannot be edited by the user.

Image   wxGauge. A control showing a quantity.

Image   wxStaticText. A control that shows a text label.

Image   wxStaticBitmap. A control that shows a bitmap label.

Image   wxStaticLine. A control displaying a line.

Image   wxStaticBox. A control displaying a box around other controls.

Menus

Menus are transient windows containing lists of commands.

Image   wxMenu. A menu that can be used as a popup or in a menu bar.

Control Bars

Control bars present concise access to commands and information, usually within a wxFrame.

Image   wxMenuBar. A menu bar that presents commands in a wxFrame.

Image   wxToolBar. A toolbar that provides quick access to commands.

Image   wxStatusBar. A status bar that shows information in multiple fields.

Base Window Classes

It’s worth mentioning base classes that you may or may not be able use directly but that implement a lot of functionality for derived classes. Use the API reference for these (and other) base classes as well as the reference for the derived classes to get a full understanding of what’s available.

wxWindow

wxWindow is both an important base class and a concrete window class that you can instantiate. However, it’s more likely that you will derive classes from it (or use pre-existing derived classes) than use it on its own.

As we’ve seen, a wxWindow may be created either in one step, using a non-default constructor, or two steps, using the default constructor followed by Create. For one-step construction, you use this constructor:

wxWindow(wxWindow* parent,
    wxWindowID id,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize,
    long style = 0,
    const wxString& name = wxT("panel"));

For example:

wxWindow* win  = new wxWindow(parent, wxID_ANY,
    wxPoint(100, 100), wxSize(200, 200));

wxWindow Styles

Each window class may add to the basic styles defined for wxWindow, listed in Table 4-1. Not all native controls support all border styles, and if no border is specified, a default style appropriate to that class will be used. For example, on Windows, most wxControl-derived classes use wxSUNKEN_BORDER by default, which will be interpreted as the border style for the current theme. An application may suppress the default border by using a style such as wxNO_BORDER.

Table 4-1 Basic Window Styles

Image

Table 4-2 lists extra styles that cannot be accommodated in the regular style and that are set using wxWindow::SetExtraStyle.

Table 4-2 Basic Extra Window Styles

Image

wxWindow Events

wxWindow and all its derived classes generate the events listed in Table 4-3. Events generated by mouse, keyboard, or joystick input are covered in Chapter 6.

Table 4-3 wxWindow Events

Image

wxWindow Member Functions

Because wxWindow is the base class for all other window classes, it has the largest number of member functions. We can’t describe them all here in detail, so instead we present a summary of some of the most important functions. Browsing them should give you a good idea of the general capabilities of windows, and you can refer to the reference manual for details of parameters and usage.

CaptureMouse captures all mouse input, and ReleaseMouse releases the capture. This is useful in a drawing program, for example, so that moving to the edge of the canvas scrolls it rather than causing another window to be activated. Use the static function GetCapture to retrieve the window with the current capture (if it’s within the current application), and HasCapture to determine if this window is capturing input.

Centre (Center), CentreOnParent (CenterOnParent), and CentreOnScreen (CenterOnScreen) center the window relative to the screen or the parent window.

ClearBackground clears the window by filling it with the current background color.

ClientToScreen and ScreenToClient convert between coordinates relative to the top-left corner of this window, and coordinates relative to the top-left corner of the screen.

Close generates a wxCloseEvent whose handler usually tries to close the window. Although the default close event handler will destroy the window, calling Close may not actually close the window if a close event handler has been provided that doesn’t destroy the window.

ConvertDialogToPixels and ConvertPixelsToDialog convert between dialog and pixel units, which is useful when basing size or position on font size in order to give more portable results.

Destroy destroys the window safely. Use this function instead of the delete operator because different window classes can be destroyed differently. Frames and dialogs are not destroyed immediately when this function is called but are added to a list of windows to be deleted on idle time, when all pending events have been processed. This prevents problems with events being sent to non-existent windows.

Enable enables or disables the window and its children for input. Some controls display themselves in a different color when disabled. Disable can be used instead of passing false to Enable.

FindFocus is a static function that can be used to find the window that currently has the keyboard focus.

FindWindow can be used with an identifier or a name to find a window in this window’s hierarchy. It can return a descendant or the parent window itself. If you know the type of the window, you can use wxDynamicCast to safely cast to the correct type, returning either a pointer to that type or NULL:


MyWindow* window = wxDynamicCast(FindWindow(ID_MYWINDOW), MyWindow);

Fit resizes the window to fit its children. This should be used with sizer-based layout. FitInside is similar, but it uses the virtual size (useful when the window has scrollbars and contains further windows).

Freeze and Thaw are hints to wxWidgets that display updates between these two function calls should be optimized. For example, you could use this when adding a lot of lines to a text control separately. Implemented for wxTextCtrl on GTK+, and all windows on Windows and Mac OS X.

GetAcceleratorTable and SetAcceleratorTable get and set the accelerator table for this window.

GetBackgroundColour and SetBackgroundColour are accessors for the window background color, used by the default wxEVT_ERASE_BACKGROUND event. After setting the color, you will need to call Refresh or ClearBackground to show the window with the new color. SetOwnBackgroundColour is the same as SetBackgroundColour but the color is not inherited by the window’s children.

GetBackgroundStyle and SetBackgroundStyle are accessors for the window background style. By default, the background style is wxBG_STYLE_SYSTEM, which tells wxWidgets to draw the window background with whatever style is appropriate, whether a texture drawn according to the current theme (for example, wxDialog), or a solid color (for example, wxListBox). If you set the style to wxBG_STYLE_COLOUR, wxWidgets will use a solid color for this window. If you set it to wxBG_STYLE_CUSTOM, wxWidgets will suppress the default background drawing, and the application can paint it from its erase or paint event handler. If you want to draw your own textured background, then setting the style to wxBG_STYLE_CUSTOM is recommended for flicker-free refreshes.

GetBestSize returns the minimal size for the window in pixels (as implemented for each window by DoGetBestSize). This is a hint to the sizer system not to resize the window so small that it cannot be viewed or used properly. For example, for a static control, it will be the minimum size such that the control label is not truncated. For windows containing subwindows (typically wxPanel), the size returned by this function will be the same as the size the window would have had after calling Fit.

GetCaret and SetCaret are accessors for the wxCaret object associated with the window.

GetClientSize and SetClientSize are accessors for the size of the client area in pixels. The client area is the region within any borders and window decorations, inside which you can draw or place child windows.

GetCursor and SetCursor are accessors for the cursor associated with the window.

GetDefaultItem returns a pointer to the child button that is the default for this window, or NULL. The default button is the one activated by pressing the Enter key. Use wxButton::SetDefault to set the default button.

GetDropTarget and SetDropTarget are accessors for the wxDropTarget object which handles dropped data objects for this window. Drag and drop is covered in Chapter 11, “Clipboard and Drag and Drop.”

GetEventHandler and SetEventHandler are accessors for the first event handler for the window. By default, the event handler is the window itself, but you can interpose a different event handler. You can also use PushEventHandler and PopEventHandler to set up a handler chain, with different handlers dealing with different events. wxWidgets will search along the chain for handlers that match incoming events (see Chapter 3, “Event Handling”).

GetExtraStyle and SetExtraStyle are accessors for the “extra” style bits. Extra styles normally start with wxWS_EX_.

GetFont and SetFont are accessors for the font associated with this window. SetOwnFont is the same as SetFont, except that the font is not inherited by the window’s children.

GetForegroundColour and SetForegroundColour are accessors for the window foreground color, whose meaning differs according to the type of window. SetOwnForegroundColour is the same as SetForegroundColour but the color is not inherited by the window’s children.

GetHelpText and SetHelpText are accessors for the context-sensitive help string associated with the window. The text is actually stored by the current wxHelpProvider implementation, and not in the window.

GetId and SetId are accessors for the window identifier.

GetLabel returns the label associated with the window. The interpretation of this value depends on the particular window class.

GetName and SetName are accessors for the window name, which does not have to be unique. The window name has no special significance to wxWidgets, except under Motif where it is the resource name for the window.

GetParent returns a pointer to the parent window.

GetPosition returns the position of the top-left corner of the window in pixels, relative to its parent.

GetRect returns a wxRect object (see Chapter 13, “Data Structure Classes”) representing the size and position of the window in pixels.

GetSize and SetSize retrieve and set the outer window dimensions in pixels.

GetSizer and SetSizer are accessors for the top-level sizer used for arranging child windows on this window.

GetTextExtent gets the dimensions of the string in pixels, as it would be drawn on the window with the currently selected font.

GetToolTip and SetToolTip are accessors for the window tooltip object.

GetUpdateRegion returns the portion of the window that currently needs refreshing (since the last paint event was handled).

GetValidator and SetValidator are accessors for the optional wxValidator object associated with the window, to handle transfer and validation of data. See Chapter 9 for more about validators.

GetVirtualSize returns the virtual size of the window in pixels, as determined by setting the scrollbar dimensions.

GetWindowStyle and SetWindowStyle are accessors for the window style.

InitDialog sends a wxEVT_INIT_DIALOG event to initiate transfer of data to the window.

IsEnabled indicates whether the window is enabled or disabled.

IsExposed indicates whether a point or a part of the rectangle is in the update region.

IsShown indicates whether the window is shown.

IsTopLevel indicates whether the window is top-level (a wxFrame or a wxDialog).

Layout invokes the sizer-based layout system if there is a sizer associated with the window. See Chapter 7 for more about sizers.

Lower sends a window to the bottom of the window hierarchy, while Raise raises the window above all other windows. This works for top-level windows and child windows.

MakeModal disables all the other top-level windows in the application so that the user can only interact with this window.

Move moves the window to a new position.

MoveAfterInTabOrder moves the tab order of this window to a position just after the window passed as argument, and MoveBeforeInTabOrder is the same but moves the tab order in front of the window argument.

PushEventHandler pushes an event handler onto the event stack for this window, and PopEventHandler removes and returns the top-most event handler on the event handler stack. RemoveEventHandler finds a handler in the event handler stack and removes it.

PopupMenu shows a menu at the specified position.

Refresh and RefreshRect causes a paint event (and optionally an erase event) to be sent to the window.

SetFocus gives the window the current keyboard focus.

SetScrollbar sets the properties for a built-in scrollbar.

SetSizeHints allows specification of the minimum and maximum window sizes, and window size increments, in pixels. This is applicable to top-level windows only.

Show shows or hides the window; Hide is equivalent to passing false to Show.

TransferDataFromWindow and TransferDataToWindow transfer data from and to the window. By default, these call validator functions, but they can be overridden by the application.

Update immediately repaints the invalidated area of the window.

UpdateWindowUI sends wxUpdateUIEvents to the window to give the window (and application) a chance to update window elements, such as toolbars as menu items.

Validate validates the current values of the child controls using their validators.

wxControl

wxControl derives from wxWindow and is the abstract base class for controls: windows that display items of data and usually respond to mouse clicks or keyboard input by sending command events.

wxControlWithItems

wxControlWithItems is an abstract base class for some wxWidgets controls that contain several items, such as wxListBox, wxCheckListBox, wxChoice, and wxComboBox. The use of this intermediate class ensures that a consistent API is used across several controls that have similar functionality.

The items in a wxControlWithItems have string labels and, optionally, client data associated with them. Client data comes in two different flavors: either simple untyped (void*) pointers, which are stored by the control but not used in any way by it, or typed pointers (wxClientData*). These typed pointers are owned by the control, meaning that the typed client data will be deleted when an item is deleted or when the entire control is cleared (for example, when it is destroyed). All items in the same control must have client data of the same type: either all typed or all untyped (if it has any at all). The client data type is determined by the first call to Append, SetClientData, or SetClientObject. To work with typed client data, you should derive a class from wxClientData containing the data you want to store, and pass it to Append or SetClientObject.

wxControlWithItems Member Functions

Append adds a single item or an array of items to the control. When adding a single item, you can also associate typed or untyped data with the item by passing a second argument. For example:

wxArrayString strArr;
strArr.Add(wxT("First string"));
strArr.Add(wxT("Second string"));
controlA->Append(strArr);
controlA->Append(wxT("Third string"));
controlB->Append(wxT("First string"), (void *) myPtr);
controlC->Append(wxT("First string"), new MyTypedData(1));

Clear clears all items from the controls (deleting all typed client data).

Delete removes an item (and its typed client data) using a zero-based position.

FindString returns the zero-based index to the item matching a string, or wxNOT_FOUND if no item was found.

GetClientData and GetClientObject return a pointer to the client data associated with the specified item (if any). SetClientData and SetClientObject can be used to set the data for a specified item.

GetCount returns the number of items in the control.

GetSelection returns the index of the selected item, or wxNOT_FOUND if none was selected. SetSelection sets the index of the selected item.

GetString returns the item label at the given position; SetString sets an item’s label.

GetStringSelection returns the label of the selected item or an empty string if no item is selected; SetStringSelection sets the selection. To avoid an assertion, first check that the string is available in the control using FindString.

Insert inserts an item (with or without client data) at a specified position in the control.

IsEmpty returns true if the control has no items, and false otherwise.

Top-Level Windows

Top-level windows are placed directly on the desktop and are not contained within other windows. They can be moved around the screen, and resized if the application permits it. There are three basic kinds of top-level window: wxFrame and wxDialog, both derived from an abstract base class called wxTopLevelWindow, and wxPopupWindow, which has less functionality and is derived directly from wxWindow. A dialog can be either modal or modeless, whereas a frame is almost always modeless. Modal means that flow through the application effectively halts until the user dismisses the dialog. This is very handy for getting a response before continuing, but it’s always good to see whether an alternative user interface can be used (for example, a font control on the toolbar rather than in a properties window) to keep the interaction more fluid.

Top-level windows normally have a title bar and can have decorations for closing, minimizing, or restoring the window. A frame often has a menu bar, toolbar, and status bar, but a dialog generally does not. On Mac OS X, a frame’s menu bar is not shown at the top of the frame, but at the top of the screen.

Don’t confuse this usage of “top-level window” with the window returned by wxApp::GetTopWindow, by which wxWidgets or your application can get hold of the “main window,” most often the first frame or dialog you create.

If needed, you can access all current top-level windows using the global variable wxTopLevelWindows, which is a wxWindowList.

wxFrame

wxFrame is a popular choice for the main application window. Figure 4-2 shows the elements that compose a frame. A frame may optionally have a title bar (with decorations such as a button for closing the window), a wxMenuBar, a wxToolBar, and a wxStatusBar. The area that is left for child windows is called the client area, and it is up to the application to arrange the children’s size and position if there is more than one child. You should use sizers for this purpose, described in Chapter 7, or perhaps a splitter window (covered later in this chapter) if you need a couple of child windows.

Figure 4-2 The elements of a frame

The elements of a frame

Because some platforms do not allow direct painting on a frame, and to support keyboard navigation between child controls, you should create an intermediate wxPanel (see later).

A frame can have more than one toolbar, but it will only do sizing and positioning for one toolbar. You must implement explicit layout for multiple toolbars.

It is highly likely that you will derive a new class from wxFrame rather than using it directly, so that you can handle events such as wxEVT_CLOSE (see the following) and command events. Often you will create child windows and a menu bar within your frame constructor.

You can assign an icon to the frame to be shown by the system, such as on the taskbar or in the file manager. On Windows, it’s best to use a compound icon at 16×16 and 32×32 pixels and perhaps several color depths. On Linux, the same icons as for Windows usually suffices. On Mac OS X, you’ll need a variety of icons in different colors and depths. For more details on icons and icon bundles, see Chapter 10, “Programming with Images.”

wxFrame has the following constructor in addition to the default constructor:

wxFrame(wxWindow* parent, wxWindowID id, const wxString& title,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize,
    long style = wxDEFAULT_FRAME_STYLE,
    const wxString& name = wxT("frame"));

For example:

wxFrame* frame = new wxFrame(NULL, ID_MYFRAME,
    wxT("Hello wxWidgets"), wxDefaultPosition,
    wxSize(500, 300));
frame->Show(true);

Note that the frame won’t be shown until Show(true) is called, to give the application the chance to do child window layout invisibly.

You don’t have to pass a parent window to the new frame, but if you do, the new window will be displayed on top of the parent window if the wxFRAME_FLOAT_ON_PARENT style is specified.

To destroy a frame, do not use delete, but instead use Destroy or Close to tell wxWidgets to clean up the frame in idle time when all its events have been processed. When you call Close, you send a wxEVT_CLOSE event to the window. The default handler for this event calls Destroy. When a frame is deleted, its children are automatically deleted, as long as they are not themselves top-level windows.

When the last top-level window has been destroyed, the application exits (although you can change this behavior by calling wxApp::SetExitOnFrame Delete). Your main window’s wxEVT_CLOSE handler may need to destroy other top-level windows that might be open—for example, a Find dialog—otherwise the application will not close when the main window is closed.

A frame does not have the equivalent of wxDialog::ShowModal to enter an event loop and disable other top-level windows. However, you can get similar behavior by creating a wxWindowDisabler object when you require other top-level windows to be disabled. Or, you can use a wxModalEventLoop object, passing the frame pointer, calling Run to start a local event loop and calling Exit (usually from an event handler) to quit the loop.

Figure 4-3 shows the frame of a consumer application running on Windows. The frame has a title bar at the top, a menu bar, a colorful toolbar, a splitter window in the frame’s client area, and a status bar at the bottom, giving help on toolbar buttons and menu items as the user drags the mouse over them.

Figure 4-3 A typical wxFrame

A typical wxFrame

wxFrame Styles

wxFrame can have the window styles listed in Table 4-4, in addition to those described for wxWindow.

Table 4-4 wxFrame Styles

Image Image

Table 4-5 shows the extra styles that couldn’t be accommodated in the regular style and that are set using wxWindow::SetExtraStyle.

Table 4-5 wxFrame Extra Styles

Image

wxFrame Events

wxFrame and its derived classes generate the events listed in Table 4-6, in addition to those mentioned for wxWindow.

Table 4-6 wxFrame Events

Image

wxFrame Member Functions

These are the major wxFrame functions. Because wxFrame derives from wxTopLevelWindow and wxWindow, please also refer also to the member functions for these classes.

CreateStatusBar creates one or more status fields at the bottom of the frame. Use SetStatusText to set the text for a particular field, and SetStatusWidths to customize the widths of the fields (see also wxStatusBar later in this chapter). For example:

frame->CreateStatusBar(2, wxST_SIZEGRIP);
int widths[3] = { 100, 100, -1 };
frame->SetStatusWidths(3, widths);
frame->SetStatusText(wxT("Ready"), 0);

CreateToolBar creates a toolbar under the menu bar and associates it with the frame. Alternatively, you can create a toolbar by using the wxToolBar constructor, but to allow it to be managed by the frame, you need to call wxFrame::SetToolBar.

GetMenuBar and SetMenuBar are accessors for the frame’s wxMenuBar. There is only one menu bar per frame. You can replace an existing one with a new menu bar, and the old menu bar will be deleted.

GetTitle and SetTitle are accessors for the title that appears on the frame’s title bar.

Iconize iconizes or restores the frame. You can test the frame’s iconic state by calling IsIconized.

Maximize resizes the frame to fit the desktop, or restores it to the previous state if it is currently maximized. Call IsMaximized to test whether the frame is maximized.

SetIcon sets the icon displayed when the frame is minimized. It’s also used for other purposes by the window manager, such as displaying the program’s icon in Windows Explorer or on the taskbar. You can also use SetIcons to set an icon bundle (multiple icons with a variety of resolutions and depths).

SetShape sets a region specifying the shape of the frame on some platforms (currently Windows, Mac OS X, and GTK+, and X11 if the appropriate X11 extension is available).

ShowFullScreen hides as many decorations as possible and shows the client window at the maximum size of the display. It can also restore the frame to its former size and state. Use IsFullScreen to determine whether the frame is currently being shown full-screen.

Non-Rectangular Frames

If you want to write a more unusual-looking consumer application, such as a clock or media player, you can set a non-rectangular region for the frame, and only that region will be displayed. In Figure 4-4, the frame has no decorations (such as caption, border, or menu bar), and its paint handler is displaying a penguin bitmap. There is a region associated with the frame that acts as a mask that lets only the penguin show through.

Figure 4-4 A shaped wxFrame

A shaped wxFrame

The principles are demonstrated by the code in samples/shaped, although it uses a different image from the one shown here. When the frame is created, a bitmap is loaded, and a region is created out of it. On GTK+, setting the window shape must be delayed until the window creation event is sent, so you will need a __WXGTK__ test in your code. The following code demonstrates the required event table, frame constructor, and window creation event handler:

BEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
    EVT_MOTION(ShapedFrame::OnMouseMove)
    EVT_PAINT(ShapedFrame::OnPaint)

#ifdef __WXGTK__
    EVT_WINDOW_CREATE(ShapedFrame::OnWindowCreate)
#endif
END_EVENT_TABLE()

ShapedFrame::ShapedFrame()
       : wxFrame((wxFrame *)NULL, wxID_ANY, wxEmptyString,
                  wxDefaultPosition, wxSize(250, 300),
                  ¦ wxFRAME_SHAPED
                  ¦ wxSIMPLE_BORDER
                  ¦ wxFRAME_NO_TASKBAR
                  ¦ wxSTAY_ON_TOP
            )
{
    m_hasShape = false;
    m_bmp = wxBitmap(wxT("penguin.png"), wxBITMAP_TYPE_PNG);
    SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));

#ifndef __WXGTK__
    // On wxGTK we can’t do this yet because the window hasn’t
    // been created yet so we wait until the EVT_WINDOW_CREATE
    // event happens. On wxMSW and wxMac the window has been created
    // at this point so we go ahead and set the shape now.
    SetWindowShape();
#endif
}

// Used on GTK+ only
void ShapedFrame::OnWindowCreate(wxWindowCreateEvent& WXUNUSED(evt))
{
    SetWindowShape();
}

To set the shape, we create a region from the bitmap and the color to be used as the transparent color, and call SetShape.

void ShapedFrame::SetWindowShape()
{
    wxRegion region(m_bmp, *wxWHITE);
    m_hasShape = SetShape(region);
}

In order to allow the window to be moved around the screen, there is a mouse handler that explicitly moves the window.

void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
{
    wxPoint pt = evt.GetPosition();
    if (evt.Dragging() && evt.LeftIsDown())
    {
        wxPoint pos = ClientToScreen(pt);
        Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
    }
}

The paint handler is very simple, but of course in a real application, you will have other windows or graphics displayed inside the frame.

void ShapedFrame::OnPaint(wxPaintEvent& evt)
{
    wxPaintDC dc(this);
    dc.DrawBitmap(m_bmp, 0, 0, true);
}

For more details, see samples/shaped in the wxWidgets distribution.

Mini-Frames

On Windows and GTK+, you can use wxMiniFrame for frames that must have a small caption—for example, if implementing tool palettes. Figure 4-5 shows a wxMiniFrame on Windows. This class is implemented as a normal frame on Mac OS X. There are no special styles or member functions for this class.

Figure 4-5 A wxMiniFrame

A wxMiniFrame

wxMDIParentFrame

This frame class, derived from wxFrame, is part of wxWidgets’ Multiple Document Interface (MDI) support, whereby a parent frame manages zero or more wxMDIChildFrame windows. How it does so depends on platform; the main visual differences are illustrated in Figure 4-6. On Windows, the child windows are clipped to the boundary of the main window. These windows can be tiled, overlapped, or maximized within the main frame so that only one shows at a time, and a Window menu (automatically added by wxWidgets) is available for controlling the child windows. The MDI style has the advantage of keeping a desktop relatively uncluttered, grouping together all the windows in the application. Also, because the main frame’s menu bar is replaced by the active child frame’s menu bar, the clutter of multiple menu bars is also reduced.

Figure 4-6 wxMDIParentFrame on Windows and GTK+

wxMDIParentFrame on Windows and GTK+

Under GTK+, wxWidgets emulates the MDI style using tabbed windows; only one window is shown at a time, but the user can switch between windows quickly using the tabs. On Mac OS, wxMDIParentFrame and wxMDIChildFrame windows look like normal frames, reflecting the fact that documents always open in a new window on Mac OS.

On platforms where MDI children are contained within the parent, a wxMDIParentFrame arranges its children on a wxMDIClientWindow, which can coexist with other windows in the frame. In Figure 4-6, the parent frame’s size event handler sets the sizes and positions of a text control and the client window. For details, see samples/mdi in your wxWidgets distribution.

Each child frame can have its own menu bar, in addition to the parent frame’s menu bar. When a child frame is activated, its menu bar is shown. When there are no child frames, the parent frame’s menu bar is shown. You need to construct your child frame menu bar carefully to include the same commands as the parent’s menu bar, adding others that are specific to the child. The parent frame and child frames can have their own toolbars and status bars, but they are not swapped like menu bars.

wxMDIParentFrame has the same constructor as wxFrame.

wxMDIParentFrame Styles

wxMDIParentFrame can have the window styles listed in Table 4-7, in addition to those described for wxFrame.

Table 4-7 wxMDIParentFrame Styles

Image

wxMDIParentFrame Member Functions

These are the major wxMDIParentFrame functions, in addition to those defined for wxFrame.

ActivateNext and ActivatePrevious activate the next or previous child frame.

Cascade and Tile provide two methods to arrange the child frames: overlapping and tiling them, respectively. ArrangeIcons lays out any minimized frames within the client window. These three functions only apply on Windows.

GetActiveChild provides the application with a pointer to the currently active child (if any).

GetClientWindow returns a pointer to the client window (a container for the child frames). You can provide a different client window from the default by overriding OnCreateClient and returning an instance of your own wxMDIClientWindow-derived class, but you must then use two-step parent frame construction.

wxMDIChildFrame

wxMDIChildFrame should always be created as a child of a wxMDIParentFrame window. As explained in the previous section, its appearance depends on the platform and will either be free-floating or constrained to the boundary of its parent.

Its constructor is the same as a regular frame; despite the fact that its true parent is a wxMDIClientWindow, you should pass the frame parent to the constructor.

For example:

#include "wx/mdi.h"

wxMDIParentFrame* parentFrame = new wxMDIParentFrame(
     NULL, ID_MYFRAME, wxT("Hello wxWidgets"));

wxMDIChildFrame* childFrame = new wxMDIChildFrame(
     parentFrame, ID_MYCHILD, wxT("Child 1"));

childFrame->Show(true);
parentFrame->Show(true);

wxMDIChildFrame Styles

wxMDIChildFrame takes the same styles as wxFrame, although depending on platform, not all of them will take effect.

wxMDIChildFrame Member Functions

These are the major wxMDIChildFrame functions. See also the base class, wxFrame.

Activate activates this frame, bringing it to the front and displaying its menu bar.

Maximize resizes the frame to fit the parent (Windows only).

Restore sets the frame to the size it was before it was maximized (Windows only).

wxDialog

A dialog is a top-level window used for presenting information, options, or selections. It can optionally have a title bar with decorations such as the close window button and minimize button, and as with wxFrame, you can assign an icon to the dialog to be shown in the taskbar or equivalent. A dialog can contain any combination of non-top level windows and control—for example, a wxNotebook with OK and Cancel buttons underneath. As its name suggests, you use this class to initiate a dialog with a user, presenting specific information and choices, compared with the frame’s usual role as the main window of an application.

There are two kinds of dialog—modal and modeless. A modal dialog blocks program flow and user input on other windows until it is dismissed (EndModal is called), whereas a modeless dialog behaves more like a frame in that program flow continues, and input in other windows is still possible. To show a modal dialog, you should use the ShowModal method, whereas to show a dialog modelessly, you simply use Show, as with frames.

Note that the modal dialog is one of the very few examples of wxWindow-derived objects that may be created on the stack and not on the heap. In other words, you can use the heap method as follows:

void AskUser()
{
    MyAskDialog *dlg = new MyAskDialog(...);
    if ( dlg->ShowModal() == wxID_OK )
        ...
    //else: dialog was cancelled or some another button pressed

    dlg->Destroy();
}

You can also achieve the same result by using the stack:

void AskUser()
{
    MyAskDialog dlg(...);
    if ( dlg.ShowModal() == wxID_OK )
        ...

    // no need to call Destroy() here
}

Normally you will derive a new class from wxDialog rather than using it directly so that you can handle events such as wxEVT_CLOSE (see the following) and command events. Often you will create your dialog’s controls within the constructor.

Just as with wxFrame, wxWidgets will resize a single child window to fill the dialog, but for more than one child, the application is responsible for sizing and positioning the controls using sizers (see Chapter 7).

When you call Show, wxWidgets calls InitDialog to send a wxInitDialog Event to the dialog, transferring data to the dialog via validators or other means.

wxDialog has the following constructor in addition to the default constructor:

wxDialog(wxWindow* parent, wxWindowID id, const wxString& title,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize,
    long style = wxDEFAULT_DIALOG_STYLE,
    const wxString& name = wxT("dialog"));

For example:

wxDialog* dialog = new wxDialog(NULL, ID_MYDIALOG,
    wxT("Hello wxWidgets"), wxDefaultPosition,
    wxSize(500, 300));
dialog->Show(true);

The dialog won’t be shown until Show(true) or ShowModal is called to give the application the chance to do child window layout invisibly.

By default, a dialog created with a NULL parent window will be given the application’s top-level window as parent. Use the wxDIALOG_NO_PARENT style to prevent this from happening and create an orphan dialog. This is not recommended for modal dialogs.

As with wxFrame, do not use delete to destroy a dialog, but instead use Destroy or Close to delay deletion until all the object’s events have been processed. When you call Close, the default wxEVT_CLOSE handler for this function usually calls Destroy.

Note that before a modal dialog is destroyed, an event handler should have called EndModal, passing the identifier of the command that closed it (for example, wxID_OK or wxID_CANCEL). This will exit the dialog’s event loop so that the dialog object can be destroyed by the code that called ShowModal. The identifier passed to EndModal will be returned by ShowModal. To clarify, the OnCancel function in the following example will be called while ShowModal is in its event loop:


// Event handler for wxID_CANCEL
void MyDialog::OnCancel(wxCommandEvent& event)
{
    EndModal(wxID_CANCEL);
}

// Show a dialog
void ShowDialog()
{
    // Show the dialog
    MyDialog dialog;

    // OnCancel or other function is called from within ShowModal
    if (dialog.ShowModal() == wxID_CANCEL)
    {
        ...
    }
}

Figure 4-7 shows a typical simple dialog, which we’ll create in Chapter 9. Dialogs can, of course, get more complicated, such as the settings dialog shown in Figure 4-8. This one has a splitter window, a tree control to navigate between multiple panels, and a grid control acting as a property editor.

Figure 4-7 A typical simple dialog

A typical simple dialog

Figure 4-8 A more complex dialog

A more complex dialogtop-level windowswxDialogwxDialogtop-level windows

wxDialog Styles

wxDialog can have the window styles listed in Table 4-8 in addition to those described for wxWindow.

Table 4-8 wxDialog Styles

Image

Table 4-9 describes extra styles that couldn’t be accommodated in the regular style, and so are set using wxWindow::SetExtraStyle. Although wxWS_EX_BLOCK_EVENTS is valid for all windows, we repeat it here because it is set by default.

Table 4-9 wxDialog Extra Styles

Image

wxDialog Events

wxDialog generates the events listed in Table 4-10, in addition to those mentioned for wxWindow.

Table 4-10 wxDialog Events

Image

wxDialog Member Functions

These are the major wxDialog functions. Please refer also to the member functions for wxWindow and wxTopLevelWindow, from which wxDialog is derived.

GetTitle and SetTitle are accessors for the title that appears on the dialog’s title bar.

Iconize iconizes or restores the dialog. You can test the dialog’s iconic state by calling IsIconized.

Maximize maximizes the dialog (makes it as large as the desktop) or restores it to the previous state. Call IsMaximized to test whether the dialog is maximized. Windows only.

SetIcon sets the icon displayed when the dialog is minimized. It’s also used for other purposes by the window manager, such as displaying the program’s icon in Windows Explorer or on the taskbar. You can also use SetIcons to set an icon bundle (multiple icons with a variety of resolutions and depths).

ShowModal is used when showing a modal dialog. It returns the value of the identifier passed to EndModal—normally this is the identifier of the control that the user clicked on to dismiss the dialog. By default (implemented in the dialog’s wxEVT_CLOSE handler), closing the dialog sends a simulated wxID_CANCEL to the dialog. The default handler for wxID_CANCEL calls EndModal with wxID_CANCEL. Therefore, if you provide a button with the identifier wxID_CANCEL, the logic for canceling the dialog is handled for you, unless you need extra functionality.

SetLeftMenu and SetRightMenu are only available on Microsoft Smartphone, and they set the commands allocated to the left and right menu buttons. They take a command identifier, such as wxID_OK, a label, and an optional pointer to a wxMenu to show.

wxPopupWindow

Pop-up windows are not implemented on all platforms (in particular, they are missing from Mac OS X), and so we will only briefly mention them.

wxPopupWindow is a top-level window that normally has minimal decoration and is used to implement windows that are shown briefly, such as a menu or a tooltip. Create it by passing a parent window and optional style to the constructor (defaulting to wxNO_BORDER). Move it into position with Position, which takes a screen position and size and makes sure that the popup is visible on the display.

wxPopupTransientWindow is a special kind of wxPopupWindow that dismisses itself (hides) when it loses the focus or the mouse is clicked outside of the window. It can also be hidden with Dismiss.

Container Windows

Container windows are designed to hold further visual elements, either child windows or graphics drawn on the window.

wxPanel

wxPanel is essentially a wxWindow with some dialog-like properties. This is usually the class to use when you want to arrange controls on a window that’s not a wxDialog, such as a wxFrame. It’s often used for pages of a wxNotebook. wxPanel normally takes the system dialog color.

As with wxDialog, you can use InitDialog to send a wxInitDialogEvent to the panel, transferring data to the panel via validators or other means. wxPanel also handles navigation keys such as the Tab key to provide automatic traversal between controls, if the wxTAB_TRAVERSAL style is provided.

wxPanel has the following constructor in addition to the default constructor:

wxPanel(wxWindow* parent, wxWindowID id,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize,
    long style = wxTAB_TRAVERSAL¦wxNO_BORDER,
    const wxString& name = wxT("panel"));

For example:

wxPanel* panel = new wxPanel(frame, wxID_ANY,
    wxDefaultPosition, wxSize(500, 300));

wxPanel Styles

There are no specific styles for wxPanel, but see the styles for wxWindow.

wxPanel Member Functions

There are no distinct wxPanel functions; please refer to the wxWindow member functions, inherited by wxPanel.

wxNotebook

This class represents a control with several pages, switched by clicking on tabs along an edge of the control. A page is normally a wxPanel or a class derived from it, although you may use other window classes.

Notebook tabs may have images as well as, or instead of, text labels. The images are supplied via a wxImageList (see Chapter 10), and specified by position in the list.

To use a notebook, create a wxNotebook object and call AddPage or InsertPage, passing a window to be used as the page. Do not explicitly destroy the window for a page that is currently managed by wxNotebook; use DeletePage instead, or let the notebook destroy the pages when it is itself destroyed.

Here’s an example of creating a notebook with three panels, and a text label and icon for each tab:

#include "wx/notebook.h"

#include "copy.xpm"
#include "cut.xpm"
#include "paste.xpm"

// Create the notebook
wxImageList* imageList = new wxImageList(16,16,true, 3);
  imageList->Add(wxlcon(copy_xpm));

// Create the image list
wxImageList* imageList = new wxImageList(16,16,true, 3);
imageList->Add(wxIcon(cut_xpm));
imageList->Add(wxIcon(paste_xpm));
notebook->SetimageList(imageList);

// Create and add the pages
wxPanel* window1 = new wxPanel(notebook, wxID_ANY);
wxPanel* window2 = new wxPanel(notebook, wxID_ANY);
wxPanel* window3 = new wxPanel(notebook, wxID_ANY);

notebook->AddPage(window1, wxT("Tab one"), true, 0);
notebook->AddPage(window2, wxT("Tab two"), false, 1);
notebook->AddPage(window3, wxT("Tab three"), false, 2);

Figure 4-9 shows the result on Windows.

Figure 4-9 A wxNotebook

A wxNotebook

On most platforms, there are scroll buttons to view tabs that cannot all be displayed on the window at once. However, on Mac OS, the tabs do not scroll, so the number you can display is limited by the window and tab label size.

If you use sizers to lay out controls on individual pages, and pass wxDefaultSize to the notebook constructor, wxNotebook will adjust its size to fit the sizes of its pages.

Notebook Theme Management

On Windows XP, the default theme paints a gradient on the notebook’s pages. Although this is the expected native behavior, it can slow down performance, and you may prefer a solid background for aesthetic reasons, especially when the notebook is not being used in a dialog. If you want to suppress themed drawing, there are three ways of doing it. You can use the wxNB_NOPAGETHEME style to disable themed drawing for a particular notebook, you can call wxSystemOptions::SetOption to disable it for the whole application, or you can disable it for individual pages by using SetBackgroundColour. To disable themed pages globally, do this:

wxSystemOptions::SetOption(wxT("msw.notebook.themed-background"), 0);

Set the value to 1 to enable it again. To give a single page a solid background that matches the current theme, use

wxColour col = notebook->GetThemeBackgroundColour();
if (col.Ok())
{
    page->SetBackgroundColour(col);
}

On platforms other than Windows, or if the application is not using Windows themes, GetThemeBackgroundColour will return an uninitialized color object, and this code will therefore work on all platforms. Please note that this syntax and behavior is subject to change, so refer to the wxNotebook documentation in your wxWidgets distribution for the latest information.

wxNotebook Styles

wxNotebook can have the window styles listed in Table 4-11, in addition to those described for wxWindow.

Table 4-11 wxNotebook Styles

Image

wxNotebook Events

wxNotebook generates wxNotebookEvent propagating events (events that can be handled by the notebook or its ancestors) specified in Table 4-12.

Table 4-12 wxNotebook Events

Image

wxNotebook Member Functions

These are the major wxNotebook functions.

AddPage adds a page, and InsertPage inserts a page at the given position. You can use a text label for the tab, or an image (specified by index into an image list), or both. For example:

// Adds an unselected page with a label and an image
// (index 2 in the associated image list).
notebook->AddPage(page, wxT("My tab"), false, 2);

DeletePage removes and destroys the specified page, while RemovePage just removes the page without deleting the page. Call DeleteAllPages to delete all the pages. When the wxNotebook is deleted, it will delete all its pages.

AdvanceSelection cycles through the pages, and SetSelection sets the specified page by zero-based index. Use GetSelection to get the index of the selected page, or wxNOT_FOUND if none was selected.

SetImageList sets a wxImageList to be used by the notebook but does not take ownership of it. Call AssignImageList if you want the notebook to delete the image list when it is destroyed. GetImageList returns the associated image list. An image list stores images to be shown on each page tab, if required. wxImageList is described in Chapter 10.

Use GetPage to return the page window for a given index, and use GetPageCount to return the number of pages in the notebook.

SetPageText and GetPageText are accessors for the label for a given page (by index).

SetPageImage and GetPageImage are accessors for the index of a page’s image index in the notebook’s image list.

Alternatives to wxNotebook

wxNotebook is derived from a base class wxBookCtrlBase, which abstracts the concept of a control that manages pages. There are two API-compatible variations of the wxNotebook concept, wxListbook and wxChoicebook, and you can implement your own, such as wxTreebook.

wxListbook uses a wxListCtrl to change pages; the list control displays icons with text labels underneath them, and can be on any of the four sides, defaulting to the left side. This is an attractive alternative to wxNotebook, and it has the advantage of being able to cope with an arbitrary number of pages even on Mac OS X because the list control can scroll.

wxChoicebook uses a choice control (a drop-down list) and is particularly handy for small devices with restricted screen space, such as smartphones. It does not display images, and by default, it will display the choice control at the top.

The include files for these classes are wx/listbook.h and wx/choicebk.h. Event handlers for these two classes take a wxListbookEvent or wxChoicebookEvent argument, respectively, and you can use the event macros EVT_XXX_PAGE_CHANGED(id, func) and EVT_XXX_PAGE_CHANGING(id, func) where XXX is LISTBOOK or CHOICEBOOK.

You can use the same window styles as wxNotebook, or you can use the equivalents, such as wxCHB_TOP or wxLB_TOP instead of wxNB_TOP.

wxScrolledWindow

All windows can have scrollbars, but extra code is required to make scrolling work. This gives the flexibility to define appropriate scrolling behaviors for different kinds of windows. wxScrolledWindow implements commonly required scrolling behavior by assuming that scrolling happens in consistent units, not different-sized jumps, and that page size (the amount scrolled when “paging” up, down, left, or right) is represented by the visible portion of the window. It is suited to drawing applications but is not so suitable for a sophisticated editor in which the amount scrolled may vary according to the size of text on a given line. For this, you would derive from wxWindow and implement scrolling yourself. wxGrid is an example of a class that implements its own scrolling, largely because columns and rows can vary in size.

To use a scrolled window, you need to define the number of pixels per logical scroll unit (how much the window is scrolled for a line up or down scroll event) and provide the virtual size in logical units. wxScrolledWindow will then take care of showing the scrollbars with appropriately sized “thumbs” (the parts you can drag) and will show or hide scrollbars as appropriate, according to the actual size of the window.

The following fragment shows how to create a scrolled window:

#include "wx/scrolwin.h"

wxScrolledWindow* scrolledWindow = new wxScrolledWindow(
    this, wxID_ANY, wxPoint(0, 0), wxSize(400, 400),
    wxVSCROLL¦wxHSCROLL);

// Set up virtual window dimensions. It will be 1000x1000
// and will scroll 10 pixels at a time
int pixelsPerUnixtX = 10;
int pixelsPerUnixtY = 10;
int noUnitsX = 1000;
int noUnitsY = 1000;

scrolledWindow->SetScrollbars(pixelsPerUnitX, pixelsPerUnitY,
    noUnitsX, noUnitsY);

A second way to specify the virtual size is to use SetVirtualSize, which takes the virtual size in pixels, plus a call to SetScrollRate to set the horizontal and vertical scrolling increments. A third way is to set a sizer for the window, and the scrolled window will calculate the required scrollbar dimensions from the space taken up by the child windows. You will still need to call SetScrollRate to specify the scrolling increments.

You can provide a paint event handler as normal, but in order to draw the graphics at the appropriate position for the current positions of the scrollbars, call DoPrepareDC before drawing. This sets the device context’s device origin. For example:

void MyScrolledWindow::OnPaint(wxPaintEvent& event)
{
    wxPaintDC dc(this);
    DoPrepareDC(dc);

    dc.SetPen(*wxBLACK_PEN);
    dc.DrawLine(0, 0, 100, 100);
}

Alternatively, you can override the OnDraw virtual function; wxScrolledWindow creates a paint device context and calls DoPrepareDC for you before calling your OnDraw function, so the code simplifies to the following:

void MyScrolledWindow::OnDraw(wxDC& dc)
{
    dc.SetPen(*wxBLACK_PEN);
    dc.DrawLine(0, 0, 100, 100);
}

Note that you will need to call DoPrepareDC if you draw on the window from outside the paint event, such as within a mouse event handler.

You can provide your own DoPrepareDC function. The default function simply shifts the device origin according to the current scroll positions so that subsequent drawing will appear at the right place:

void wxScrolledWindow::DoPrepareDC(wxDC& dc)
{
    int ppuX, ppuY, startX, startY;

    GetScrollPixelsPerUnit(& ppuX, & ppuY);
    GetViewStart(& startX, & startY);

    dc.SetDeviceOrigin( - startX * ppuX, - startY * ppuY );
}

For more on painting on a wxScrolledWindow, including using buffered drawing, please see the section on wxPaintDC in Chapter 5, “Drawing and Printing.”

wxScrolledWindow Styles

There are no special styles for wxScrolledWindow, but usually you will supply wxVSCROLL¦wxHSCROLL (the default style for wxScrolledWindow). On some platforms, if these styles are not present, no scrollbars will be provided for efficiency reasons.

wxScrolledWindow Events

wxScrolledWindow generates wxScrollWinEvent events (see Table 4-13). These events do not propagate up the window parent-child hierarchy, so if you want to intercept these events, you must derive a new class or plug an event handler object into the window object. Normally you will not need to override the existing handlers for these events.

Table 4-13 wxScrolledWindow Events

Image

wxScrolledWindow Member Functions

These are the major wxScrolledWindow functions.

CalcScrolledPosition and CalcUnscrolledPosition both take four arguments: two integers for the position input in pixels, and two pointers to integers for the transformed position output, also in pixels. CalcScrolledPosition calculates the device position from the logical position. For example, if the window is scrolled 10 pixels down from the top, the logical first visible position is 0, but the device position is -10. CalcUnscrolledPosition does the inverse, calculating the logical position from the device position.

EnableScrolling enables or disables physical scrolling in horizontal and vertical directions independently. Physical scrolling is the physical transfer of bits up or down the screen when a scroll event occurs. If the application scrolls by a variable amount (for example, if there are different font sizes), then physical scrolling will not work, and you should switch it off. If physical scrolling is disabled, you will have to reposition child windows yourself. Physical scrolling may not be available on all platforms, but it is enabled by default where it is available.

GetScrollPixelsPerUnit returns the horizontal and vertical scroll unit sizes in two pointers to integers. A value of zero indicates that there is no scrolling in that direction.

GetViewStart returns the position of the first visible position on the window, in logical units. Pass two pointers to integers to receive the values. You will need to multiply by the values returned by GetScrollPixelsPerUnit to get pixel values.

GetVirtualSize returns the size in device units (pixels) of the scrollable window area. Pass two pointers to integers to receive the virtual width and height.

DoPrepareDC prepares the device context by setting the device origin according to the current scrollbar positions.

Scroll scrolls a window so that the view is at the given point in scroll units (not pixels), passed as two integers. If either parameter is -1, that position will be unchanged.

SetScrollbars sets the pixels per unit in each direction, the number of units for the virtual window in each direction, the horizontal and vertical position to scroll to (optional), and a boolean to indicate whether the window should be refreshed (false by default).

SetScrollRate sets the horizontal and increment scroll rate (the same as the pixels per unit parameters in SetScrollbars).

SetTargetWindow can be used to scroll a window other than the wxScrolledWindow.

Scrolling Without Using wxScrolledWindow

If you want to implement your own scrolling behavior, you can derive a class from wxWindow and use wxWindow::SetScrollbar to set scrollbar properties.

SetScrollbar takes the arguments listed in Table 4-14.

Table 4-14 SetScrollbar Arguments

Image

Let’s say you want to display 50 lines of text, using the same font. The window is sized so that you can only see 16 lines at a time.

You would use

SetScrollbar(wxVERTICAL, 0, 16, 50)

Note that with the window at this size, the thumb position can never go above 50 minus 16, or 34.

You can determine how many lines are currently visible by dividing the current view size by the character height in pixels.

When defining your own scrollbar behavior, you will always need to recalculate the scrollbar settings when the window size changes. You could therefore introduce a new function AdjustScrollbars into which you place your scrollbar calculations and SetScrollbar call. AdjustScrollbars can be called initially, and also from your wxSizeEvent handler function.

It’s instructive to look at the implementations of wxScrolledWindow and wxGrid if you’re thinking of implementing your own scrolling behavior.

You may want to look at wxVScrolledWindow in the wxWidgets reference manual; this can be used to build a scrolled window class that can scroll by lines of unequal height in the vertical direction.

wxSplitterWindow

This class manages up to two subwindows (use nested splitter windows if you need more splits). The current view can be split into two by the application, for example, from a menu command. It can be unsplit either by the application or via the splitter window user interface by double-clicking on the sash or dragging the sash until one of the panes has zero size (override the latter behavior with SetMinimumPaneSize).

On most platforms, when the sash is dragged, a reverse-video line will be drawn to show where the sash will end up. You can pass wxSP_LIVE_UPDATE to let the sash move in “real time” instead, resizing the child windows. This is the default (and only) mode on Mac OS X.

The following fragment shows how to create a splitter window, creating two subwindows and hiding one of them.

#include "wx/splitter.h"

wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY,
    wxPoint(0, 0), wxSize(400, 400), wxSP_3D);

leftWindow = new MyWindow(splitter);
leftWindow->SetScrollbars(20, 20, 50, 50);

rightWindow = new MyWindow(splitter);
  rightWindow->SetScrollbars(20, 20, 50, 50);
  rightWindow->Show(false);

splitter->Initialize(leftWindow);

// Unncomment this to prevent unsplitting
//    splitter->SetMinimumPaneSize(20);

This fragment shows how the splitter window can be manipulated after creation:

void MyFrame::OnSplitVertical(wxCommandEvent& event)
{
    if ( splitter->IsSplit() )
        splitter->Unsplit();
    leftWindow->Show(true);
    rightWindow->Show(true);
    splitter->SplitVertically( leftWindow, rightWindow );
}

void MyFrame::OnSplitHorizontal(wxCommandEvent& event)
{
    if ( splitter->IsSplit() )
        splitter->Unsplit();
    leftWindow->Show(true);
    rightWindow->Show(true);
    splitter->SplitHorizontally( leftWindow, rightWindow );
}

void MyFrame::OnUnsplit(wxCommandEvent& event)
{
    if ( splitter->IsSplit() )
        splitter->Unsplit();
}

Figure 4-10 shows how the wxWidgets splitter sample looks on Windows without the wxSP_NO_XP_THEME style. If you use this style, the splitter will take on a more traditional look with a sunken border and 3D sash.

Figure 4-10 A wxSplitterWindow

A wxSplitterWindow

wxSplitterWindow Styles

wxSplitterWindow can have the window styles shown in Table 4-15 in addition to those described for wxWindow.

Table 4-15 wxSplitterWindow Styles

Image

wxSplitterWindow Events

wxSplitterWindow generates wxSplitterEvent propagating events, as listed in Table 4-16.

Table 4-16 wxSplitterWindow Events

Image

wxSplitterWindow Member Functions

These are the major wxSplitterWindow functions.

GetMinimumPaneSize and SetMinimumPaneSize are accessors for the minimum pane size. The default minimum pane size is zero, which means that either pane can be reduced to zero by dragging the sash, thus removing one of the panes. To prevent this behavior (and veto out-of-range sash dragging), set a minimum size, for example 20 pixels. However, if the wxSP_PERMIT_UNSPLIT style is used when a splitter window is created, the window may be unsplit even if the minimum size is non-zero.

GetSashPosition and SetSashPosition are accessors for the sash position. Passing true to SetSashPosition resizes the pane and redraws the sash and border.

GetSplitMode and SetSplitMode are accessors for the split orientation, which can be wxSPLIT_VERTICAL or wxSPLIT_HORIZONTAL.

GetWindow1 and GetWindow2 get the pointers to the two panes.

Initialize can be called with a pointer to a window if you only want to have one pane initially.

IsSplit tests whether the window is split.

ReplaceWindow replaces one of the windows managed by the wxSplitter Window with another one. Generally, it’s better to use this function instead of calling Unsplit and then resplitting the window.

SetSashGravity takes a floating-point argument, which determines the position of the sash as the window is resized. A value of 0.0 (the default) means that only the bottom or right child window will be resized, and a value of 1.0 means that only the top or left child window will be resized. Values inbetween indicate that the change in size should be distributed between both child windows (a value of 0.5 distributes the size evenly). Use GetSashGravity to return the current setting.

SplitHorizontally and SplitVertically initialize the splitter window with two panes and optionally an initial sash size.

Unsplit removes the specified pane.

UpdateSize causes the splitter to update its sash position immediately (normally, this is done in idle time).

Sizing Issues with wxSplitterWindow

There are subtleties to be aware of when using a splitter window as part of a sizer hierarchy. If you don’t need the sash to be moveable, you can create both child windows with absolute sizes. This will fix the minimum size of both child windows, and the sash will therefore not be free to move. If you need the sash to be moveable, as is normally the case, pass default values to the child windows and specify an initial minimum size in the splitter window constructor. Then add the splitter window to its sizer, passing the wxFIXED_MINSIZE flag to Add, which tells wxWidgets to treat the specified size as the minimum size.

Another issue is that a splitter does not set its sash position (and therefore the sizes of its child windows) until idle time, when it can be sure that sizing has been finalized and the sash position won’t be set prematurely. This can result in a sash that visibly repositions itself just after the window has been shown. To fix this, call wxSplitterWindow::UpdateSize as soon as you have done your layout, for example after a wxSizer::Fit call. The splitter will update its sash and child window sizes immediately.

By default, when the user or application resizes the splitter, only the bottom (or right) window is adjusted to take into account the new size. If you need different behavior, use SetSashGravity as documented in the previous section.

Alternatives to wxSplitterWindow

If you have a lot of “split” windows in your application, consider using wxSashWindow. This is a window that allows any of its edges to have a sash (as specified by the application) that can be dragged to resize the window. The actual content window is normally created by the application as a child of wxSashWindow.

When a sash is dragged, it notifies the application with a wxSashEvent so the handler can change the window size accordingly before laying out the windows. Layout is achieved via a class called wxLayoutAlgorithm, which provides LayoutWindow, LayoutFrame, and LayoutMDIFrame methods for arranging the sash windows on different kinds of parent windows.

You can also use the class wxSashLayoutWindow, which responds to events of type wxQueryLayoutInfoEvent to provide orientation and size information to wxLayoutAlgorithm.

Please see the reference manual for further details. wxSashWindow doesn’t permit moving or undocking windows, and it’s likely that these classes will be superceded by a general docking and layout framework in the near future.

Figure 4-11 shows a view of the wxSashWindow sample provided in samples/sashtest.

Figure 4-11 The wxSashWindow demo

The wxSashWindow demo

Non-Static Controls

Non-static controls, such as wxButton and wxListBox, respond to mouse and keyboard input. We’ll describe the basic ones here; more advanced controls are described in Chapter 12. You can also download others (see Appendix E) or create your own.

wxButton

A wxButton is a control that looks like a physical push button with a text label, and it is one of the most common elements of a user interface. It may be placed on a dialog box or panel, or almost any other window. A command event is generated when the user clicks on the button.

Here’s a simple example of creating a button:

#include "wx/button.h"
wxButton* button = new wxButton(panel, wxID_OK, wxT("OK"),
    wxPoint(10, 10), wxDefaultSize);

Figure 4-12 shows how a button with the default size looks on Windows XP.

Figure 4-12 A wxButton

A wxButton

wxWidgets obtains the default button size by calling the static function wxButton::GetDefaultSize, calculated appropriately for each platform, but you can let wxWidgets size the button to just fit the label by passing the style wxBU_EXACTFIT.

wxButton Styles

Table 4-17 lists the specific window styles for wxButton.

Table 4-17 wxButton Styles

Image

wxButton Events

wxButton generates a wxCommandEvent propagating event, as shown in Table 4-18.

Table 4-18 wxButton Events

Image

wxButton Member Functions

These are the major wxButton functions.

SetLabel and GetLabel are accessors for the button label. You can use an ampersand to indicate that the following letter is a mnemonic on Windows and GTK+.

SetDefault sets this button to be the default button on the parent window, so pressing the Enter key activates this button.

wxButton Labels

You can use an ampersand in the button label to indicate that the next letter is an underlined mnemonic (or “access key”), so that the user can press that key instead of clicking on the button. The mnemonic only works on Windows and GTK+; on other platforms, the ampersand will simply be stripped from the label and ignored.

On some systems, notably GTK+, standard buttons such as OK and New are displayed with special graphics in line with the native look and feel for that platform. wxWidgets maps some of its standard window identifiers to these stock buttons, but it also permits the application to substitute a custom label should the need arise.

The recommended usage is as follows. When using a stock button identifier, and you want wxWidgets to supply the label, just supply the identifier and not the label (or an empty string for the label). For example:

wxButton* button = new wxButton(this, wxID_OK);

wxWidgets will substitute the correct standard label on all platforms. For example, on Windows and Mac OS X, the string "&OK" will be used. On GTK+, the stock OK button will be used. However, if you supply a label that is different from the stock label, wxWidgets will use that label. For example:

wxButton* button = new wxButton(this, wxID_OK, wxT("&Apply"));

This will result in the “Apply” label being displayed on all platforms, overriding the standard identifier.

You can get the stock button label for a given identifier with wxGetStockLabel (include wx/stockitem.h), passing the identifier, true (if you want menu codes to be included), and an optional accelerator string to append.

Table 4-19 shows the stock button identifiers and their corresponding labels.

Table 4-19 Stock Button Identifiers

Image Image

wxBitmapButton

A bitmap button is like a normal text button, but it shows a bitmap instead of text. A command event is generated when the user clicks on the button.

Here’s a simple example of creating a bitmap button:

#include "wx/bmpbuttn.h"

wxBitmap bitmap(wxT("print.xpm"), wxBITMAP_TYPE_XPM);
wxBitmapButton* button = new wxBitmapButton(panel, wxID_OK,
    bitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);

Figure 4-13 shows the result under Windows.

Figure 4-13 A wxBitmapButton

A wxBitmapButton

A bitmap button can be supplied with a single bitmap (optionally with transparency information), and wxWidgets will draw all button states using this bitmap. If the application needs more control, additional bitmaps for the selected state, unpressed focused state, and grayed-out state may be supplied.

XPM is a good choice of bitmap format for buttons because it supports transparency and can be included into C++ code, but you can load them from other formats too, such as JPEG, PNG, GIF, and BMP.

wxBitmapButton Styles

Table 4-20 lists the specific window styles for wxBitmapButton.

Table 4-20 wxBitmapButton Styles

Image

wxBitmapButton Events

wxBitmapButton generates wxCommandEvent propagating events, identical to wxButton.

wxBitmapButton Member Functions

These are the major wxBitmapButton functions.

SetBitmapLabel and GetBitmapLabel are accessors for the main button label bitmap. You can also use SetBitmapFocus, SetBitmapSelected, and SetBitmapDisabled and their corresponding getters for more precise control of the button in different states.

SetDefault sets this button to be the default button on the parent window, so pressing the Enter key will activate the button.

wxChoice

The choice control consists of a read-only text area that reflects the selection of a drop-down list box. The list box is hidden until the user presses a button on the control to reveal the list of strings.

To create a choice control, pass the usual parent window, identifier, position, size, and style parameters, plus an array of strings to populate the list. For example:

#include "wx/choice.h"

wxArrayString strings;
strings.Add(wxT("One"));
strings.Add(wxT("Two"));
strings.Add(wxT("Three"));

wxChoice* choice = new wxChoice(panel, ID_COMBOBOX,
    wxDefaultPosition, wxDefaultSize, strings);

On most platforms, the look is similar to wxComboBox (see Figure 4-14), except that the user cannot edit the text. On GTK+, wxChoice is a button with a drop-down menu. You may like to use a read-only wxComboBox to get the benefit of the scrolling drop-down list.

Figure 4-14 A wxComboBox

A wxComboBox

wxChoice Styles

There are no special styles for wxChoice.

wxChoice Events

wxChoice generates wxCommandEvent propagating events, as shown in Table 4-21.

Table 4-21 wxChoice Events

Image

wxChoice Member Functions

All wxChoice functions are described by wxControlWithItems: Clear, Delete, FindString, GetClientData, GetClientObject, SetClientData, SetClientObject, GetCount, GetSelection, SetSelection, GetString, SetString, GetStringSelection, SetStringSelection, Insert, and IsEmpty.

wxComboBox

The combo box is a combination of a list box and a single-line text field, and it allows you to set and get the text of the text field independently of the list box. The text field can be read-only, in which case it behaves very much like wxChoice. Normally, the list box is hidden until the user presses a button on the control to reveal the list of strings. This makes for a very compact way of allowing the user to enter text and also to choose from a list of existing options.

To create a combo box, pass the usual parent window, identifier, position, size, and style parameters, plus the initial text and an array of strings to populate the list. For example:

#include "wx/combobox.h"

wxArrayString strings;
strings.Add(wxT("Apple"));
strings.Add(wxT("Orange"));
strings.Add(wxT("Pear"));
strings.Add(wxT("Grapefruit"));

wxComboBox* combo = new wxComboBox(panel, ID_COMBOBOX,
    wxT("Apple"), wxDefaultPosition, wxDefaultSize,
    strings, wxCB_DROPDOWN);

The result on Windows is shown in Figure 4-14 with the drop-down list activated.

wxComboBox Styles

Table 4-22 lists the specific window styles for wxComboBox.

Table 4-22 wxComboBox Styles

Image

wxComboBox Events

wxComboBox generates wxCommandEvent propagating events, described in Table 4-23.

Table 4-23 wxComboBox Events

Image

wxComboBox Member Functions

These are the major wxComboBox functions. Please refer also to the wxControlWithItems member functions from earlier in this chapter.

Copy copies the selected text onto the clipboard from the text field. Cut does the same, and it also deletes the selected text. Paste copies text from the clipboard into the text field.

GetInsertionPoint returns the insertion point for the combo box’s text field (a long integer representing the position), and SetInsertionPoint sets it. Use SetInsertionPointEnd to set the insertion point at the end of the text field.

GetLastPosition returns the last position in the text field.

GetValue returns the value of the text field, and SetValue sets it. For a combo box with the wxCB_READONLY style, the string must be in the combo box choices list; otherwise, the call is ignored in release mode, and it displays an alert in debug mode.

SetSelection with two arguments selects the text in the combo box text field between two given positions. Replace replaces the text between two given positions with specified text. Remove removes the text between two given positions.

See also the following functions from wxControlWithItems: Clear, Delete, FindString, GetClientData, GetClientObject, SetClientData, SetClientObject, GetCount, GetSelection, SetSelection, GetString, SetString, GetStringSelection, SetStringSelection, Insert, and IsEmpty.

wxCheckBox

A check box is a control that normally has two states: on or off. It is represented by a box containing a cross or tick if checked, with a label to the left or right of the check box. Optionally, it can have a third state, called the mixed or undetermined state, which can be used to indicate that the item does not apply (for example, a component in an installer that is always installed and therefore cannot be selected or deselected).

Here’s a simple example of creating a check box:

#include "wx/checkbox.h"

wxCheckBox* checkbox = new wxCheckBox(panel, ID_CHECKBOX,
    wxT("&Check me"), wxDefaultPosition, wxDefaultSize);
checkBox->SetValue(true);

Figure 4-15 shows how this looks on Windows.

Figure 4-15 A wxCheckBox

A wxCheckBox

A check box with the wxCHK_3STATE style looks like Figure 4-16 on Windows.

Figure 4-16 A three-state wxCheckBox

A three-state wxCheckBoxnon-static controlswxCheckBoxwxCheckBoxnon-static controls

wxCheckBox Styles

Table 4-24 lists the specific window styles for wxCheckBox.

Table 4-24 wxCheckBox Styles

Image

wxCheckBox Events

wxCheckBox generates wxCommandEvent propagating events, described in Table 4-25.

Table 4-25 wxCheckBox Events

Image

wxCheckBox Member Functions

These are the major wxCheckBox functions.

SetLabel and GetLabel are accessors for the check box label. You can use an ampersand to indicate that the following letter is the mnemonic (or “access key”) on Windows and GTK+.

GetValue and SetValue get and set the boolean state. Use Get3StateValue or Set3StateValue to get and set one of wxCHK_UNCHECKED, wxCHK_CHECKED, or wxCHK_UNDETERMINED.

Is3State can be used to determine whether the check box is a three-state check box.

IsChecked returns true if the check box is checked.

wxListBox and wxCheckListBox

A wxListBox is used to select one or more of a list of strings, numbered from zero. The strings are displayed in a scrolling box, with the selected strings marked in reverse video. A list box can be single-selection: if an item is selected, the previous selection is removed. In a multiple-selection list box, clicking an item toggles the item on or off independently of other selections.

Here’s an example of creating a single-selection list box:

#include "wx/listbox.h"

wxArrayString strings;
strings.Add(wxT("First string"));
strings.Add(wxT("Second string"));
strings.Add(wxT("Third string"));
strings.Add(wxT("Fourth string"));
strings.Add(wxT("Fifth string"));
strings.Add(wxT("Sixth string"));

wxListBox* listBox = new wxListBox(panel, ID_LISTBOX,
    wxDefaultPosition, wxSize(180, 80), strings, wxLB_SINGLE);

Figure 4-17 shows what this looks like under Windows.

Figure 4-17 A wxListBox

A wxListBox

wxCheckListBox is derived from wxListBox and inherits its functionality, but in addition, it can display a check box next to each item label. Include wx/checklst.h to use this class. Figure 4-18 shows a wxCheckListBox on Windows.

Figure 4-18 A wxCheckListBox

A wxCheckListBox

If you have a lot of items to display, consider using wxVListBox. This is a virtual list box that displays data directly from a source that you specify by deriving a new class and implementing the functions OnDrawItem and OnMeasureItem. Its event macros are the same as for wxListBox.

wxHtmlListBox is derived from wxVListBox and offers an easy way to display complex items. wxHtmlListBox obtains HTML fragments from the OnGetItem function, which your derived class must override. Figure 4-19 shows the wxWidgets wxHtmlListBox sample (in samples/htlbox), with custom separators drawn by an overridden OnDrawSeparator function.

Figure 4-19 The wxHtmlListBox sample

The wxHtmlListBox sample

wxListBox and wxCheckListBox Styles

Table 4-26 lists the specific window styles for wxListBox and wxCheckListBox.

Table 4-26 wxListBox and wxCheckListBox Styles

Image

wxListBox and wxCheckListBox Events

wxListBox and wxCheckListBox generate wxCommandEvent propagating events, described in Table 4-27.

Table 4-27 wxListBox Events

Image

wxListBox Member Functions

These are the major wxListBox functions.

Deselect deselects an item in the list box.

GetSelections fills a wxArrayInt array with the positions of the currently selected items and returns it.

InsertItems inserts the given number of strings before the specified position. Pass either the number of items, a C++ array of wxStrings, and the insertion position, or a wxArrayString object and the insertion position.

Selected returns true if the given item is selected.

Set clears the list box and adds the given strings to it. Pass either the number of items, a C++ array of wxStrings, and an optional array of void* client data, or a wxArrayString object and an optional array of void* client data.

SetFirstItem sets the specified item to be the first visible item.

SetSelection and SetStringSelection take an integer or string item and an optional boolean for the selection state, defaulting to true.

See also the wxControlWithItems functions: Clear, Delete, FindString, GetClientData, GetClientObject, SetClientData, SetClientObject, GetCount, GetSelection, GetString, SetString, GetStringSelection, Insert, and IsEmpty.

wxCheckListBox Member Functions

In addition to wxListBox’s functions, wxCheckListBox has the following functions.

Check takes an item index and boolean and checks or unchecks the item.

IsChecked returns true if the given item is checked, and false otherwise.

wxRadioBox

A radio box is used to select an item from a number of mutually exclusive buttons. It is displayed as a vertical column or horizontal row of labeled buttons, within a static box, which may have a label.

The way that the buttons are laid out depends on two constructor parameters: the major dimension, and the orientation style, which can be wxRA_SPECIFY_COLS (the default) or wxRA_SPECIFY_ROWS. The major dimension is the number of rows or columns. For example, eight buttons laid out with a major dimension of two and the wxRA_SPECIFY_COLS style will have two columns and four rows. Changing to wxRA_SPECIFY_ROWS will give the radio box two rows and four columns.

Here’s an example of creating a radio box with three columns:

#include "wx/radiobox.h"

wxArrayString strings;
strings.Add(wxT("&One"));
strings.Add(wxT("&Two"));
strings.Add(wxT("T&hree"));
strings.Add(wxT("&Four "));
strings.Add(wxT("F&ive "));
strings.Add(wxT("&Six "));

wxRadioBox* radioBox = new wxRadioBox(panel, ID_RADIOBOX,
    wxT("Radiobox"), wxDefaultPosition, wxDefaultSize,
    strings, 3, wxRA_SPECIFY_COLS);

The constructor specifies that the buttons should be laid out in three columns. On Windows, this produces the result shown in Figure 4-20.

Figure 4-20 A wxRadioBox

A wxRadioBox

wxRadioBox Styles

wxRadioBox can have the window styles listed in Table 4-28 in addition to those described for wxWindow. Specifying a different major dimension changes the button ordering.

Table 4-28 wxRadioBox Styles

Image

wxRadioBox Events

wxRadioBox generates wxCommandEvent propagating events, as shown in Table 4-29.

Table 4-29 wxRadioBox Events

Image

wxRadioBox Member Functions

These are the major wxRadioBox functions.

Enable with an index and a boolean enables or disables a specified button.

FindString returns the index of a button matching the given string, or wxNOT_FOUND if no match was found.

GetCount returns the number of buttons in the radio box.

GetString and SetString are accessors for the label of the specified button. GetLabel and SetLabel set the radio box label.

GetSelection returns the zero-based index of the selected radio button. GetStringSelection returns the label of the selected button. SetSelection and SetStringSelection set the selection without generating a command event.

Show shows or hides an individual button or the whole radio box.

wxRadioButton

A radio button usually denotes one of several mutually exclusive options. It has a text label next to a button, which is normally round in appearance.

It has two states: on or off. You can create a group of mutually exclusive radio buttons by specifying wxRB_GROUP for the first in the group. The group ends when another radio button group is created, or when there are no more controls. You can also create other types of control within a group.

You might use a group of radio buttons instead of a radio box when the layout is slightly more complex: for example, you may have an extra description or other control next to each radio button. Or you may use radio buttons simply to avoid the static box that wxRadioBox provides.

Figure 4-21 A pair of radio buttons

A pair of radio buttons

Here’s a simple example of a group of two radio buttons.

#include "wx/radiobut.h"

wxRadioButton* radioButton1 = new wxRadioButton (panel,
    ID_RADIOBUTTON1, wxT("&Male"), wxDefaultPosition,
    wxDefaultSize, wxRB_GROUP);
radioButton1->SetValue(true);
wxRadioButton* radioButton2 = new wxRadioButton (panel,
    ID_RADIOBUTTON2, wxT("&Female"));

// Sizer code to group the buttons horizontally
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(radioButton1, 0, wxALIGN_CENTER_VERTICAL¦wxALL, 5);
sizer->Add(radioButton2, 0, wxALIGN_CENTER_VERTICAL¦wxALL, 5);
parentSizer->Add(sizer, 0, wxALIGN_CENTER_VERTICAL¦wxALL, 5);

On Windows, this will create the controls shown in Figure 4-21.

Figure 4-22 A wxScrollBar

A wxScrollBar

wxRadioButton Styles

Table 4-30 lists the specific window styles for wxRadioButton.

Table 4-30 wxRadioButton Styles

Image

wxRadioButton Events

wxRadioButton generates wxCommandEvent propagating events, which are described in Table 4-31.

Table 4-31 wxRadioButton Events

Image

wxRadioButton Member Functions

GetValue and SetValue get and set the boolean state.

wxScrollBar

A wxScrollBar is a control that represents a horizontal or vertical scrollbar. It is distinct from the two scrollbars that some windows provide automatically, but the two types of scrollbar share the way events are received. A scrollbar has the following main attributes: range, thumb size, page size, and position.

The range is the total number of units associated with the view represented by the scrollbar. For a table with 15 columns, the range would be 15.

The thumb size is the number of units that are currently visible. For the table example, the window might be sized so that only 5 columns are currently visible, in which case the application would set the thumb size to 5. When the thumb size becomes the same as or greater than the range, the scrollbar will automatically be hidden on most platforms.

The page size is the number of units that the scrollbar should scroll when paging through the data.

The scrollbar position is the current thumb position.

To create a scrollbar control, pass the usual parent window, identifier, position, size, and style parameters. For example:

#include "wx/scrolbar.h"

wxScrollBar* scrollBar = new wxScrollBar(panel, ID_SCROLLBAR,
    wxDefaultPosition, wxSize(200, 20), wxSB_HORIZONTAL);

Under Windows, this will look like the control in Figure 4-22.

After creation, call SetScrollbar to set its properties. For more information on using this function, see the description of wxScrolledWindow earlier in this chapter.

wxScrollBar Styles

Table 4-32 lists the specific window styles for wxScrollBar.

Table 4-32 wxScrollBar Styles

Image

wxScrollBar Events

wxScrollBar generates wxScrollEvent propagating events. You can use EVT_COMMAND_SCROLL... macros with window identifiers when intercepting scroll events from controls, or EVT_SCROLL... macros without window identifiers for intercepting scroll events from the receiving window—except for this, the macros behave exactly the same. Use EVT_SCROLL(func) to respond to all scroll events. For a comprehensive list of scroll event macros, please see Table I-1 in Appendix I, “Event Classes and Macros,” and also see the reference manual.

wxScrollBar Member Functions

These are the major wxScrollBar functions.

GetRange returns the length of the scrollbar.

GetPageSize returns the number of scroll units that will be scrolled when the user pages up or down. Often it is the same as the thumb size.

GetThumbPosition and SetThumbPosition are accessors for the current position of the scrollbar thumb.

GetThumbLength returns the thumb or “view” size.

SetScrollbar sets the scrollbar properties. It takes the position in scroll units, thumb size, range, page size, and optional boolean to specify whether the control will be refreshed.

wxSpinButton

wxSpinButton has two small up and down (or left and right) arrow buttons. It is often used next to a text control for incrementing and decrementing a value. Portable programs should try to use wxSpinCtrl instead as wxSpinButton is not implemented for all platforms.

The range supported by this control (and wxSpinCtrl) depends on the platform but is at least -32768 to 32767.

To create a wxSpinButton control, pass the usual parent window, identifier, position, size, and style parameters. For example:

#include "wx/spinbutt.h"

wxSpinButton* spinButton = new wxSpinButton(panel, ID_SPINBUTTON,
    wxDefaultPosition, wxDefaultSize, wxSP_VERTICAL);

On Windows, the result is the control shown in Figure 4-23.

Figure 4-23 A wxSpinButton

A wxSpinButton

wxSpinButton Styles

Table 4-33 lists the specific window styles for wxSpinButton.

Table 4-33 wxSpinButton Styles

Image

wxSpinButton Events

wxSpinButton generates wxSpinEvent propagating events, as shown in Table 4-34.

Table 4-34 wxSpinButton Events

Image

wxSpinButton Member Functions

These are the major wxSpinButton functions.

GetMax returns the maximum permissible value.

GetMin returns the minimum permissible value.

GetValue returns the current spin button value, and SetValue sets the current spin value.

SetRange sets the minimum and maximum values.

wxSpinCtrl

wxSpinCtrl combines a wxTextCtrl and a wxSpinButton into one control. When you click on the up and down arrow buttons, the value displayed in the text control will be incremented or decremented, and you can also type integers directly into the text control.

To create a wxSpinCtrl control, pass the usual parent window, identifier, position, size, and style parameters. The following code creates a spin control with a range of zero to 100 and an initial value of 5.

#include "wx/spinctrl.h"

wxSpinCtrl* spinCtrl = new wxSpinCtrl(panel, ID_SPINCTRL,
    wxT("5"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS,
    0, 100, 5);

On Windows, this will look like the control in Figure 4-24.

Figure 4-24 A wxSpinCtrl

A wxSpinCtrl

wxSpinCtrl Styles

Table 4-35 lists the specific window styles for wxSpinCtrl.

Table 4-35 wxSpinCtrl Styles

Image

wxSpinCtrl Events

wxSpinCtrl generates wxSpinEvent propagating events as shown in Table 4-36. You can also use EVT_TEXT to intercept text updates with a wxCommandEvent handler.

Table 4-36 wxSpinCtrl Events

Image

wxSpinCtrl Member Functions

These are the major wxSpinCtrl functions.

GetMax returns the maximum permissible value.

GetMin returns the minimum permissible value.

GetValue returns the current integer spin button value, and SetValue sets the current spin value.

SetRange sets the minimum and maximum values.

wxSlider

A slider is a control with a handle that can be moved back and forth to change the value.

To create a wxSlider control, pass the usual parent window, identifier, position, size, and style parameters. The following code creates a slider control with a range of zero to 40 and an initial position of 16.

#include "wx/slider.h"

wxSlider* slider = new wxSlider(panel, ID_SLIDER, 16, 0, 40,
    wxDefaultPosition, wxSize(200, -1),
    wxSL_HORIZONTAL¦wxSL_AUTOTICKS¦wxSL_LABELS);

On Windows, this creates the control shown in Figure 4-25.

Figure 4-25 A wxSlider

A wxSlider

wxSlider Styles

Table 4-37 lists the specific window styles for wxSlider.

Table 4-37 wxSlider Styles

Image

wxSlider Events

wxSlider generates wxCommandEvent propagating events, as shown in Table 4-38, but if you need finer control, you can use EVT_COMMAND_SCROLL_... with wxScrollEvent handlers; see Table I-1 in Appendix I.

Table 4-38 wxSlider Events

Image

wxSlider Member Functions

These are the major wxSlider functions.

ClearSel clears the selection for a slider with wxSL_SELRANGE on Windows. ClearTicks clears the ticks on Windows.

GetLineSize and SetLineSize are accessors for the number of units incremented or decremented when the arrow buttons are clicked. GetPageSize and SetPageSize are accessors for the number of units paged when clicking either side of the thumb.

GetMax returns the maximum permissible value.

GetMin returns the minimum permissible value.

GetSelEnd and GetSelStart return the selection end and start points; use SetSelection to set the selection. These functions are only implemented on Windows.

GetThumbLength and SetThumbLength are accessors for the slider thumb size.

GetTickFreq and SetTickFreq are accessors for the tick frequency on Windows. Use SetTick to set a tick position on Windows.

GetValue returns the current slider value, and SetValue sets the slider value.

SetRange sets the minimum and maximum values.

wxTextCtrl

The text control enables text to be displayed and edited, either as a single-line or a multi-line control. Some simple styling and formatting is supported on some platforms (Windows, GTK+, and Mac OS X via setting and getting text attributes using the wxTextAttr class.

To create a text control, pass the usual parent window, identifier, position, size, and style parameters, plus the initial text. For example, to create a multi-line text control:

#include "wx/textctrl.h"

wxTextCtrl* textCtrl = new wxTextCtrl(panel, ID_TEXTCTRL,
    wxEmptyString, wxDefaultPosition, wxSize(240, 100),
    wxTE_MULTILINE);

On Windows, this will create the control shown in Figure 4-26.

Figure 4-26 A multiline wxTextCtrl

A multiline wxTextCtrl

Multi-line text controls always store text as a sequence of lines separated by characters, using Unix newlines even on non-Unix platforms. As a result, you can ignore the differences between platforms, but at a price: indices such as those returned by GetInsertionPoint or GetSelection cannot be used as indices into the string returned by GetValue as they’re going to be slightly off for platforms using as the separator as Windows does.

Instead, if you need to obtain a substring between the two indices obtained from the control with the help of the functions mentioned previously, you should use GetRange. The indices themselves can only be passed to other methods, such as SetInsertionPoint or SetSelection. Never use the indices returned by multi-line text controls as indices into the string it contains, but only as arguments to be passed back to other wxTextCtrl methods.

Multi-line text controls support setting styles: you can set colors and fonts for individual characters. Note that under Windows, the wxTE_RICH style is required for style support. To use the styles, you can either call SetDefaultStyle before inserting the text or call SetStyle later to change the style of the text already in the control. The first method is much more efficient.

In either case, if the style doesn’t specify some of the attributes, the values of the default style will be used. If there is no default style, the attributes of the text control itself are used.

In the following code, the second call to SetDefaultStyle doesn’t change the text foreground color (which stays red), while the last one doesn’t change the background color (which stays gray):

text->SetDefaultStyle(wxTextAttr(*wxRED));
text->AppendText(wxT("Red text "));
text->SetDefaultStyle(wxTextAttr(wxNullColour, *wxLIGHT_GREY));
text->AppendText(wxT("Red on gray text "));
text->SetDefaultStyle(wxTextAttr(*wxBLUE);
text->AppendText(wxT("Blue on gray text "));

wxTextCtrl Styles

Table 4-39 lists the specific window styles for wxTextCtrl.

Table 4-39 wxTextCtrl Styles

Image Image

wxTextCtrl Events

wxTextCtrl generates wxCommandEvent propagating events, as described in Table 4-40.

Table 4-40 wxTextCtrl Events

Image

wxTextCtrl Member Functions

These are the major wxTextCtrl functions.

AppendText appends the given text to the end of the text control, and WriteText writes the text at the current insertion point. SetValue clears and then sets the value, after which IsModified returns false. You can pass strings with newlines for a multi-line text control. Be aware that these functions send text update events.

GetValue returns the entire contents of the control, possibly with newlines for a multi-line control. GetLineText gets just one line from a multi-line control. GetRange gets the text between two positions.

Copy copies the selected text onto the clipboard from the text field. Cut does the same, and it also deletes the selected text. Paste copies text from the clipboard into the text field. You can use CanCopy, CanCut, and CanPaste in UI update event handlers.

Clear clears the text in the control. Note that this will generate a text update event.

DiscardEdits resets the internal “modified” flag as if the current edits had been saved.

EmulateKeyPress inserts the character that would have been inserted if the given key event had occurred in the text control.

GetDefaultStyle and SetDefaultStyle are accessors for the font currently used for new text. GetStyle returns the style at the given position in the text, and SetStyle sets the style for the given range.

GetInsertionPoint and SetInsertionPoint get and set the current insertion point for new text. GetLastPosition returns the last position in the control, and SetInsertionPointEnd sets the insertion point at the end of the text.

GetLineLength returns the length of the specified line in characters.

GetNumberOfLines returns the number of lines of text in the control.

GetStringSelection returns the text currently selected in the control, or an empty string if there is no selection. GetSelection returns the current selection span in two pointers to long integers. SetSelection selects the text range indicated by two long integers representing positions in the text.

IsEditable returns true if the contents may be edited. Call SetEditable to make the control read-only or writeable. IsModified returns true if the user has modified the text. IsMultiline returns true if the control is multi-line.

LoadFile loads text from a file into the control, and SaveFile saves the contents as a file.

PositionToXY converts a pixel position to character position and line number, whereas XYToPosition goes the other way.

Remove removes the text in the given span. Replace replaces the text in the given span.

ShowPosition makes the line containing the given position visible.

Undo undoes the last edit, and Redo redoes the last edit. This may do nothing on some platforms. You can use CanUndo and CanRedo to test whether these operations can be applied to the control’s text (but not whether the platform supports undo/redo).

wxToggleButton

wxToggleButton is a button that stays pressed when clicked. In other words, it is similar to wxCheckBox in functionality but looks like a wxButton.

Here’s a simple example of creating a toggle button:

#include "wx/tglbtn.h"

wxToggleButton* toggleButton = new wxToggleButton(panel, ID_TOGGLE,
    wxT("&Toggle label"), wxDefaultPosition, wxDefaultSize);
toggleButton->SetValue(true);

Figure 4-27 shows how a toggle button looks on Windows in the toggled state.

Figure 4-27 A wxToggleButton

A wxToggleButton

wxToggleButton Styles

There are no specific wxToggleButton styles.

wxToggleButton Events

wxToggleButton generates wxCommandEvent propagating events, described in Table 4-41.

Table 4-41 wxToggleButton Events

Image

wxToggleButton Member Functions

These are the major wxToggleButton functions.

SetLabel and GetLabel are accessors for the button label. You can use an ampersand to indicate that the following letter is the mnemonic (or “access key”), used on Windows and GTK+.

GetValue and SetValue get and set the boolean state.

Static Controls

Static controls do not take any input and are used to display information or to enhance the application’s aesthetics.

wxGauge

This is a horizontal or vertical bar that shows a quantity (often time) from zero to the specified range. No command events are generated for the gauge. Here’s a simple example of creating a gauge:

#include "wx/gauge.h"

wxGauge* gauge = new wxGauge(panel, ID_GAUGE,
  200, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL);
gauge->SetValue(50);

Under Windows, this is displayed as shown in Figure 4-28.

Figure 4-28 A wxGauge

A wxGaugenon-static controlswxGaugewxGaugenon-static controls

wxGauge Styles

Table 4-42 lists the specific window styles for wxGauge.

Table 4-42 wxGauge Styles

Image

wxGauge Events

Because it only displays information, wxGauge does not generate events.

wxGauge Member Functions

These are the major wxGauge functions.

GetRange and SetRange are accessors for the gauge range (the maximum integer value).

GetValue and SetValue get and set the integer value of the gauge.

IsVertical returns true if the gauge is vertical, and false if horizontal.

wxwStaticText

A static text control displays one or more lines of read-only text.

To create a wxStaticText control, pass a parent window, identifier, label, position, size, and style. For example:

#include "wx/stattext.h"

wxStaticText* staticText = new wxStaticText(panel, wxID_STATIC,
  wxT("This is my &static label"),
  wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);

Under Windows, this creates the control shown in Figure 4-29.

Figure 4-29 A wxStaticText

A wxStaticText

An ampersand in the label (as shown here) indicates to some platforms—currently Windows and GTK+—that the following letter should be underscored and used as a shortcut key for navigating to the next non-static control.

wxStaticText Styles

Table 4-43 lists the specific window styles for wxStaticText.

Table 4-43 wxStaticText Styles

Image

wxStaticText Member Functions

GetLabel and SetLabel are accessors for the text label.

wxStaticBitmap

A static bitmap control displays an image.

To create a wxStaticBitmap control, pass a parent window, identifier, bitmap, position, size and style. For example:

#include "wx/statbmp.h"
#include "print.xpm"

wxBitmap bitmap(print_xpm);
wxStaticBitmap* staticBitmap = new wxStaticBitmap(panel, wxID_STATIC,
  bitmap);

This produces a simple image on the panel or dialog as shown in Figure 4-30.

Figure 4-30 A wxStaticBitmap

A wxStaticBitmapstatic controlswxStaticBitmapwxStaticBitmapstatic controls

wxStaticBitmap Styles

There are no special styles for wxStaticBitmap.

wxStaticBitmap Member Functions

GetBitmap and SetBitmap are accessors for the bitmap label.

wxStaticLine

This control displays a horizontal or vertical line, to be used as a separator in dialogs.

Here’s an example of creating a wxStaticLine control:

#include "wx/statline.h"

wxStaticLine* staticLine = new wxStaticLine(panel, wxID_STATIC,
    wxDefaultPosition, wxSize(150, -1), wxLI_HORIZONTAL);

Figure 4-31 shows what a horizontal static line looks like under Windows.

Figure 4-31 A wxStaticLine

A wxStaticLine

wxStaticLine Styles

Table 4-44 lists the specific window styles for wxStaticLine.

Table 4-44 wxStaticLine Styles

Image

wxStaticLine Member Functions

IsVertical returns true if the line is vertical, false otherwise.

wxStaticBox

This control is a rectangle drawn around other controls to denote a logical grouping of items, with an optional text label. At present, the control should not be used as a parent for further controls; the controls that it surrounds are actually siblings of the box and should be created after it but with the same parent as the box. Future versions of wxWidgets may allow contained controls to be either siblings or children.

Here’s an example of creating a wxStaticBox control:

#include "wx/statbox.h"

wxStaticBox* staticBox = new wxStaticBox(panel, wxID_STATIC,
  wxT("&Static box"), wxDefaultPosition, wxSize(100, 100));

This will look like the control in Figure 4-32 under Windows.

Figure 4-32 A wxStaticBox

A wxStaticBoxstatic controlswxStaticBoxwxStaticBoxstatic controls

wxStaticBox Styles

There are no special styles for wxStaticBox.

wxStaticBox Member Functions

Use GetLabel and SetLabel to get and set the static box text.

Menus

In this section, we’ll describe programming with wxMenu, a simple way to present commands without taking up a lot of display space. In the next section, we’ll look at how menus are used in menu bars.

wxMenu

A menu is a list of commands that pops up either from a menu bar or on an arbitrary window, often as a “context menu” invoked by clicking the right mouse button (or equivalent). A menu item can be a normal command, or it can have a check or radio button next to the label. A menu item in a disabled state won’t respond to commands. A special kind of menu item can display a visual indication of a further pull-right menu, and this can be nested to an arbitrary level. Another kind of menu item is the separator, which simply displays a line or space to indicate separation between two groups of items.

Figure 4-33 shows a typical menu with normal, check, and radio items and a submenu.

Figure 4-33 A typical menu

A typical menu

The example shows the use of both mnemonics and shortcuts. A mnemonic is a highlighted key in a label (such as the “N” in “New”) that can be pressed when the menu is shown to execute that command. Specify a mnemonic by preceding the letter with an ampersand (“&”). A shortcut (or accelerator) is a key combination that can be used when the menu is not shown, and it is indicated in a menu item by a key combination following a tab character. For example, the New menu item in the example was created with this code:

menu->Append(wxID_NEW, wxT("&New... Ctrl+N"));

For more on creating accelerators via menu items or by programming with wxAcceleratorTable, please see Chapter 6.

Check and radio items automatically update their state; that is, when the user toggles a check item, it will be shown in the reverse state when the menu is next popped up. Similarly, consecutive radio items form a group and when one item is checked, the other items in the group are unchecked. You can also set these states yourself, for example from a user interface update event handler (see Chapter 9).

You can create a menu and show it at a particular point in a window using wxWindow::PopupMenu, for example:

void wxWindow::OnRightClick(wxMouseEvent& event)
{
    if (!m_menu)
    {
        m_menu = new wxMenu;
        m_menu->Append(wxID_OPEN, wxT("&Open"));
        m_menu->AppendSeparator();
        m_menu->Append(wxID_EXIT, wxT("E&xit"));
    }

    PopupMenu(m_menu, event.GetPosition());
}

Events are sent to the menu itself before travelling up the hierarchy of windows starting from the window the popup menu was shown on. PopupMenu will cause program flow to “block” at this point, resuming when the user has dismissed the menu. If you want, you can delete and re-create the menu every time it needs to be shown, or you can reuse the same menu.

Where possible, use standard wxWidgets identifiers in menus, such as wxID_OPEN, wxID_ABOUT, wxID_PRINT, and so on. You can find a full list of these in Chapter 3. In particular, wxID_ABOUT, wxID_PREFERENCES and wxID_EXIT are interpreted specially on Mac OS X. When used in a menu bar, these menu items are not shown in the menus to which they are appended, but are shown instead in the standard application menu. Thus wxWidgets adapts your menus automatically to Mac OS X conventions, but beware of side effects such as a Help menu with no menu items, or two separators together.

See samples/menu in the wxWidgets distribution for a test of most menu functionality, and also see samples/ownerdrw for a demonstration of the use of custom fonts and bitmaps in menu items.

wxMenu Events

There are four different kinds of event associated with wxMenu: wxCommandEvent, wxUpdateUIEvent, wxMenuEvent, and wxContextMenuEvent.

Table 4-45 lists the command events, whose handlers take a wxCommandEvent argument. Use these for processing menu commands, either from a pop-up menu or a menu bar on a frame. These are interchangeable with the equivalent toolbar event macros so that events generated from both menus and toolbar buttons can be processed by the same handler.

Table 4-45 wxMenu Command Events

Image

Table 4-46 lists the event macros for update events—events generated by the framework in idle time to give the application a chance to update elements of the UI—for example, enabling or disabling menu items. Although wxUpdateUIEvent applies to all windows, menu event handlers can use them slightly differently than other event handlers: they can call Check and SetText as well as Enable. Check checks or unchecks the menu item, while SetText sets the menu item label, which is useful if the label changes dynamically according to some condition. For example:

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_UPDATE_UI(ID_TOGGLE_TOOLBAR, MyFrame::OnUpdateToggleToolbar)
END_EVENT_TABLE()

void MyFrame::OnUpdateToggleToolbar(wxUpdateUIEvent& event)
{
    event.Enable(true);
    event.Check(m_showToolBar);
    event.SetText(m_showToolBar ?
                  wxT("Show &Toolbar (shown)") :
                  wxT("Show &Toolbar (hidden)"));
}

Table 4-46 wxMenu Update Events

Image

For more on UI update events, please see Chapter 9.

Table 4-47 lists the other menu-related events. EVT_CONTEXT_MENU handlers take a wxContextMenuEvent, which is derived from wxCommandEvent and therefore propagates up the parent-child window hierarchy. Use this in preference to intercepting a right mouse button click when you want to show a context menu, and call the event object’s GetPosition function to find out where to show the menu.

Table 4-47 Other wxMenu Events

Image

The remaining macros process wxMenuEvent objects, and these are only sent from a menu bar to its frame. They tell the application when a menu has been opened and closed, and when the user has highlighted a menu item. The default EVT_MENU_HIGHLIGHT handler shows a menu item’s help string in the status bar, but you can provide your own handler to do something different.

wxMenu Member Functions

These are the major wxMenu functions.

Append adds a menu item: specify an identifier, a label, a help string, and the kind of item (wxITEM_NORMAL, wxITEM_SEPARATOR, wxITEM_CHECK or wxITEM_RADIO). You can also use AppendCheckItem and AppendRadioItem to avoid specifying wxITEM_CHECK or wxITEM_RADIO. For example:

// Append a normal item
menu->Append(wxID_NEW, wxT("&New... Ctrl+N"));

// Append a check item
menu->AppendCheckItem(ID_SHOW_STATUS, wxT("&Show Status"));

// Append a radio item
menu->AppendRadioItem(ID_PAGE_MODE, wxT("&Page Mode"));

Another overload of Append enables you to append a submenu, for example:

// Append a submenu
menu->Append(ID_SUBMENU, wxT("&More options..."), subMenu);

Yet another overload of Append enables you to use a wxMenuItem object directly to append an item, and this is the only way to show bitmaps on menus or to set special fonts. For example:

// Initialization of bitmaps and font not shown
wxBitmap bmpEnabled, bmpDisabled;
wxFont fontLarge;

// Create a menu item
wxMenuItem* pItem = new wxMenuItem(menu, wxID_OPEN, wxT("&Open..."));

// Set bitmaps and font
pItem->SetBitmaps(bmpEnabled, bmpDisabled);
pItem->SetFont(fontLarge);

// Finally append it to the menu
menu->Append(pItem);

Use Insert to insert a menu at a particular position. There are also the functions Prepend, PrependCheckItem, PrependRadioItem, and PrependSeparator for inserting items at the start of the menu.

AppendSeparator adds a separator, and InsertSeparator inserts a separator in a given position. For example:

// Append a separator
menu->AppendSeparator();

Break inserts a break in a menu, causing the next appended item to appear in a new column.

Use Check to toggle a check or radio item on or off, passing the menu item identifier and a boolean value. Use IsChecked to get the checked status.

Delete deletes a menu item specified by identifier or by wxMenuItem pointer. If the item is a menu, the submenu will not be deleted. Use Destroy if you want to remove and delete a submenu. Remove removes the menu item from a menu without deleting the returned wxMenuItem object.

Use Enable to enable or disable a menu item, but rather than doing this explicitly, you may want to use UI update events (see Chapter 9). IsEnabled returns the enabled status.

Use FindItem to find an item by label or identifier. Use FindItemByPosition to find an item by position in the menu.

GetHelpString and SetHelpString are accessors for the help string associated with a menu item. When the menu is part of a menu bar, wxFrame shows this string in the status bar (if available), as the user highlights each menu item.

GetLabel and SetLabel get or set the menu item label, given its identifier.

GetMenuCount returns the number of items in the menu.

GetMenuItems returns a reference to the list of menu items, a wxMenuItemList object.

GetTitle and SetTitle are accessors for the optional title of a menu and are only used for pop-up menus.

UpdateUI sends UI update events to the event handler argument or to the owning window if NULL is passed. This is called just before the menu is popped up, but the application may call it at other times if required.

Control Bars

A control bar provides a convenient way to contain and arrange multiple controls. There are currently three kinds of control bars: wxMenuBar, wxToolBar, and wxStatusBar. wxMenuBar can only belong to a wxFrame. wxToolBar and wxStatusBar are most commonly used with wxFrame, but they can also be children of other windows.

wxMenuBar

A menu bar contains a series of menus accessible from the top of a frame under the title bar. You can replace a frame’s current menu bar by calling SetMenuBar. To create a menu bar, use the default constructor and append wxMenu objects. For example:

wxMenuBar* menuBar = new wxMenuBar;
wxMenu* fileMenu = new wxMenu;
fileMenu->Append(wxID_OPEN, wxT("&Open..."), wxT("Opens a file"));
fileMenu->AppendSeparator();
fileMenu->Append(wxID_EXIT, wxT("E&xit"), wxT("Quits the program"));
menuBar->Append(fileMenu);
frame->SetMenuBar(menuBar, wxT("&File"));

This code creates a one-menu menu bar, as shown in Figure 4-34.

Figure 4-34 A wxMenuBar

A wxMenuBar

You can append submenus to a wxMenu, and you can create check and radio menu items (refer to the “Menus” section earlier in this chapter). As in the previous example, an ampersand in a label indicates that the following character should be used as a mnemonic (pressing that key when the menu is shown executes the associated command).

If you provide a help string, it will be shown in the frame’s status bar (if any) by virtue of the default EVT_MENU_HIGHLIGHT handler.

wxMenuBar Styles

wxMenuBar takes the wxMB_DOCKABLE style, used under GTK+ to allow the menu bar to be detached from the frame.

wxMenuBar Events

Menu bars use the events already covered in the description of wxMenu.

wxMenuBar Member Functions

These are the major wxMenuBar functions.

Append adds a menu to the end of the menu bar, which will then own the menu and will destroy it when the menu bar is destroyed (usually by the owning frame). Pass the menu and a label. Insert inserts a menu at the given position.

Enable enables or disables the given menu item, given its identifier. Use IsEnabled to check its enabled status.

Check checks or unchecks a check or radio menu item. Use IsChecked to test its checked status.

EnableTop enables or disables a whole menu, by zero-based position.

FindMenu returns the index of a menu whose label matches the given string, with or without mnemonic characters. It returns wxNOT_FOUND if there was no match.

FindMenuItem returns the index of a menu item given a menu name and a menu item.

FindItem returns the wxMenuItem object given a menu item identifier, and if it is a submenu, its wxMenu pointer will be returned in the second argument.

GetHelpString and SetHelpString are accessors for the help string for a given menu item.

GetLabel and SetLabel are accessors for a menu item’s label.

GetLabelTop and SetLabelTop are accessors for a menu’s label in the menu bar, given the zero-based menu position.

GetMenu returns a pointer to the wxMenu at the given zero-based position.

GetMenuCount returns the number of menus in the menu bar.

Refresh redraws the menu bar.

Remove removes a menu and returns the wxMenu object, which the application is then responsible for deleting.

Replace replaces a menu at the given position with another one. The old menu is returned, and the application is responsible for deleting it.

wxToolBar

A toolbar contains a number of buttons and controls. It can be horizontal or vertical, and the buttons can be push, check, or radio buttons. The buttons can show labels as well as bitmaps. If you use wxFrame::CreateToolBar to create the toolbar, or wxFrame::SetToolBar to associate it with a frame, the frame will manage the toolbar, and it will not be counted as part of the client area. If you use it in any other way, then your code will have to manage the toolbar size and position using sizers or some other method.

Here’s an example of creating a toolbar and associating it with a frame:

#include "wx/toolbar.h"

#include "open.xpm"
#include "save.xpm"

wxToolBar* toolBar = new wxToolBar(frame, wxID_ANY,
    wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL¦wxNO_BORDER);
wxBitmap bmpOpen(open_xpm);
wxBitmap bmpSave(save_xpm);
toolBar->AddTool(wxID_OPEN, bmpOpen, wxT("Open"));
toolBar->AddTool(wxID_SAVE, bmpSave, wxT("Save"));
toolBar->AddSeparator();
wxComboBox* comboBox = new wxComboBox(toolBar, ID_COMBOBOX);
toolBar->AddControl(comboBox);
toolBar->Realize();
frame->SetToolBar(toolBar);

Under Windows, this will create a toolbar, as shown in Figure 4-35.

Figure 4-35 A wxToolBar

A wxToolBar

Note the call to Realize, which must be performed after all buttons and controls have been added to the toolbar; otherwise, nothing will appear in the toolbar.

Check out the wxWidgets sample in samples/toolbar for a demonstration of changing orientation, showing labels on buttons, changing the button size, and other aspects of wxToolBar.

Tool Bitmap Colors Under Windows

Under Windows, wxWidgets will attempt to map colors in the tool bitmaps that are close to “standard” colors to equivalents used by the current theme. In particular, light gray is used to indicate transparency within the bitmap. Table 4-48 lists these colors. In fact, colors in the bitmap only have to be close to the indicated color (each RGB element can be within 10 units of the standard value) for the substitution to take place.

Table 4-48 Standard Bitmap Colors

Image

This is fine for 16-color tool bitmaps, but if you use more colors, the mapping can be undesirable because it leads to a grainy effect. In this case, add the following line to your code before the creation of the toolbar to switch off the mapping:

wxSystemOptions::SetOption(wxT("msw.remap"), 0);

You will need to include wx/sysopt.h in your source file.

wxToolBar Styles

Table 4-49 lists the specific window styles for wxToolBar.

Table 4-49 wxToolBar Styles

Image

wxToolBar Events

Toolbar event macros are listed in Table 4-50. The toolbar class emits menu commands in the same way that a frame’s menu bar does, so you can use one EVT_MENU or EVT_TOOL macro for both a menu item and a toolbar button. The event handler functions take a wxCommandEvent argument. For most of the event macros, the identifier of the tool is passed, but for EVT_TOOL_ENTER, the toolbar window identifier is passed, and the tool identifier is retrieved from the wxCommandEvent. This is because the identifier may be -1 when the mouse moves off a tool, and -1 is not allowed as an identifier in the event system.

Table 4-50 wxToolBar Events

Image

wxToolBar Member Functions

These are the major wxToolBar functions.

AddTool adds a tool: specify the identifier, an optional label, a bitmap, a help string, and the kind of tool (wxITEM_NORMAL, wxITEM_CHECK, or wxITEM_RADIO). Use InsertTool to insert the tool at a particular position. You can also use AddCheckTool and AddRadioTool to avoid specifying wxITEM_CHECK or wxITEM_RADIO. AddSeparator adds a separator, which is a line or a space depending on implementation. Use InsertSeparator to insert a separator in a given position. For example, the following line adds a checkable tool with a caption ("Save"), a bitmap, and a help string ("Toggle button 1"):

toolBar->AddTool(wxID_SAVE, wxT("Save"), bitmap,
                 wxT("Toggle button 1"), wxITEM_CHECK);

AddControl adds a control, such as a combo box. InsertControl inserts a control at a given position.

DeleteTool deletes a tool specified by identifier. DeleteToolByPos deletes a tool by position. RemoveTool removes a tool from the toolbar but doesn’t delete the wxToolBarTool object, which is returned from the function.

Use EnableTool to enable or disable a tool, but rather than doing this explicitly, you may want to use UI update events (see Chapter 9). GetToolEnabled returns the enabled status.

Use FindById and FindControl to find a tool or control by identifier.

If you need to add bitmaps with a size other than the default 16×15, call SetToolBitmapSize. GetToolBitmapSize returns the current bitmap size. GetToolSize returns the size including decorations around the tool.

GetMargins and SetMargins are accessors for the left/right and top/bottom margins.

GetToolClientData and SetToolClientData can be used to return or associate an arbitrary wxObject for a tool, given the tool identifier.

GetToolLongHelp and SetToolLongHelp are accessors for the long help string associated with a tool. This is a line of help that could be shown in a status bar, for example. GetToolShortHelp and SetToolShortHelp are accessors for the short help string (tooltip) associated with a tool.

GetToolPacking and SetToolPacking are accessors for the tool spacing in the vertical direction if the toolbar is horizontal, and for spacing in the horizontal direction if the toolbar is vertical.

GetToolPosition returns the position in the toolbar given a tool identifier.

GetToolSeparation and SetToolSeparation are accessors for the tool separator size.

GetToolState and SetToolState are accessors for a check or radio tool on/off state.

Realize must always be called after tools have been added.

ToggleTool toggles the given radio or check tool on or off.

wxStatusBar

A status bar is a narrow window that can be placed along the bottom of a frame to give small amounts of status information. It can contain one or more fields, which can have fixed or variable width. If you use wxFrame::CreateStatusBar to create the status bar, or wxFrame::SetStatusBar to associate it with a frame, the frame will manage the status bar, and it will not be counted as part of the client area. If you use it in any other way, then your code will have to manage the status bar size and position using sizers or some other method.

Here’s an example of creating a status bar with three fields, two that are 60 pixels wide and a third that expands to fill the rest of the status bar.

#include "wx/statusbr.h"

wxStatusBar* statusBar = new wxStatusBar(frame, wxID_ANY,
    wxST_SIZEGRIP);
frame->SetStatusBar(statusBar);
int widths[] = { 60, 60, -1 };
statusBar->SetFieldWidths(WXSIZEOF(widths), widths);
statusBar->SetStatusText(wxT("Ready"), 0);

The resulting status bar is shown in Figure 4-36.

Figure 4-36 A wxStatusBar

A wxStatusBar

If you want, you can create small controls inside status bar fields. You will have to manage their size and position yourself—for example, from within the size event handler of a class derived from wxStatusBar.

wxStatusBar Styles

Table 4-51 shows the specific window style for wxStatusBar. You can also determine the appearance of the individual field borders using SetStatusStyles.

Table 4-51 wxStatusBar Style

Image

wxStatusBar Events

There are no special events for wxStatusBar.

wxStatusBar Member Functions

These are the major wxStatusBar functions.

GetFieldRect returns the size and position of a field’s internal bounding rectangle.

GetFieldsCount returns the number of fields in the status bar. Use SetFieldsCount to set the number of fields.

GetStatusText gets the status text for a field, and SetStatusText sets the text for a field.

PushStatusText saves the current field text in a stack and sets the field text to the string passed as an argument. PopStatusText sets the field text to the top of the stack and pops the stack of saved strings.

SetMinHeight sets the minimal possible height for the status bar.

SetStatusWidths takes the number of fields and an array of integers that represent each field’s width, or a negative number to specify a proportion of the status bar to fill. For example, to create one field of fixed width 100 in the right part of the status bar and two more fields that get 66% and 33% of the remaining space respectively, you should specify an array containing -2, -1, and 100. The negative numbers are used to distinguish absolute pixel values from proportions.

SetStatusStyles takes the number of fields and an array of integer styles that determine the appearance of the fields. Use wxSB_NORMAL for a sunken field with a 3D border, wxSB_FLAT for a flat field with no border, and wxSB_RAISED for a field with a raised 3D border.

Summary

This chapter has given you enough information about the capabilities of essential window and control classes to know how to start building useful applications. For more details on these and other window classes, please refer to the reference manual. For further window classes, and how to create your own controls, see Chapter 12. You’ll also find it useful to look at the samples in your wxWidgets distribution, such as samples/widgets, samples/toolbar, samples/text, and samples/listbox.

Next, we’ll look at how how your application can draw on a variety of surfaces, including windows, bitmaps, and the printed page.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.194