wxWidgets: Creating a Custom Widget

| Version: 3.0.5

Creating a Custom Widget

Typically combining the existing Controls controls in wxDialogs and wxFrames is sufficient to fullfill any GUI design.

Using the wxWidgets standard controls makes your GUI looks native on all ports and is obviously easier and faster.

However there are situations where you need to show some particular kind of data which is not suited to any existing control. In these cases rather than hacking an existing control for something it has not been conceived for, it's better to write a new widget.

# Writing a Custom Widget

There are at least two very different ways to implement a new widget.

The first is to build it upon wxWidgets existing classes, thus deriving it from wxControl or wxWindow. In this way you'll get a generic widget. This method has the advantage that writing a single implementation works on all ports; the disadvantage is that it the widget will look the same on all platforms, and thus it may not integrate well with the native look and feel.

The second method is to build it directly upon the native toolkits of the platforms you want to support (e.g. GTK+, Carbon and GDI). In this way you'll get a native widget. This method in fact has the advantage of a native look and feel but requires different implementations and thus more work.

In both cases you'll want to better explore some hot topics like:

- Window Sizing Overview
- Custom Event Summary to implement your custom widget's events.

You will probably need also to gain some familiarity with the wxWidgets sources, since you'll need to interface with some undocumented wxWidgets internal mechanisms.

## Writing a Generic Widget

Generic widgets are typically derived from wxControl or wxWindow. They are easy to write. The typical "template" is as follows:

enum MySpecialWidgetStyles
{
SWS_LOOK_CRAZY = 1,
SWS_LOOK_SERIOUS = 2,
SWS_SHOW_BUTTON = 4,
SWS_DEFAULT_STYLE = (SWS_SHOW_BUTTON|SWS_LOOK_SERIOUS)
};
class MySpecialWidget : public wxControl
{
public:
MySpecialWidget() { Init(); }
MySpecialWidget(wxWindow *parent,
wxWindowID winid,
const wxString& label,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = SWS_DEFAULT_STYLE,
const wxValidator& val = wxDefaultValidator,
const wxString& name = "MySpecialWidget")
{
Init();
Create(parent, winid, label, pos, size, style, val, name);
}
bool Create(wxWindow *parent,
wxWindowID winid,
const wxString& label,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = SWS_DEFAULT_STYLE,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxCollapsiblePaneNameStr);
// accessors...
protected:
void Init() {
// init widget's internals...
}
virtual wxSize DoGetBestSize() const {
// we need to calculate and return the best size of the widget...
}
void OnPaint(wxPaintEvent&) {
// draw the widget on a wxDC...
}
private:
wxDECLARE_DYNAMIC_CLASS(MySpecialWidget);
wxDECLARE_EVENT_TABLE();
};
wxControl
This is the base class for a control or "widget".
Definition: control.h:86
wxControl::Create
bool Create(wxWindow *parent, wxWindowID id, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=0, const wxValidator &validator=wxDefaultValidator, const wxString &name=wxControlNameStr)
wxPaintEvent
A paint event is sent when a window's contents needs to be repainted.
Definition: event.h:2225
wxPoint
A wxPoint is a useful data structure for graphics operations.
Definition: gdicmn.h:591
wxSize
A wxSize is a useful data structure for graphics operations.
Definition: gdicmn.h:872
wxString
String class for passing textual data to or receiving it from wxWidgets.
Definition: string.h:314
wxValidator
wxValidator is the base class for a family of validator classes that mediate between a class of contr...
Definition: validate.h:38
wxWindow
wxWindow is the base class for all windows and represents any visible object on screen.
Definition: window.h:287
wxWindow::DoGetBestSize
virtual wxSize DoGetBestSize() const
Implementation of GetBestSize() that can be overridden.
wxDECLARE_EVENT_TABLE
#define wxDECLARE_EVENT_TABLE()
Use this macro inside a class declaration to declare a static event table for that class.
Definition: event.h:4578
wxDefaultSize
const wxSize wxDefaultSize
Global instance of a wxSize object initialized to (-1,-1).
Definition: gdicmn.h:1028
wxDefaultPosition
const wxPoint wxDefaultPosition
Global instance of a wxPoint initialized with values (-1,-1).
Definition: gdicmn.h:714
wxDECLARE_DYNAMIC_CLASS
#define wxDECLARE_DYNAMIC_CLASS(className)
Used inside a class declaration to make the class known to wxWidgets RTTI system and also declare tha...
Definition: object.h:705
wxDefaultValidator
const wxValidator wxDefaultValidator
An empty, "null" wxValidator instance.
Definition: validate.h:133
wxWindowID
int wxWindowID
The type of unique identifiers (ID) used for wxWindow-derived classes.
Definition: windowid.h:11

## Writing a Native Widget

Writing a native widget is typically more difficult as it requires you to know the APIs of the platforms you want to support. See Native Toolkit Documentation for links to the documentation manuals of the various toolkits.

The organization used by wxWidgets consists in:

- declaring the common interface of the control in a generic header, using the 'Base' postfix; e.g. MySpecialWidgetBase. See for example the wxWidgets' `"wx/button.h"` file.
- declaring the real widget class inheriting from the Base version in platform-specific headers; see for example the wxWidgets' `"wx/gtk/button.h"` file.
- separating the different implementations in different source files, putting all common stuff in a separate source. See for example the wxWidgets' `"src/common/btncmn.cpp"`, `"src/gtk/button.cpp"` and `"src/msw/button.cpp"` files.