First Next Previous Last Glossary About

Programming with wxWindows - first steps


Introduction

We now look at another and much more friendly way of building windows programs using a set of class libraries called wxWindows. Strictly speaking wxWindows is much more than libraries, it is an application framework, which means it provides an architecture for using the classes in developing complete applications. The benefits of using wxWindows don't stop there, it is also a cross-platform library. In the words of the wxWindows authors:

What is wxWindows?
wxWindows gives you a single, easy-to-use API for writing GUI applications on multiple platforms. Link with the appropriate library for your platform (Windows/Unix/Mac) and compiler (almost any popular C++ compiler), and your application will adopt the look and feel appropriate to that platform. On top of great GUI functionality, wxWindows gives you: online help, network programming, streams, clipboard and drag and drop, multithreading, image loading and saving in a variety of popular formats, database support, HTML viewing and printing, and much much more.

wxWindows is a very high-quality piece of work, indeed, some people might use the term "commercial quality" in describing wxWindows meaning that it is good enough to pay for. That is certainly true but if there is one criticism that has been made of wxWindows, it is that, for a beginner, it can be difficult to come to grips with: the initial learning process is a little complex. The optimistic reply to that criticism is that once the programmer has a grasp of the wxWindows architecture, ie it's classes, functions and techniques, writing useful applications is a very rewarding and relatively straightforward process. It can be financially rewarding too, wxWindows is such a rich framework that almost any application domain can be tackled.

You have probably already guessed, whilst reading this, that I am a very keen supporter of wxWindows. That's true and I'd like to communicate my enthusiasm for wxWindows to you through these web pages.

My plan is to explain the architecture of wxWindows and introduce the classes in wxWindows through a series of example programs starting with the very basics. By the time you have finished you should have a good grasp wxWindows.

Before starting, here are some notes of caution:

These pages can be a great help to you if you are a beginner in programming in C++ but you want to get quickly into stride developing real-world GUI programs using wxWindows. Come along for the ride!


Return to top of page


The wxWindows architecture and a first program

WxWindows basic architecture

This is the starting point and initially I have kept things quite simple. The first acquaintance with the wxWindows framework is kept to the simplest view. As we develop further we look in more detail at the framework.

A wxWindows GUI program consists of:

In the most simple of programs we might have just an empty frame and this is the first basic example we look at. It's reasonable to wonder what earthly use that is. It is instructive if nothing else and that's why we look at it first. You will see that it shows all the usual behaviours of a windowed application. It has a system menu, it can be moved around, it can be resized and it can be dismissed.


wxWindows most basic application - the empty frame

I know it doesn't look much but it's ours! It also shows us that the program takes on the appearance of the native GUI. In this case it is Windows 98 but remember that wxWindows is a cross-platform framework and could be used to develop applications for other platforms like Linux, OS2, Mac etc.

The source code for the first example is shown below.



#ifndef BASIC_H
#define BASIC_H

class BasicApplication : public wxApp
{
  public:
	virtual bool OnInit();
};

class BasicFrame : public wxFrame
{
  public:
	BasicFrame( const wxChar *title, 
                int xpos, int ypos, 
                int width, int height);
	~BasicFrame();

};
#endif

This is the header file. In this basic application we declare two classes:

  • BasicApplication which inherits from wxApp and
  • BasicFrame which inherits from wxFrame

We declare a constructor and destructor for BasicFrame but the only thing we do for BasicApplication is to override the OnInit() method. Note that since we are overriding we declare the method to be virtual.

#include <wx/wx.h>
#include "basic.h"

IMPLEMENT_APP(BasicApplication)

bool BasicApplication::OnInit()
{
  BasicFrame
   *frame = new BasicFrame("Basic", 50, 50, 450, 300);

  frame->Show(TRUE);
  SetTopWindow(frame);
  return TRUE;	
}

BasicFrame::BasicFrame
             (const wxChar *title,
                    int xpos, int ypos,
                    int width, int height)
             : wxFrame
                ( (wxFrame *) NULL,
                   -1,
                   title,
                   wxPoint(xpos, ypos),
                   wxSize(width, height)
                )
{

}

BasicFrame::~BasicFrame()
{

}

This is the implementation, the definition of the classes declared in basic.h.

The first thing to notice is the macro

IMPLEMENT_APP(BasicApplication)

which, from our point of view, constructs the BasicApplication object and provides the main entry point for our application. It replaces virtually all of the work we did in the previous lesson in the int WINAPI WinMain( ... ) function.

The OnInit() method creates an instance of BasicFrame with some default x and y, width and height values and a title. It then calls the Show() method to show the frame. If you look at the wxFrame class you won't find a Show() method, wxFrame inherits from wxWindow and Show() is a wxWindow member function. As a beginner you might need to keep this is mind - since many of the classes are derived from other classes don't overlook the methods that are available in parent classes.

OnInit() also calls SetTopWindow() which is a member of wxApp.

The constructor and destructor don't add any new behaviours to our BasicFrame class.

#include "wx/msw/wx.rc"
The last relevant file is the resource file. In this simple example we don't add any of our own resources but you should always use a resource file that contains at least the line:

#include "wx/msw/wx.rc"

In later examples we add our own resources.


All that remains is for you to build and run the program.



Building wxWindows programs with MingW

Location of wxWindows library and include files

