Windows Techniques
 

Windows Techniques

Introduction

No serious programmer can ignore Windows--or, more generally, a window-based programming environment. I knew from the beginning that this book would have to include a section on Windows programming. At some point I had several chapters written, complete with a multi-threaded application that painted a three-dimensional animated polygon mesh. Then I tossed it all.

The problem is that teaching Windows programming is a huge undertaking. It calls for a separate book, maybe even a multi-volume compendium. So if I wanted to include an introduction to Windows in this book, I had to be very selective. I had to focus on a few important issues and give the foundations on which the reader could build his or her understanding of Windows programming.

From the point of view of C++ programming methodologies, Windows programming is essentially a virgin territory. There are a few books that use a limited subset of C++ to demonstrate Windows API (Application Programmmer's Interface--the name given to the set of library functions that give the programmer access to the Windows operating system). There are a few commercial libraries that develop their own dialects--again, based on a subset of C++. But the attempts at providing a comprehensive strategy of dealing with a window-based environment using modern C++ are essentially non-existent.

A few years ago I started posting little Windows tutorials and snippets of code at my company's web site. Nothing sophisticated, just a few tips at how to encapsulate some basic Windows functionality. I was amazed at the positive response I got from the programming community. Judging from the number of visits and the tenor of e-mail messages, both from beginning as well as experienced Windows programmers, I must have fulfilled a significant demand.

So here's the plan. I'll start with a small diatrybe against some existing solutions. Then I'll proceed with the introduction to the Windows programming paradigm. I'll show you how to write some simple programs to get you started programming Windows. Then I'll get to the main topic--how to best encapsulate Windows API using the object-oriented paradigm in C++. Even though it's not my ambition to write a complete Windows library, I'll try to explain a lot of the techniques that could be used in writing one.

Of Macros and Wizards

Let's start by talking about how not to write a library.

First of all, do not try to create an obscure dialect of C++. By a dialect I mean a system of macros that generate C++ code. For instance, would you recognize this as a fragment of a C++ program?
IMPLEMENT_DYNAMIC(CMyThing, CMyObject)
BEGIN_MESSAGE_MAP(CMyThing, CMyObject)
    ON_WM_PAINT()
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

If this were the only way to write Windows programs in C++, I'd say C++ is just not the right language for the task. Instead of creating a new dialect using a C++ macro preprocessor, let's invent a new language altogether--a language that is more suitable for Windows and has a semblance of a half-decent programming language. In fact I toyed with this idea, but decided to first give C++ a chance.

Another language escape mechanism used by library writers are "wizards"--little programmer-friendly gadgets that generate C++ code. In principle, generating code using GUI (Graphical User Interface) controls is not such a bad idea. If well thought out, it is equivalent to introducing some sort of a higher-level programming language, in which programming might involve the manipulation of UI gadgets. There is some research into "visual" languages, and this might just be the thing for visually intensive Windows applications.

However, if you want to invent a new language--visual or otherwise--you better be a pretty good language designer. Throwing together a few ad hoc wizards is no substitute for a programming paradigm. It might in fact do more damage than good. One major, unspoken, requirement of any programming language is that your programming environment doesn't discard your source code.

Imagine a C++ compiler deleting your source files after producing machine code.

And this is exactly what most wizards do! Once they generate the target C++ code, your input is lost. Because input in this case consists of the strings you entered in edit controls, the checkboxes you checked, the buttons you pushed, etc. These actions are all part of the "visual" language the wizard implements. If they are not remembered, there is no way you (or, for that matter, anybody else) can make incremental modifications. You either have to redo the whole procedure from scratch, or abandon the visual language altogether and modify the generated code by hand. At this point the whole advantage of the wizard is lost. No matter how good the wizard is, the code it generates is not human-friendly.

So as long as we don't have two-way wizards that can reverse-engineer C++ code into its visual form and let you not only create, but also maintain visual code, we have little choice but to use the programming language at hand--in our case, C++.