PETZOLD BOOK BLOG

Charles Petzold on writing books, reading books, and exercising the internal UTM


Recent Entries
< PreviousBrowse the ArchivesNext >
Subscribe to the RSS Feed

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

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.


Comments:

I've got the 3.5" SDK discs (11 of them) for Windows 3.1 ("Copyright 1985-1992")

and another set (6 discs) "For Personal Computers Running Microsoft Windows/286 and Microsoft Windows/386" (no copyright date on the label), which I assume is Windows 2.0.

I probably have the binders somewhere too...

James Curran, Mon, 8 Dec 2014 23:23:58 -0500

I dug out my USB 3.5 floppy drive. The files on the mystery disks were all dated 7/26/1988 1:00 am.

Now I have an urge to install an ancient OS on a VirtualBox. Unfortunately, my Win 2, Win 3.1, and DOS 6.22 sets are all missing discs (and my Win 1.0 is on 5.25" discs)

But I was able to find a seemingly complete WinNT (v3.5, I think)

James Curran, Mon, 8 Dec 2014 23:52:06 -0500

As intimidating as early Windows programming was, it would have been far harder without your books. Thanks for wading through this and giving the rest of us something we could use.

John Cook, Tue, 9 Dec 2014 10:56:20 -0500

Charles, here are three versions of the source code, from floppies.

http://ozz.ie/h31100

— Ray Ozzie, Tue, 9 Dec 2014 11:42:52 -0500

Thanks! This is very interesting: Three different versions showing three different ways of handling the strings. — Charles

This is the first hello word application that I wrote back in my high school days. I still have my old win32 API books written by Charles. Thank you for this post, I feel young again :)

— Mateusz Kopij, Tue, 9 Dec 2014 11:56:05 -0500

Back in that era, I was quite proficient at Motif on Unix. Porting apps to Windows was monumentally frustrating. Your books would provide answers when a half dozen others could not.

Thank you Charles.

— Mark Johnson, Tue, 9 Dec 2014 15:35:24 -0500

Haha, you were right: Coming from a pascal/DOS background those days, it was really astonishing how many code was required to get only a simple window, telling "hello world" :-))

Vomitorium, Tue, 9 Dec 2014 16:01:05 -0500

Hey Charles

I, like many people of my age (I'm 60) learned Windows programming from your book. At the time, I would have said that the code was insanely complex. I recently re-read the book, Having grappled with the Microsoft APIs ever since then, I found it refreshingly simple. WCF, Entity Framework anyone?

— Andrew, Tue, 9 Dec 2014 21:04:53 -0500

I think you missed the point in their sample.

Their sample showed not just how to write "Hello World" in the client area, but demonstrated all those other things that you explicitly took out.

All things which, the programmers at least believed, people would want to do in their programs.

Could it have been shorter? Absolutely; That doesn't mean their sample wasn't useful, indeed, your article itself demonstrates the learnings that their sample hoped to convey in a suitably interested student.

— Peter Dolkens, Tue, 9 Dec 2014 22:09:21 -0500

And now I'm amazed, given that I've been looking for Windows Premiere Edition for a while (the version widely available on the internet being a fake), and now the hello world from its SDK shows up!

Interesting that the .rc says version 1.01, though.

James, your 2.x SDK seems interesting, I guess it's 2.03 by the date (between that of 2.03 and 2.1).

slipstream, Wed, 10 Dec 2014 04:27:16 -0500

The best windows programmers are the ones who started on the old-style C message loop apps. They are the ones who really "get" how things work.

— Dave Smith, Wed, 10 Dec 2014 04:52:09 -0500

I have the Binder, Floppies somewhere around here. At my age that was my middle aged fun. I loved that time of computing (and I love it now) - but the mystery of everything. You would buy a computer, sit down and really learn everything you could. No books. Just SDK manuals like the windows binders. MSDN came along much later (originally was called Developer Network, came on 1 CD - the reason I bought my first CDROM drive).

I am way too much of a packrat. I still have all my TRS-DOS and CP/M stuff as well.

— Lester Henderson, Wed, 10 Dec 2014 11:04:02 -0500

Petzold, Pietrek, Schulman, Duncan... those were my bibles back in the day.

Definitely brings back memories.

— Dave Newton, Wed, 10 Dec 2014 13:04:25 -0500

Peter Dolkens, with all due respect, you're thinking like a manager. Possessing a capability doesn't require its use. Forcing programmers to use those unneeded capabilities is a waste of time and bits.

— gus3, Wed, 10 Dec 2014 13:57:53 -0500

I remember picking up "Programming Windows: the definitive guide to win32 API" and my jaw dropped when I looked at the Hello world Windows program. Albeit never actually using the stuff you teach in the book as I end up being a *nix developer, I really impressed with the style and detail level of this book.

— Doug, Wed, 10 Dec 2014 18:42:36 -0500

I still have my copy of "Programming Windows" for version 3.0 and I keep it as a souvenir along with my copy of Kernighan and Ritchie from 1983. It's beggars belief that this is all we had before the MSDN, Code Project, Stack Overflow etc.

Two of the best books, I ever acquired.

— Greg Russell, Thu, 11 Dec 2014 03:04:43 -0500

Like others I cut my teeth on Windows 3.0 with Charles' book. It was a bit of a culture shock after learning realtime embedded C from K & R but I've no doubt my life would have been much harder without it. Thank you Charles.

Steve Lee, Thu, 11 Dec 2014 06:03:40 -0500

Thank you very much for your invaluable help Mr. Petzold! Your book teached me Windows programming and I enjoy it so much. Best regards!

— Cesar Mello, Thu, 11 Dec 2014 06:47:45 -0500

Charles, your book was my bible - I learnt a lot of stuff from them. When I did my work using MFC and later the .Net Framework, the insights your book gave me always made my life easier, the work interesting.

Thank you.

Sean Cleetus, Thu, 11 Dec 2014 07:21:27 -0500

The final version really captures the spirit of "Hello World." The "Hello World" program wasn't an exercise in programming, it was an exercise in compiling and running. Is the compiler on your path? Are you properly referencing your "includes" directory? Can you run the linker, or invoke the JVM, or whatever is needed to run it. Did the words "Hello World" appear as expected? You really need to know that all of that is out of the way before proceeding.

Charles Forsythe, Thu, 11 Dec 2014 09:05:16 -0500

Happy days ! Your book and the Quick C for Windows product were the start of a voyage of discovery ... Thanks for the memories ! (pun intended)

— ian, Thu, 11 Dec 2014 09:48:02 -0500

Something called gus3 wrote

"Peter Dolkens, with all due respect, you're thinking like a manager."

No, he isn't, but you're being a jerk and misrepresenting his point.

— mk, Thu, 11 Dec 2014 13:16:10 -0500

OK, time to close off comments. Thank you all and sorry it had to descend into name-calling. — Charles


Recent Entries
< PreviousBrowse the ArchivesNext >
Subscribe to the RSS Feed

(c) Copyright Charles Petzold
www.charlespetzold.com