The wxWindows distribution contains many samples and for all of the samples there are make files for all the different platforms that wxWindows can use. Although this is a sensible way to generate programs since the user need not be concerned with specifying all the detail which determines what kind of target program will be generated, I must admit I found it a bit puzzling. There was also the disadvantage, as I perceived it anyway, that the build process had to specify where the include files and libraries where kept. I found that keeping the wxWindows includes in the standard include location and the wxWindows library in the standard library location to be more helpful. After building and installing the library I moved it, and the wx include directories, to the standard locations. On my Windows system this is in the MingW tree, on my Linux system this was either in the /usr or /usr/local tree (usr/lib, /usr/include or /usr/local/lib, /usr/local/include).

The primary benefit of relocating the library and include files is that it removes one level of obfuscation which might confuse the beginner. That done I can now use this makefile to build the examples:

PROGRAM = basic
OBJECTS = ${PROGRAM}.o ${PROGRAM}_resources.o
RC = windres.exe
CC = g++

INCLUDES = 

CCSW1 = --pipe -fvtable-thunks -c -D_X86_=1 -DWIN32 -D_WIN32 -DWINVER=0x0400 -D__WIN95__ \
	-D__GNUWIN32__ -D__WIN32__ -DSTRICT  -D__WXMSW__ -D__WINDOWS__\
	-Wall -fno-pcc-struct-return -O2 -fno-rtti -fno-exceptions   

CCSW2 = --pipe -fvtable-thunks -Wl,--subsystem,windows -mwindows 

LIBS  = -lwx -lxpm -lcomctl32 -ladvapi32 -lwsock32 -lole32 -loleaut32 -luuid 

RESSW = --include-dir c:/gcc-2.95.2-1/i386-mingw32msvc/include \
        --define __WIN32__ --define __WIN95__ --define __GNUWIN32__

.SUFFIXES: .o .cpp

all:    ${OBJECTS}
	$(CC) -o $(PROGRAM) ${OBJECTS} ${CCSW2} ${LIBS} 

.cpp.o: 
	$(CC) ${CCSW1} ${INCLUDES} -c -o $@ $<

${PROGRAM}_resources.o:
	$(RC) ${RESSW} ${PROGRAM}.rc $@

.PHONY : clean

clean:
	echo cleaning up
	rm $(OBJECTS)
	rm *.$$$$$$
	rm ${PROGRAM}.exe


To build the program:

  1. Create the source files in a single directory
    • basic.h
    • basic.cpp
    • basic_resources.rc
    • Makefile
  2. Run make in the directory where the files are stored
  3. Run the program

You can download the files (wxbasic0.zip) if you wish.



The wxWindows classes we used

We only used two classes:

from which we derived our own classes BasicApplication and BasicFrame. I am going to enlarge the detail of the two classes but you can also read the more complete description in the wxWindows documentation.

wxApp

The wxApp class contains around 30+ accessible members but at this stage we don't need to look at wxApp in any detail. Later when we do some work with the wxWindows event system we can pursue wxApp.

wxFrame

Since the work the wxFrame class does is rather more "visible" we might spend a short time looking at some of its properties.

wxFrame 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 = "frame"
)

Our BasicFrame constructor provided for only four obvious parameters: a title, x and y position, and, width and height.

The wxFrame constructor has other parameters: a wxWindow pointer, a style, a name and a wxWindowID, the latter is an integer and if it is -1 the a default value is used. It might sometimes be useful to supply an ID of your own. The pointer points to a parent window, if there is one. In our case the pointer was NULL, there was no parent window. The name parameter can be supplied by the programmer and, like the ID parameter, may be useful if a frame is to be referred to.

The frame style can be a variety of styles:

Window styles

A frame style is the OR of a one or more styles. In the absence of a style definition (as in our BasicFrame) the default applies, ie BasicFrame will have a minimize box, a maximize box, a system menu, a caption and will be resizable.

Something to do ...
BasicFrame::BasicFrame
             (const wxChar *title,
                    int xpos, int ypos,
                    int width, int height)
             : wxFrame
                ( (wxFrame *) NULL,
                   -1,
                   title,
                   wxPoint(xpos, ypos),
                   wxSize(width, height),
                   wxSIMPLE_BORDER
                )
...

So that you can see the effect of the different styles modify the BasicFrame constructor so that a style is passed as an argument to the wxFrame constructor as shown here.



Amongst the two-dozen or so members of wxFrame are the methods:

You will use most of these during the coming sessions but for now here is an exercise with the SetTitle and GetTitle member functions.

frame Titles and frame Names
BasicFrame::BasicFrame
             (const wxChar *title, 
              int xpos, int ypos, 
              int width, int height)
             : wxFrame( (wxFrame *) NULL,
                         -1,
                         title,
                         wxPoint(xpos, ypos),
                         wxSize(width, height),
                         wxDEFAULT_FRAME_STYLE,
                         "Fred"
                      )
{

}

The constructor has been modified so that it passes a name to the wxFrame constructor. Now add this line:

  frame->SetTitle(frame->GetTitle() + " " + frame->GetName());
to the BasicApplication::OnInit() function before the frame->Show(true) line.

Build and run the program and you will see the effect. Where does the GetName() method come from?




Summary

In this first session you have covered a fair piece of ground. You have seen the basic wxWindows framework and might be getting some idea of the architecture. Don't forget to lookup references to the classes in the wxWindows documentation. You may find it confusing at first but the exercise pays off well. I suggest also that when the opportunity arises (which is quite often) you should browse through the source code for wxWindows. You will find lots of useful comments there and also start to get a grasp of what underlies this excellent package.

The complete tutorial (to date up to icpp_wx7) is available for download.


Return to top of page


First Next Previous Last Glossary About


Copyright © 1999 - 2001 David Beech