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
that wxWidgets uses. This
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 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
(such as a frame with menu bar, toolbar, and status bar), or no child
(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
class or derived class, but this is not always the case: for example, the drop-down list in a native
is not usually
with a separate
Client and Non-Client Areas
When we refer to the
, we normally include the outer dimensions, including decorations such as the border and title bar. When we refer to the size of the
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.
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
to own their own scrollbars. More information on scrolling can be found later in this chapter when we discuss
Caret and Cursor
A window can have a
(for displaying the current text position) and a
(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.
Windows are broadly divided into top-level windows (
) and other windows. Only top-level windows may be created with a
parent, and only top-level windows have delayed destruction (they are not deleted until idle time, when all other events have been
). Except for pop-up windows, top-level windows can have decorations such as title bars and close
and can normally be dragged around the screen and resized, if the application allows it.
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
that is used to paint on the window. For more on device contexts, see Chapter 5, "Drawing and Printing."
When a window needs to be
, it receives two events,
to paint the background, and
to paint the foreground. Ready-to-use classes such as
, but to create your own special window class, you will need to handle these events. You can optimize painting by getting the
(the part that needs refreshing) from the window.
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.
On Mac OS X, a window has the concept of
, whereby it can be shown in a selection of sizes:
. Changing to a smaller variant is useful when you have a lot of information to
and limited space, but it should be used in
. Some applications use the small variant throughout.
When a window is resized, either by the application or by the
, it receives a
event. If the window has children, they will need to be positioned and
appropriately, and the recommended way is to use
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
as an individual size or position value). To this end, each control implements
which returns a reasonable default size based on the control content, current font, and other factors.
Any window can receive input from the mouse at any time, unless another window has temporarily
the mouse or the window is
. Only the window with the current
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
event is sent to a window that is receiving the 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
specified) recipients of
), 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,
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
, 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.
has typical constructor signatures:
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
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-
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
. 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
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
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
, which has the same signature as the full constructor. For example, to create a button in two steps:
wxButton* button = new wxButton;
Only when you call
is the underlying window created, and a
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
if those properties are used within the
call. For example, you may want to set the
extra style (which must be set with
). In the case of a dialog, this style is used from within its
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
, or any non-top-level derived window class, it is always in a visible stateso if the parent is visible at the time of creation, the window will also be visible. You can then use
to hide it if required. This is different from
, which are initially created in a hidden state to enable the application to lay out the controls without initial flicker, before showing with
or (for modal dialogs)
Windows are deleted by calling
(for top-level windows) or
(for child windows), and the
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.
A window has a
. Window styles are a
way to specify alternative behavior and
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
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.