Main Page | File List

Win32GUI Tutorial, for VC7.1

1.0

Windows Programming with win32gui and VC7.1, A Tutorial for C++ Beginners

By Kevin Duong

Overview

Traditionally, C++ programmers have to use third-party vendors software such as Visual C++, Qt, Borland C++, etc. to create GUI programs. They have to live with these software data types and libraries, so it is relatively difficult to fully integrrate the C++ Standard Library into the program.

The template library Win32 GUI (http://www.torjo.com/) is posed to change all of that. For one thing, it blends very well with the C++ Standard Library. For example, you could use the C++ Standard string class or the IO Stream facility to perform text input/output from and to the dialog boxes. Also, according to John Torjo, the Win32’s creator, we could also perform “true binding of your data to UI controls on your dialog.”

Another great bonus is that the result executable file is ALL is needed for distribution to the end users. (For a more convincing of Win32 GUI features, see the July/2004 article namely “Win32 GUI Generics: The Roots” – from the C/C++ User’s Journal – CUJ, or the nine goals that John mentions in his website.)

Being previously exposed to and struggled with GUI methods such as plain Windows programming, the MFC library, the C++.NET platform and its CLI awkward syntax, this time I want to familiarize myself again with Windows programming using Win32 GUI, combined with the RAD facility from the Visual C++.NET 7.1 IDE.

My assumption is that you are a C++ beginner, that you know just a little bit about the Visual C++ IDE, and that you are inspired by the simplicity yet beauty of Win32 GUI, and you want to learn how to quickly start to program with it. I felt that John’s articles from the CUJ are rather advanced, so by writing down my findings along the way, I hope this tutorial would be useful to other C++ beginners as well.

Advanced generic programming explanations are out of the scope of this tutorial, for I just want to delve into details how things works in practice and leave advanced stuffs for you to explore.

For a gentle treatment of STL and generic programming, I highly recommend “STL Tutorial and Reference Guide, Second Edition”, written by David Musser, Gilmer J. Derge, and Atul Saini.

For a readable C++ book, I urge you to obtain a copy of “C++, the Core Language”, written by Gregory Satir and Doug Brown.

Installing Win32GUI

First of all, you need to go to John Torjo’s website at http://www.torjo.com/to check out all of his latest articles, tools, and documentations.

Then you can go to his sourceforge website at: http://sf.net/projects/win32gui/to download the latest package. At the time of this writing, the development version v1.6.2 is available.

I also assume that you already installed Visual C++.NET vesion 7.1 (2003 Edition). Now, after unzipping the package, double click on the build_library.exe program (from the now created win32gui-lib directory), then click on the Build… option on the right hand side of the Visual C++ 7.1 group-box.

A DOS window appears to show you the progress of this library compiling step.

build_win32gui.gif

Once the compiling process completes, open VC++ IDE and select Tools->Options, then Select Projects tab-> VC++ Directories. In the “Show directories for” option, select Include files, then add path_to_your_unzipped_dir/win32gui-lib to the list.

include_dirs.gif

Next, in the “Show directories for” option, select Library files, then add path_to_your_unzipped_dir/win32gui-lib/win32gui/lib to the list.

lib_dirs.gif

Win32 GUI’s “Hello World!” program

For those for us who wouldn’t know where to start, John Torjo already created a seed project called sample start. I would recommend you to make a copy of the folder, then rename it to something like win32gui_seed_project, and create another folder to store your future projects.

dirs.gif

Next, copy the win32gui_seed_project to your project folder, then rename it to become Hello World. Make sure also to change the status of these files to become writable. Then, double click on the sample_start.sln file.

Next, expand your Solution Explorer window at the right hand side of the VC++ IDE, and start to examine the content of the files that John created for us. Now, to add the simplest control onto our program, switch to the resource tab and double click on the IDD_SAMPLE dialog item:

resource_editor.gif

open the Toolbox window by clicking on it,

toolbox.gif

then click on the Static Text entry

toolbox_detail.gif

and finally drag it into the dialog box. Go to the Properties window and rename the Caption field to Hello World!

static.gif

and here is the result:

result.gif

You'll notice also that I could change the title of the dialog by clicking on any point near the border of it, then retype the Caption’s content in the Properties window:

caption.gif

Now if you select Buid->Rebuild solution, VC++ would compile again the program with our new text. Here is the result after you choose Debug->Start:

hello_world.gif

A Closer Look at our “Hello World!” program

As simple as it appears, the last section reveals that we could utilize the already available VC++ Toolbox facility to speed up the GUI creation process.

Later on, I will visit the most useful controls one by one, using John’s excellent examples stored under the win32gui directory.

Now let us examine the content of each of the cpp and header files and try to understand how things work.

The Hello World! program has essentially five source code files, and a “rc” resource file that we modify not manually but through the Resource View. The five source code files are:

1. stdafx.h

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#ifndef SAMPLE_STDAFX_H
#define SAMPLE_STDAFX_H

#include <win32gui/window.hpp>
#include <win32gui/controls.hpp>
#include <win32gui/event_handler.hpp>
#include <win32gui/frame.hpp>

// Win32GUI Window base class 
using win32::gui::window_base;
using win32::gui::create_wnd;
// ... null window
using win32::gui::null_wnd;

// for extending windows/dialogs
using win32::gui::wnd_extend;

// Dialog class
using win32::gui::dialog;
using win32::gui::create_dlg;
using win32::gui::create_modal_dlg;

// for defining event handlers
using win32::gui::event_handler;

// Resizing Ability
using win32::gui::resizable_wnd;

// Frames
using win32::gui::view_frame;
using win32::gui::sdi_frame;
using win32::gui::mdi_frame;

// STL
#include <map>
#include <vector>
#include <string>
#include <algorithm>

#endif

2. stdafx.cpp

// stdafx.cpp : source file that includes just the standard includes
// sample_start.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

3. sample_dlg.h

// sample_dlg.h
#ifndef SAMPLE_DLG_H
#define SAMPLE_DLG_H

struct sample_dlg : wnd_extend<dialog,sample_dlg>, 
                    wnd_extend<resizable_wnd,sample_dlg> // usually the window needs to be made Resizable 
                    {
    sample_dlg();
    ~sample_dlg();
    static int dialog_id();
};

#endif

4. sample_dlg.cpp

#include "stdafx.h"
// sample_dlg.cpp
#include "resource.h"
#include "sample_dlg.h"

using namespace win32::gui;


struct sample_dlg_handler : event_handler<sample_dlg_handler, sample_dlg> {
};


sample_dlg::sample_dlg() {
}

sample_dlg::~sample_dlg() {
}

int sample_dlg::dialog_id() { return IDD_SAMPLE; }

5. main.cpp

// sample_start.cpp : Defines the entry point for the application.

#include "stdafx.h"
#include "sample_dlg.h"

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPTSTR, int) {
    create_modal_dlg<sample_dlg>(null_wnd)  .wait();
}

The first two files, stdafx.h and stdafx.cpp. contain the most useful include files such that we won’t have to re-declare them again in sample_dlg.cpp and main.cpp.

Notice also the most useful STL header files such as string, vector, map, and algorithm are all included. (I can’t wait to start using string inside our next examples!) You can read the meaning of these files from John’s comments.

The file sample_dlg.hpp is the class definition of the IDD_SAMPLE dialog box. From reading the documentation file (win32gui.html), we realize our sample_dlg class are derived from both the dialog and the resizable_wnd template classes.

The key to bind the class to the resource is in the dialog_id() function. In the file sample_dlg.cpp, we see the implementation of this function is to simply “return IDD_SAMPLE;”, where IDD_SAMPLE is the name of the dialog box. We also see the declaration of the event handling class sample_dlg_handler as a child class from event_handler class template:

struct sample_dlg_handler : event_handler<sample_dlg_handler, sample_dlg> {};

Finally, in the main.cpp file, we see the unique WinMain() function required as the entrance to run our program. Inside, a modal dialog is created and is waiting for the user to do something:

create_modal_dlg<sample_dlg>(null_wnd)  .wait();

As you can see, create a “Hello World! ” modal dialog with Win32 GUI is not required a lot of work, but the result executable file is all it needs for the program to run. Goodbye MFC and its depending DLLs!!!!

