A C++ Library for Win32 Applications

I had a few reasons for creating my own C++ library for Win32 development, even though MFC already existed. First of all, it was a great way to practice Win32 development and apply the great stuff I was learning in the Petzold book. This was also a terrific chance to practice making an object-oriented application framework that I liked. MFC is nice and is terribly useful, compared to all the boilerplate stuff required for straight-API C coding. Still, I wanted something that was a little closer to the API that would let me make use of STL and namespaces.

Below is an example of the simplest possible application that can be made with this library:

// Simplest possible Parks Computing WindowLib application

#include <WindowApp.h>

int APIENTRY _tWinMain(
    HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, 
    LPTSTR lpCmdLine, 
    int nCmdShow
    )
{
    ParksComputing::WindowLib::WindowApp().Main(hInstance, lpCmdLine, nCmdShow);
}

I'll be adding descriptions of the classes in the library, but for now you can download WindowLib.zip (approximately 1.2 MB), which contains the library source code, release versions of the .LIB and .DLL builds of the library for ASCII and Unicode, and several example applications.

Latest Changes

I have finally released a version that compiles with Visual Studio .NET. This does not mean, of course, that the library uses the .NET platform; it just takes some advantage of the improved C++ standards support in Visual Studio .NET. I also cleaned up several bugs and really dumb things. The current version has been "battle-tested" on production programs, also, and has performed well.

One thing this version still lacks is proper thread safety. I have used Loki and a thread class of my own, but I didn't include these because of some difficulty building and using the library in some situations. I will revisit this soon, and update the library accordingly.

Compiling the Code

To compile the library and examples you will need a C++ compiler and the Win32 Platform SDK. I used Microsoft Visual Studio .NET to write the library, and I have included the Visual Studio projects (.vcproj) and solutions (.sln) that I built.

Extract the WindowLib zip file into a directory. The directory will contain WindowLib, Baseline++, HEXCALC, OWNDRAW, SplitterWindow, and SYSMETS sub-directories. If you are running Microsoft Visual Studio .NET, you can load the WindowLib.sln solution in this directory to view all the projects at once. Otherwise, configure your include path to point to the WindowLib directory and add the appropriate library file to your link phase. There are subdirectories under the WindowLib directory for various debug and release versions for ASCII and Unicode.

Message Cracking

I added a separate article about the message-cracking template classes containing the info that used to be on this page, plus a little bit more.

Threading, Security, and Error Handling

I'm rolling back through my Win32 Library line by line now looking for places where I should be concerned about thread safety, security issues, and error handling. Naturally, this should all have been in place already were this a professional-quality library. Since the more I work on this library, the more complete it becomes, I thought it would also be a good idea to practice dealing with these issues while I'm under the hood... before they come back to bite me.

The Error-Handling Approach

My approach to error handling actually began with making the library fail when an error occurred. Read more about it here.

The Threading Approach

Thread safety started with a concept called resource acquisition is initialization, and it's now heading toward radical templatization. Read more about it here.

A Big Overhaul

My goodness, I've been busy. I changed so much from the last revision that I scarcely where to begin!

Clean Up

I made the virtual message handlers protected since nobody has any business ever calling one of those directly from outside the class implementation. If you do find a reason, feel free to derive your own class and make the handlers public, but don't blame me when it blows up in your face.

I fixed a lot of type-related issues as well. I got rid of BOOL where I could and replaced it with the built-in bool type. There is now a template method called bool_cast that assists in this conversion. It's a very simple method:

template<class T> inline bool bool_cast(T value)
{
    return value ? true : false;
}

Anytime you want to convert an integer value to bool without triggering a warning, wrap the value in a call to bool_cast:

int myInteger = TRUE;
bool myBoolean = bool_cast(myInteger);

Other than a lot of basic housekeeping, the biggest change I made was in the way Windows messages are handled.

Library Overview

Listed here are all the classes in the library. As I document each class, the headings below will become hyperlinks to detailed descriptions. Unless otherwise noted, these classes live in the ParksComputing::WindowLib namespace.

Window

This is the base class for most of the library. It provides basic methods and properties related to window creation and manipulation. The most interesting part of writing this class was making the Win32 window procedure play well on a C++ playground. This is done with a static GlobalWindowProcedure method that looks for a window handle in a hash map of handles to instances of Window objects. Once found, the static procedure calls the instance's WindowProc method; otherwise, it hands messages off to the default window procedure (::DefWindowProc).

Other methods are provided for window registration, creation, initialization and subclassing, and the rest are thin wrappers around Win32 API calls that operate on window handles.

One thing that is evident in this class and which cascades to its descendants is the way that it handles Unicode. I didn't want to introduce something like the MFC CString class because I want this library to work well with STL, which already provides the std::string class. Unfortunately, STL provides std::string for 8-bit characters and std::wstring for wide characters, which would have been cumbersome. What I did instead was create a typedef called tstring which resolves to std::basic_string<TCHAR>. This typedef is then used all over the library to ease string manipulation.

WindowClass

This class is derived from the base API structure WNDCLASSEX. It adds some useful methods to the WNDCLASSEX structure, such as constructors to initialize the fields to a sane default, assignment and equality operators, conversion operators, and methods to assist in window registration.

Message

The Message class is derived from the base Win32 MSG class (actually ::tagMSG). Like WindowClass, it provides constructors, assignment and equality operators, and conversion operators. It also contains an internal functor class called TestDialogMessage, which calls ::IsDialogMessage to determine if a message is destined for a supplied dialog handle.

WindowApp

This, as they say, is where the magic happens. Derived from the Window class, WindowApp provides enough boilerplate code to be a fully-functional (if somewhat dull) Win32 application. Besides overriding the WindowProc method of Window, it supplies InitInstance and Main methods. As seen in the example above, the Main method is the entry point into an application written with WindowLib.

Dialog

This class provides boilerplate code for dialogs. Besides providing a default dialog procedure, it also provides a Main method which starts a modal instance of the dialog.

ModelessDialog

This is derived from Dialog and, as the name implies, it provides a base class for non-modal dialogs.

DialogApp

DialogApp is the dialog equivalent to WindowApp. It provides a Main method with the same signature as WindowApp::Main, and it also supplies constructors that accept a dialog resource ID. This class is derived from WindowApp.

ControlWindow

This is the base class for all dialog controls, such as buttons, list boxes, etc. The override of Window::Create subclasses the control's window to provide a window procedure for message handling. Also supplied are message handlers for WM_CHAR and WM_GETDLGCODE.

Button

Control class for button controls.

Edit

Control class for edit controls.

ListBox

Control class for list box controls.

Static

Control class for static controls.

StatusBar

This class handles the creation and manipulation of window status bars.

Splitter

This is a class that was the first "value-added" class in the library, meaning that it provides a feature beyond something provided in base Win32. It is a base class for horizontal and vertical splitters that provide a means to resize two adjacent windows split with a draggable bar.

HorizSplitter

Horizontal splitter class derived from Splitter.

VertSplitter

Vertical splitter class derived from Splitter.

OleControlSite

This one never went anywhere. I wanted to add the ability to host ActiveX controls, but it was more time than I could invest when I started to work on it. Maybe one day, when I'm really bored...