The Infamous Windows “Hello World” Program
December 8, 2014
New York, N.Y.
A recent blog post by consultant John Cook reminded everybody about the infamous “Hello World” programs in the early chapters of the first five editions of Programming Windows:
“Hello world” is the hard part
Following a little discussion on my Facebook page initiated by my Xamarin colleague and old friend Larry O'Brien, I began to realize that some people believe that I invented the excessively overlong Windows "Hello World" program. I'm afraid I did not.
I learned Windows programming from documents included with the Windows 1.0 beta and release Software Development Kits. These included a printed API reference, of course, but beyond that the most important document was the Programming Guide, which was published with the SDK in 1985 as 258 7"x9" looseleaf pages in a binder. This document contained five sample programs that I studied in great depth in attempting to learn the Windows API. These samples were named
- HELLO
- TYPE
- TRACK
- SHAPES
- FONTTEST
I no longer have the 5" floppies that contained the sample code, but I do still have the binder with the Programming Guide and the printed listings.
Although it was the very first Windows sample program, the HELLO program was quite fancy: Besides displaying "Hello Windows" in its title bar and client area, it added an About item to the system menu and displayed a dialog box when that item was selected.
Here is the listing of the HELLO.C file from that Windows Programming Guide, patched together from scans of four pages:
The HELLO.H header file is missing from the book, but it was undoubtedly very short and only defined identifers that were referenced in both the C file and the HELLO.RC resource script, which looked like this:
As I studied this program and experimented with it, it became quite obvious to me that it was longer and more complex than it needed to be. I began to believe that it was not a good introductory program for someone learning the Windows API, and I thought that explaining Windows programming might benefit with something shorter and simpler. So I methodically began trimming this program down to size. (I had no idea at the time I might actually write a book about Windows programming, but it helps me in learning something new if I imagine trying to explain it to somebody else.)
I wondered if the code could be restructured to add clarity. The separate definitions of the HelloInit and HelloPaint functions seemed unnecessary, so I eliminated those and replaced the function calls with the bodies of those functions.
I think I then started looking at the text strings. As you can see, towards the top of the file some global char pointers are declared, and the beginning of WinMain uses LocalAlloc to allocate memory for these strings and then load them from the resource script with LoadString. Although I recognized the value of defining strings external to the source code, the needs of internationalization didn't seem appropriate for a first program. I wondered if the strings could be declared and initialized right in the source code, and it turned out they could. (Keep in mind that it was not at all obvious that standard C programming practices would work in a Windows program. That's how weird this was.)
Following the CreateWindow call, calls to GetSystemMenu and ChangeMenu put another item on the system menu. I wondered: Was this absolutely necessary to the proper functioning of a Windows program? I commented out those lines, and the program still ran. Because the program could no longer display the dialog box, I eliminated the About function and the processing of the WM_SYSCOMMAND message and the dialog template, and then I realized the only thing left in the resource script was the icon. Could a Windows program survive without a custom icon? Apparently yes. Could a Windows program be compiled and linked without a resource script? Turned out it could.
I tried a bunch of other simplifications. Some worked, some did not. But eventually I got it down to the bare essentials: Two functions, seven local variables, no yucky global variables, and no resource script.
The first edition of Programming Windows was published in 1988 and focused on Windows 2. Interestingly, the first code in that book did not present the "classical" Windows "Hello World" program but instead played around with multiple windows and let the titlebars say "hello.". You can browse the code from that first edition here:
ftp://ftp.charlespetzold.com/ProgWin1/
It was the second edition of Programming Windows (1990 and focusing on Windows 3.0) that first included what is now the familiar Windows "Hello World" program. Here's all the source code from that edition:
ftp://ftp.charlespetzold.com/ProgWin30
And here's the HELLOWIN.C listing from Chapter 1. No resource script was included in this project:
/*--------------------------------------------------------
HELLOWIN.C -- Displays "Hello, Windows" in client area
(c) Charles Petzold, 1990
--------------------------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdParam, int nCmdShow)
{
static char szAppName[] = "HelloWin" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, // window class name
"The Hello Program", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, "Hello, Windows!", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
Aside from the antique C syntax and the weird idiosyncratic formatting, I think most people would agree that compared with Microsoft's original, mine is a model of clarity and brevity.
Eventually I got tired of people complaining how long my "Hello World" program was, so Programming Windows, 5th edition (1998) began with this program:
/*--------------------------------------------------------------
HelloMsg.c -- Displays "Hello, Windows 98!" in a message box
(c) Charles Petzold, 1998
--------------------------------------------------------------*/
#include <windows.h>
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MessageBox (NULL, TEXT ("Hello, Windows 98!"), TEXT ("HelloMsg"), 0) ;
return 0 ;
}
That version probably has as much relevance to real-life Windows programming as printf("hello world") has to real-life character-mode C programming.