Notice that we don’t have to do any coding, yet the program exits if we press either OK, Cancel or the x button at the upper right hand side of the program.

Edit controls

To see how easy it is to add an edit control to a program, consider the user_and_passw1 program, found under win32gui directory.

First, select the IDD_login dialog from the Resource View, then select an edit control and a static text control from the Toolbox.

Rename the static text control content to become “Branch”,

login.gif

then add these bold text lines to main.cpp:

#include <win32gui/window.hpp>
#include <win32gui/wnd_extend/save_dlg.hpp>
#include "resource.h"

//    Shows how simple it is to create a save_dlg correspondence class.
//    In this case, the correspondence is created in-line
//    That is, we're not creating a custom save_dlg::corresp class.
//    For a custom save_dlg::corresp class, you can check out the 'simpl_empl_edit' dialog.

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPTSTR, int) {
    using namespace win32::gui;
    std::string user_name = "john";
    std::string passw = "secret";
    std::string branch = "New York";

    create_modal_save_dlg( 
        IDD_login,
        // in-line correspondence. No validation
        save_dlg::corresp()
            .add_corresp(&user_name, ID_user_name)
            .add_corresp(&passw, ID_passw)
                .add_corresp(&branch, IDC_EDIT1),
        null_wnd);

    msg_box(null_wnd, "You selected '" + user_name + "’, ‘" + passw + "' and '" + branch + "' ");
}

When you rebuild the solution and run the program, you will see:

login2.gif

and after selecting OK, here is what you will see:

login_msg.gif

Not only you could you a std::string class inside a Windows program, you could map it to a corresponding edit control, thus you could enter or receive data as if the control understands and knows how to work with the std::string class!!!

This user_and_passw1 program also shows us another way to create a dialog: by calling the create_modal_save_dlg() function, passing the IDD_login id, the save_dlg::corresp() funtion, and the returning null_wnd pointer.

Just to see if STL is working well with Win32 GUI or not, I added three lines (in bold) from the above program using a simple example from “The STL Tutorial and Reference Guide” book:

#include <win32gui/window.hpp>
#include <win32gui/wnd_extend/save_dlg.hpp>
#include "resource.h"
#include <string>               // ADDED LINE
#include <algorithm>            // ADDED LINE - For reverse algorithm

//    Shows how simple it is to create a save_dlg correspondence class.
//    In this case, the correspondence is created in-line
//    That is, we're not creating a custom save_dlg::corresp class.
//    For a custom save_dlg::corresp class, you can check out the 'simpl_empl_edit' dialog.
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPTSTR, int) {
    using namespace win32::gui;
    std::string user_name = "john";
    std::string passw = "secret";
    std::string branch = "New York";

    create_modal_save_dlg( 
        IDD_login,
        // in-line correspondence. No validation
        save_dlg::corresp()
            .add_corresp(&user_name, ID_user_name)
            .add_corresp(&passw, ID_passw)
                        .add_corresp(&branch, IDC_EDIT1),
        null_wnd);

    reverse(branch.begin(), branch.end());          // ADDED LINE

        msg_box(null_wnd, "You selected '" + user_name + "’, ‘" + passw + "' and '" + branch + "' ");
}

I’m expecting to see the “New York” text backward, and sure enough:

login_msg2.gif

Great!!! Now I can learn STL features and have the output neatly inside a nice dialog box, instead of the boring DOS prompt :) !!!

(to be continued …)


Generated on Fri Jan 21 11:16:27 2005 for Learn Windows Programming with Win32 GUI Generics and VC7.1 by  doxygen 1.3.9.1