Click here to Skip to main content
Click here to Skip to main content
Go to top

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

, 15 Dec 2005
Rate this:
Please Sign up or sign in to vote.
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:

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 --

#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 --

#ifndef MYTOOLBARCALLBACK
#define MYTOOLBARCALLBACK


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


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


#endif // MYTOOLBARCALLBACK

-- mytoolbarcallback.cpp --

#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:

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

Share

About the Author

Gabriel Bizzotto
Software Developer (Senior)
Brazil Brazil
No Biography provided

Comments and Discussions

 
Generalcompiling PinmembersantanaJ4-Sep-07 13:19 
GeneralRe: compiling PinmemberGabriel Bizzotto4-Sep-07 15:52 
GeneralRe: compiling PinmembersantanaJ5-Sep-07 17:56 
GeneralRe: compiling PinmemberGabriel Bizzotto13-Sep-07 15:06 
GeneralCall back for ListView Item Pinmembertomekskiba12311-Dec-05 7:48 
GeneralRe: Call back for ListView Item PinmemberGabriel Bizzotto12-Dec-05 11:45 
GeneralRe: Call back for ListView Item Pinmembertomekskiba12313-Dec-05 17:57 
GeneralUpdate to VC.NET 2005 PinmemberAmos Ortal6-Nov-05 11:10 
GeneralRe: Update to VC.NET 2005 Pinmemberukuk7-Nov-05 15:01 
Questionis there any extencion? Pinmemberevgeshag17-Aug-04 4:10 
AnswerRe: is there any extencion? Pinmemberukuk17-Aug-04 4:40 
GeneralPlotting a graph Pinmemberblobblob23-Mar-04 22:49 
GeneralRe: Plotting a graph Pinmemberukuk24-Mar-04 13:43 
GeneralRe: Plotting a graph PinsussAnonymous24-Mar-04 22:19 
Generalcomplied error in vc5.0 ,os:win2000 pro Pinmemberelliot2148-Feb-04 18:57 
GeneralRe: complied error in vc5.0 ,os:win2000 pro Pinmemberukuk10-Mar-04 6:14 
Questioncan I do this on a web form PinmemberogiDogi7-May-03 4:46 
AnswerRe: can I do this on a web form Pinmemberukuk7-May-03 10:47 
GeneralMaaaaaan, this is great, PinmemberVertex20-Mar-03 8:35 
GeneralExport display Pinmemberukuk21-Mar-03 2:06 
GeneralExport display via network Pinmemberukuk27-Apr-02 8:28 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140922.1 | Last Updated 15 Dec 2005
Article Copyright 2002 by Gabriel Bizzotto
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid