WxSmith tutorial: Creating items with custom paint and mouse handling

From Code::Blocks
Revision as of 15:22, 6 December 2010 by Greenbreen (talk | contribs) (Minor edits for clarity)

Warning: unfinished

Welcome back :) We've already learned nice techniques of working with wxSmith in previous tutorials and now it's time for something even better. Usually when writing some more advanced application, it turns out that none of the items provided by wxWidgets fits our purposes, especially when we need to present some data in graphical form. Hopefully as with almost all GUI toolkits, wxWidgets is also prepared for this and gives us the possibility to create an item with custom drawing and mouse handling - this allows us to create any item we like.

Creating item with custom paint procedure

Before we start creating our customized item, some background knowledge is needed. First thing you should know is how wxWidgets draws items.

Most of items have custom paint procedures provided by operating system or some other toolkit available in system (like gtk+). In case of such items, when OS posts request to repaint item, either such message is forwarded by wxWidgets back into system or even the whole procedure is done without any wxWidgets' intervention. Unfortunately this means that we can not replace paint procedure in case of all items and even if it would work on some platforms, it won't on others. From items available in wxSmith, only wxPanel is guaranteed to work with custom paint procedure.

Now if we overwrite painting on wxPanel, wxWidgets will post two events on each paint request:

* erase background event (EVT_ERASE_BACKGROUND)
* paint event (EVT_PAINT)

First one is used to prepare area occupied by our item before adding content and the second one is used to do actual drawing. We don't have to override both events so we can only draw custom background or custom content leaving background as default one.


Second thing you should know before writing custom paint method is that wxWidgets uses wxDC objects to draw. In case of erase background event, this object is provided within event, in case of paint event, we must create such object manually. To get more informations about wxDC and drawing functions, take look at this page in wxWidgets documentation.

Creating simple resource and overriding paint method

Now let's create some simple window. For our purposes we need some wxPanel inside the window which we will work on:

Wxs tut07 001.png

Now let's go to event's tab in properties browser. You may see that wxPanel can process much more events than other items. That's because it can be use as base for custom items which may have custom handler for any standard event. Ok, let's find EVT_PAINT method (sohuld be at the top) and add new empty event.

The first thing we should do inside the handler is to create wxDC object we will use. If you look at wxWidgets documentation you may read that not doing so causes wxWidgets to go into infinite loop because paint method will be recalled over and over again.

There are few types of wxDC objects we could use here. The most commonly used is wxPaintDC:

void Tutorial7Dialog::OnPanel1Paint(wxPaintEvent& event)
{
    wxPaintDC dc( Panel1 );
}

You can see that we passed panel's pointer as argument - wxPaintDC require pointer to item we will draw on on it's constructor. Remember not to use this opinter.

Now let's add some drawing code - just some diagonal line to test whether drawing does work:

void Tutorial7Dialog::OnPanel1Paint(wxPaintEvent& event)
{
    wxPaintDC dc( Panel1 );
    dc.DrawLine( 0, 0, 100, 100 );
}

Now if we run our aplication, the window will look like this:

Wxs tut07 002.png