Click here to Skip to main content
15,886,554 members
Articles / Desktop Programming / MFC
Article

A C++ Win32 GUI library for Java-AWT-like source code

Rate me:
Please Sign up or sign in to vote.
4.37/5 (17 votes)
15 Dec 20054 min read 129.3K   1.3K   31   21
This library provides a simple set of classes for creating GUIs. It uses only the Win32 API with some common controls. The development is at the beginning and many changes are to be done.

The source files contain two workspaces:

  • jlWindows itself, generating a .lib.
  • Testor, having jlWindows as a dependency.

Please visit jlWindows hosted by MtpForge here.

Introduction

The global aim of the library is to provide a really easy to use GUI API. Creating a small GUI for a simple piece of software should be very fast and clean, only few code lines, with the behavior of components isolated in classes.

In future, this library could allow the creation of remote GUIs, i.e., new jlWindow("192.168.xx.xx"); or something like that. Another idea is to make jlWindows GUIs dynamically modifiable, for example, allowing to cut/paste buttons or textfields over tabs, and making all the components resizable and even renamable. I also would like to port it to X.

For now, I'm trying to override the native Win32 functions and data structures, which are, in my mind, pretty messy. So jlWindows tends to give a consistent view of the existing API. Then I want to provide more functionalities, like layout managers that auto-organize components inside a window.

The library was created in April 2002, however it is very far from its final version.

Today, it allows to:

  • create some basic components: windows, buttons, textfields, listviews...
  • set some properties of the windows like parent, position, size, window title...
  • set some specific properties like listviews' icons set, buttons' caption or icon...
  • set a callback handler by the component with some default behavior.

How you can use it

There are two base classes:

  • jlComponent
  • jlCallbackHandler

Components are visible stuff, like windows with title bar, buttons and textfields. Each kind of component has a class that inherits -directly or not- jlComponent. You can create a component passing no argument at all to the constructor, but you can also pass the parent as a parameter and the styles, which are Win32 styles. After a component's creation, you cannot change its styles anymore. But you can change any other property, by calling the right method. You can even change the parent of a window, thus moving a component from one place to another.

You can give a component a callback handler, which will receive the Win32 messages and do stuff with it. Each type of component has an associated type of callback handler, because, for instance, a button does not do the same things when it's clicked, as a listview. Each interactive component of your graphical user interface will have a callback handler. You can use the default behavior of jlWindows' callback handlers, like jlWindowCallback that calls PostQuitMessage() when it receives the message WM_DESTROY. But most probably you will have to override the callback handlers to give your application the behavior you want.

The job of a callback handler is to call a particular method (on itself) depending on the message it received. It has one method which is called each time the associated component(s) receives a message. That method should return true if the message was not handled, or more generally, if you want the default callback function of the component to be called.

Here is the callback handler's dispatch function of jlTextField:

C++
bool jlTextFieldCallback::componentCallback(HWND WindowHandle, 
                   UINT Message, WPARAM WParam, LPARAM LParam)
{
    switch (Message)
    {
        case WM_DROPFILES:
            return filesDropped(WParam);
            break;
    }

    return true;
}

When you override a callback handler, your job is to fill those methods called by the dispatch function of the callback handler, like, in the example above, the method filesDropped().

Example

The following code creates the sample app (whose screenshot and source code is above):

-- main.cpp --

C++
#include <windows.h>
#include <stdio.h>

#include "jlWindows.h"
#include "resource.h"
#include "mytoolbarcallback.h"

int WINAPI WinMain(HINSTANCE hInstance, 
     HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    //     jlComponent  ( jlComponent * parentcomponent = NULL ,
    //                   DWORD style = 0 , DWORD exstyle = 0 );
    jlWindow * win = new jlWindow(NULL, WS_OVERLAPPEDWINDOW);
    jlToolbar * tb = new jlToolbar();

    win->setTitle("jlWindows Testor");
    win->setSize(400,300);
    win->show();
  // sets a default callback handler for the window
  // this callback handler calls PostQuitMessage(0) on WM_DESTROY
    win->setCallbackHandler(new jlWindowCallback());

    tb->setButtonSize(16, 16);
    tb->setImageList(IDB_BITMAP1);
    tb->addButtons(2, 0); // addButtons (int count, int start_image)
    tb->addButtons(2, 0);
    // I created a simple class MyToolbarCallback to handle
    // the messages the tb receives. It just pops a messagebox up
    // with the zero-based number of the button of the toolbar
    tb->setCallbackHandler(new MyToolbarCallback());

    // just an example of listview that does nothing
    jlListView * lv = new jlListView();
    lv->setPosition(30,30);
    lv->setSize(200,200);
    lv->addColumn("second");
    lv->addColumn("third");
    lv->setImageList(IDB_BITMAP1);
    lv->addItem(0, "blah1"); // addItem (U32 line_index, char * text)
    lv->addItem(1, "blah2");
    lv->addItem(2, "blah3");
    lv->setMasterColumn("first");

    win->addToolbar(tb);
    win->addComponent(lv);

  // receives and dispatches messages to jlWindows Components
  // this function returns when the message WM_QUIT
    // (sent by PostQuitMessage()) is received
    jlComponent::loop();

    return 0;
}

-- mytoolbarcallback.h --

C++
#ifndef MYTOOLBARCALLBACK
#define MYTOOLBARCALLBACK


#include <windows.h>
#include "jlWindows.h"


class MyToolbarCallback : public jlToolbarCallback
{
    virtual bool buttonClicked(int button_id);
};


