Click here to Skip to main content
13,046,499 members (71,671 online)
Click here to Skip to main content
Add your own
alternative version


27 bookmarked
Posted 12 Oct 2005

A Custom GUI System

, 31 May 2006
Rate this:
Please Sign up or sign in to vote.
If you demand the most possible control of your code, if you like to force Windows looking your way, and if you are lazy enough, this tutorial is exactly for you.


If you don't like tools that automatically create loads of useless code you mostly won't understand it because the authors didn't bother to document it. If you demand the most possible control of your code, if you like to force Windows looking your way, and if you are lazy enough, this tutorial is exactly for you.

Well, some months ago these were the reasons that made me think of an ultimate solution of a simple, expandable and easy-to-use GUI system. Actually I liked the ideas behind MFC like: separate class for each window type, handlers for messages instead of huge window procedures, but I wanted them in combination with the "low-level" nature of pure Win32 API.


When you look at the source code, you will notice that the basic framework consists of two classes. (Note: Both classes have more or less detailed documentation in the source files. They were extracted from a larger project, and for the purpose of this tutorial, they were stripped down to substantial elements needed to present the basic principles behind them.)

The first class is winbase, a class that represents a generic window (like CWnd in MFC). Its core functionality relies on the standard creation method create(), pre and post create initialization methods and message handlers. Message handlers are implemented as message specific, one handler for one type of message, except for the generic message handler on_message() that provides a way of extending the functionality of the system without recompiling the whole API. The generic handler has also the ability to catch unprocessed messages. All functions in this class are virtual.

The second class is winpool that is a placeholder for all application windows and also acts as an application manager. This class has only static methods as there is no need for multiple instances of this class per application.

Now comes 'the magic' - the common window procedure passed to CreateWindowEx() that gets called in create():

LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
   winbase* wb = 0;

   //special case: at the moment we don't have 
   //the hwnd associated with our window object
   if(msg == WM_CREATE)
      //find the window we are creating - this window has WDS_INITIAL flag set
      wb = winpool::get_created_window();

      //init windows`s hwnd and data members that need to be obtained 
      //through this hwnd (hdc,...) and set window`s display state to WDS_OPEN

      //bail with calling the user defined (or default) on_create() handler
      return wb->on_create(wp, lp);

   //standard case: we already have the hwnd assigned 
   //to our window object, window has WDS_OPEN flag set
   //get the window this message belongs to
   wb = winpool::get_window_from_hwnd(hwnd);

   //call message specific handlers
      return wb->on_lbuttonup(wp, lp);
      return wb->on_rbuttonup(wp, lp);
   case WM_CLOSE:
      return wb->on_close(wp, lp);
   case WM_DESTROY:
      return wb->on_destroy(wp, lp);
      return wb->on_ncdestroy(wp, lp);
   //call generic handlers
      //we have the pointer to the window
         return wb->on_message(msg, wp, lp);
      //for the sake of security when we for any reason
      // don't have the pointer to the window
         return DefWindowProc(hwnd, msg, wp, lp);

Using the system

Well, the system is created, it should do something useful. For the purpose of this tutorial we will make a simple window that will react on mouse clicks and key strokes. So we create a subclass of the generic window, called MyWindow. This window will center itself on the screen and it will also load and display the cross-hair cursor. Then we override the handlers so that when the user left-clicks the window, a message box pops up asking whether the user likes to close the window. When the user right-clicks the window a message box pops up showing the coordinates of the click, and when the user strokes a key a message box pops up showing the ASCII value of the key being stroked. Making the application run is then a piece of cake:

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
   //initialize application manager

   //register our window class
   winpool::register_class(hinst, "MyWindow");

   //window instance
   MyWindow wnd;

   //position and dimensions array (dims={x, y, w, h})
   //we don`t need to specify position since the window centers itself
   int dims[] = {0, 0, 640, 480};

   //initialize window data members needed for creating the window
   //(e.g hinstance, classname and display state to WDS_INITIAL)
   wnd.pre_create_window(hinst, "MyWindow");

   //create the window - we specify only the 
   //owner (NULL=desktop), caption and dimensions
   wnd.create(NULL, "Tutorial 1 - Use mouse buttons" 
                    " and keyboard keys", dims);

   //finally show the window on the screen

   //run message loop until WM_QUIT is encountered
   while(winpool::dispatch_message()){ /* run */}

   //clean up
   winpool::unregister_class(hinst, "MyWindow");

   return 1;

Last Words

As you can see we ended up with a running GUI system that is easy-to-use and can be further expanded. Now you should understand how the "wheels are turning" in the Win32 Pro package (you can find this package here - feel free to download it and experiment with it). See the next tutorial, where I try to explain how I implemented the support for dialogs, custom and subclassed controls.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

oto spal
Slovakia Slovakia
No Biography provided

You may also be interested in...


Comments and Discussions

NewsWin32 Pro 1.1 Pin
oto spal30-May-06 7:39
memberoto spal30-May-06 7:39 
NewsWin32 Lite 1.1 Pin
oto spal16-Mar-06 11:11
memberoto spal16-Mar-06 11:11 
GeneralThis is Advanced stuff. Pin
WREY13-Oct-05 11:08
memberWREY13-Oct-05 11:08 
GeneralRe: This is Advanced stuff. [modified] Pin
oto spal13-Oct-05 11:35
memberoto spal13-Oct-05 11:35 
GeneralRe: This is Advanced stuff. Pin
WREY13-Oct-05 13:14
memberWREY13-Oct-05 13:14 
GeneralRe: This is Advanced stuff. Pin
oto spal13-Oct-05 20:44
memberoto spal13-Oct-05 20:44 
GeneralAn even more crazy solution Pin
yarp12-Oct-05 18:59
memberyarp12-Oct-05 18:59 
GeneralRe: An even more crazy solution Pin
gri12-Oct-05 20:39
membergri12-Oct-05 20:39 
GeneralNot as cool, but maybe idea giving Pin
David O'Neil12-Oct-05 21:39
memberDavid O'Neil12-Oct-05 21:39 
GeneralRe: Not as cool, but maybe idea giving Pin
yarp13-Oct-05 5:49
memberyarp13-Oct-05 5:49 
GeneralAnd for a REALLY crazy solution Pin
Jim Crafton13-Oct-05 4:03
memberJim Crafton13-Oct-05 4:03 
GeneralRe: And for a REALLY crazy solution Pin
Kochise13-Oct-05 4:10
memberKochise13-Oct-05 4:10 
GeneralRe: And for a REALLY crazy solution Pin
Jim Crafton13-Oct-05 4:18
memberJim Crafton13-Oct-05 4:18 
GeneralRe: An even more crazy solution Pin
oto spal13-Oct-05 11:18
memberoto spal13-Oct-05 11:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170713.1 | Last Updated 31 May 2006
Article Copyright 2005 by oto spal
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid