No matter which development tools you use, programming for Windows
is different from old-style batch-oriented or transaction-oriented
programming. To get started, you need to know some Windows fundamentals. As a frame
of reference, we'll use the well-known MS-DOS programming model. Even if
you don't currently program for plain MS-DOS, you're probably familiar with it.
When you write an MS-DOS-based application in C, the only absolute requirement is a function named main. The operating system calls main when the user runs the program, and from that point on, you can use any programming structure you want. If your program needs to get user keystrokes or otherwise use operating system services, it calls an appropriate function, such as getchar, or perhaps uses a character-based windowing library.
When the Windows operating system launches a program, it calls the program's WinMain function. Somewhere your application must have WinMain, which performs some specific tasks. Its most important task is creating the application's main window, which must have its own code to process messages that Windows sends it. An essential difference between a program written for MS-DOS and a program written for Windows is that an MS-DOS-based program calls the operating system to get user input, but a Windows-based program processes user input via messages from the operating system.
Many development environments for Windows, including Microsoft Visual C++ version 6.0 with the Microsoft Foundation Class (MFC) Library version 6.0, simplify programming by hiding the WinMain function and structuring the message-handling process. When you use the MFC library, you need not write a WinMain function but it is essential that you understand the link between the operating system and your programs.
Most messages in Windows are strictly defined and apply to all programs. For example, a WM_CREATE message is sent when a window is being created, a WM_LBUTTONDOWN message is sent when the user presses the left mouse button, a WM_CHAR message is sent when the user types a character, and a WM_CLOSE message is sent when the user closes a window. All messages have two 32-bit parameters that convey information such as cursor coordinates, key code, and so forth. Windows sends WM_COMMAND messages to the appropriate window in response to user menu choices, dialog button clicks, and so on. Command message parameters vary depending on the window's menu layout. You can define your own messages, which your program can send to any window on the desktop. These user-defined messages actually make C++ look a little like Smalltalk.
Don't worry yet about how these messages are connected to your
code. That's the job of the application framework. Be aware, though, that the
Windows message processing requirement imposes a lot of structure on your
program. Don't try to force your Windows programs to look like your old
MS-DOS programs. Study the examples in this book, and then be prepared to start fresh.
The Windows Graphics Device Interface
Many MS-DOS programs wrote directly to the video memory and the
printer port. The disadvantage of this technique was the need to supply driver
software for every video board and every printer model. Windows introduced a layer
of abstraction called the Graphics Device Interface (GDI). Windows provides
the video and printer drivers, so your program doesn't need to know the type
of video board and printer attached to the system. Instead of addressing the
hardware, your program calls GDI functions that reference a data structure called
a device context. Windows maps the device context structure to a physical
device and issues the appropriate input/output instructions. The GDI is almost as
fast as direct video access, and it allows different applications written for
Windows to share the display.
To do data-driven programming in MS-DOS, you must either code the data as initialization constants or provide separate data files for your program to read. When you program for Windows, you store data in a resource file using a number of established formats. The linker combines this binary resource file with the C++ compiler's output to generate an executable program. Resource files can include bitmaps, icons, menu definitions, dialog box layouts, and strings. They can even include custom resource formats that you define.
You use a text editor to edit a program, but you generally use
wysiwyg (what you see is what you get) tools to edit resources. If you're laying out a
dialog box, for example, you select elements (buttons, list boxes, and so forth)
from an array of icons called a control
palette, and you position and size the
elements with the mouse. Microsoft Visual C++ 6.0 has graphics resource editors for
all standard resource formats.
With each new version of Windows, memory management gets easier. If
you've heard horror stories about locking memory handles, thunks, and
burgermasters, don't worry. That's all in the past. Today you simply allocate the memory you need, and Windows takes care of the details. Chapter 10 describes
current memory management techniques for Win32, including virtual memory
and memory-mapped files.
Dynamic Link Libraries
In the MS-DOS environment, all of a program's object modules are statically linked during the build process. Windows allows dynamic linking, which means that specially constructed libraries can be loaded and linked at runtime. Multiple applications can share dynamic link libraries (DLLs), which saves memory and disk space. Dynamic linking increases program modularity because you can compile and test DLLs separately.
Designers originally created DLLs for use with the C language, and
C++ has added some complications. The MFC developers succeeded in
combining all the application framework classes into a few ready-built DLLs. This
means that you can statically or dynamically link the application framework classes
into your application. In addition, you can create your own
extension DLLs that build on the MFC DLLs. Chapter 22 includes information about creating MFC extension DLLs and regular DLLs.
The Win32 Application Programming Interface
Early Windows programmers wrote applications in C for the Win16 application programming interface (API). Today, if you want to write 32-bit applications, you must use the new Win32 API, either directly or indirectly. Most Win16 functions have Win32 equivalents, but many of the parameters are different16-bit parameters are often replaced with 32-bit parameters, for example. The Win32 API offers many new functions, including functions for disk I/O, which was formerly handled by MS-DOS calls. With the 16-bit versions of Visual C++, MFC programmers were largely insulated from these API differences because they wrote to the MFC standard, which was designed to work with either Win16 or Win32 underneath.