#endif // MYTOOLBARCALLBACK

-- mytoolbarcallback.cpp --

C++
#include <windows.h>
#include <stdio.h>
#include "mytoolbarcallback.h"


bool MyToolbarCallback::buttonClicked(int button_id)
{
    char msg[10];
    sprintf(msg, "%d", button_id);

    MessageBox(NULL, msg, "toolbar", MB_OK);

    return false;
}

How it works

Each jlComponent has the HANDLE of the Win32 item (usually called window, whatever it is, button, menu or listview) it is associated with. When creating a jlComponent, a call to CreateWindowEx() is performed, with the styles and parent you gave in the parameters or with the default ones. Buttons, listviews and stuff like that use predefined window classes, with predefined callback functions that make them behave the standard way. But just after their creation, the windows are given a new callback function, jlWindows' one, which is common to every jlComponent. The windows are also given particular "user data". Each window receives as user data, a pointer to the jlComponent associated with it. Those properties are set by calling SetWindowLong(). Then, in jlWindows' global callback function, that user data is retrieved from the window that received a message. That way, jlWindows knows what jlComponent a message is destined to. It just has to call a method on it, and that jlComponent will forward the message to its callback handler, if any.

Note that if jlWindows' global callback function detects that a jlComponent did not handle a message, it calls the standard callback function of the window associated with it, which has been saved when setting jlWindows' callback function. Most of the times, one should let jlWindows call the standard callback function of a component, because it generally deals with its display. For example, overriding the behavior of a button when it's clicked without letting jlWindows call its standard callback function, will prevent it from being displayed pushed.

After creating the components, setting their properties, their callback handlers and showing them, you have to call jlComponent::loop();. That static method will receive and dispatch the messages that the graphic interface you designed receives. The code of that method is typical and always the same in every C++/Win32 application. That loop ends only when it receives the WM_QUIT message:

C++
void jlComponent::loop()
{
    MSG Message;   
    int Status;

    while ((Status = GetMessage(&Message, NULL, 0, 0)))
    {                        
        if (Status == -1)
             break;

        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
}

License

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


Written By
Software Developer (Senior)
Brazil Brazil
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalcompiling Pin
santanaJ4-Sep-07 13:19
santanaJ4-Sep-07 13:19 
GeneralRe: compiling Pin
Gabriel Bizzotto4-Sep-07 15:52
Gabriel Bizzotto4-Sep-07 15:52 
GeneralRe: compiling Pin
santanaJ5-Sep-07 17:56
santanaJ5-Sep-07 17:56 
GeneralRe: compiling Pin
Gabriel Bizzotto13-Sep-07 15:06
Gabriel Bizzotto13-Sep-07 15:06 
GeneralCall back for ListView Item Pin
tomekskiba12311-Dec-05 7:48
tomekskiba12311-Dec-05 7:48 
GeneralRe: Call back for ListView Item Pin
Gabriel Bizzotto12-Dec-05 11:45
Gabriel Bizzotto12-Dec-05 11:45 
GeneralRe: Call back for ListView Item Pin
tomekskiba12313-Dec-05 17:57
tomekskiba12313-Dec-05 17:57 
GeneralUpdate to VC.NET 2005 Pin
Amos Ortal6-Nov-05 11:10
Amos Ortal6-Nov-05 11:10 
GeneralRe: Update to VC.NET 2005 Pin
Gabriel Bizzotto7-Nov-05 15:01
Gabriel Bizzotto7-Nov-05 15:01 
Questionis there any extencion? Pin
evgeshag17-Aug-04 4:10
evgeshag17-Aug-04 4:10 
AnswerRe: is there any extencion? Pin
Gabriel Bizzotto17-Aug-04 4:40
Gabriel Bizzotto17-Aug-04 4:40 
Please check the project page on MtpForge at
http://mtpforge.melting-pot.org/projects/jlwindows/

This is the actual project page with latest versions and news and all...
jlWindows is already a bit different from the old version available here. Debugged, more stuff, easier to use... I guess (:

MtpForge is an instance of GForge which is a fork of SourceForge.

----
Ukuk
GeneralPlotting a graph Pin
blobblob23-Mar-04 22:49
blobblob23-Mar-04 22:49 
GeneralRe: Plotting a graph Pin
Gabriel Bizzotto24-Mar-04 13:43
Gabriel Bizzotto24-Mar-04 13:43 
GeneralRe: Plotting a graph Pin
Anonymous24-Mar-04 22:19
Anonymous24-Mar-04 22:19 
Generalcomplied error in vc5.0 ,os:win2000 pro Pin
elliot2148-Feb-04 18:57
elliot2148-Feb-04 18:57 
GeneralRe: complied error in vc5.0 ,os:win2000 pro Pin
Gabriel Bizzotto10-Mar-04 6:14
Gabriel Bizzotto10-Mar-04 6:14 
Questioncan I do this on a web form Pin
ogiDogi7-May-03 4:46
ogiDogi7-May-03 4:46 
AnswerRe: can I do this on a web form Pin
Gabriel Bizzotto7-May-03 10:47
Gabriel Bizzotto7-May-03 10:47 
GeneralMaaaaaan, this is great, Pin
Vertex20-Mar-03 8:35
Vertex20-Mar-03 8:35 
GeneralExport display Pin
Gabriel Bizzotto21-Mar-03 2:06
Gabriel Bizzotto21-Mar-03 2:06 
GeneralExport display via network Pin
Gabriel Bizzotto27-Apr-02 8:28
Gabriel Bizzotto27-Apr-02 8:28 

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.