Home Catalog Evaluate Download

Errata for Petzold's book

"Programming Windows Fifth Edition"

The most widely recommended book for learning to write Windows programs is Charles Petzold's Programming Windows Fifth Edition. This book teaches Microsoft's WIN32 API (application programming interface) which is the infrastructure that Microsoft offers developers so they can accomplish the standard Windows user interface (graphical look and feel). This is a great book, and has as few errors as any programming book I have ever seen. But there are a few. Mr. Petzold posts an incomplete errata list as part of the FAQ on his web page at

http://www.charlespetzold.com/pw5/pw5faq.html.

Here is a list of additional errata for this book.
p. 27 The fourth complete sentence from the top is: "If you define this array as a local variable to a function, it must be defined as a static variable..." However this has not been true since the adoption of ANSI C in 1990.
p. 45 The HELLOWIN.C program would be better if it checked the HWND returned by the call to CreateWindow() before using this variable in the subsequent call to ShowWindow().
p. 143 The first sentence of the final paragraph uses the acronym GPI which I believe should be API (GPI was OS/2 talk).
p. 264 In the second to last paragraph the reference to DestroyWindow() should be a reference to DestroyCaret().
p. 318 The SYSMETS.C program listing should show the statement:

    #define _WIN32_WINNT 0x0500

before including windows.h . The actual code on the CDROM does have this statement. Without it, the code will not compile.

p. 357 The last sentence of the first paragraph states: "a separate window procedure named ChildProc" but as seen on p. 300 the window procedure in CHECKER3 was actually named ChildWndProc.
p. 391 Just before the final sentence there is a code sample involving GetWindowLong() but the preceding sentence states that the code sample will employ GetWindowWord() which is an obsolete function.
p. 393 Near the bottom are references to GetClassWord() and SetClassWord(), both of which are obsolete and replaced by GetClassLong() and SetClassLong() (which are used in the code sample on that page).
p. 490 In the middle of the page are the sentences: "Thus, for this particular dialog box, the upper left corner of the dialog box is 5 characters from the left edge of the main window's client area and 2-1/2 characters from the top edge. The dialog itself is 40 characters wide and 10 characters high." These sentences should be: "Thus, for this particular dialog box, the upper left corner of the dialog box is 8 characters from the left edge of the main window's client area and 4 characters from the top edge. The dialog itself is 45 characters wide and 12-1/2 characters high."
p. 496 The table at the top of the page shows the following default window styles:

    GROUPBOX : BS_GROUPBOX | WS_TABSTOP
    LISTBOX : LBS_NOTIFY | WS_BORDER | WS_VSCROLL

However Microsoft's documentation for these controls state that if you don't specify any window style then you will get only the following:

    GROUPBOX : BS_GROUPBOX
    LISTBOX : LBS_NOTIFY | WS_BORDER

p. 506 At the bottom of the page, the code:

    SendDlgItemMessage( hDlg, id, iMsg, wParam, lParam );

is equivalent to:

    SendMessage( GetDlgItem( hDlg, id ), iMsg, wParam, lParam );

instead of what's shown, which is:

    SendMessage( GetDlgItem( hDlg, id ), id, wParam, lParam );

p. 512 The source code statement:

    hCtrlBlock = GetDlgItem (hDlg, IDD_PAINT) ;

should be:

    hCtrlBlock = GetDlgItem (hDlg, IDC_PAINT) ;

p. 518 The CONTROL statement at the bottom of the page employs the style "TABGRP" which does not seem to be defined anywhere but is probably intended to mean WS_TABSTOP | WS_GROUP.
p. 564 The reference to "Figure 10-11" should be "Figure 11-11".
p. 603 The word "job" near the end of the first paragraph should be "call".
p. 634 The source code that starts on this page uses the variable "iNoiColCopy" but the write-up on p. 638 refers to it as "iNonColCopy".
p. 725 The definition of the BITMAPFILEHEADER struct refers to the final member as .bfOffsetBits but its name is actually .bfOffBits.
p. 747 The following 3 lines in the Printf() function of DIBHEADS.C do not guarantee that the new text is appended to the end of the EDIT control's contents:

    SendMessage( hwnd, EM_SETSEL, (WPARAM)-1, (LPARAM)-1 );
    SendMessage( hwnd, EM_REPLACESEL, FALSE, (LPARAM)szBuffer );
    SendMessage( hwnd, EM_SCROLLCARET, 0, 0 );

Things can get screwed up when the user employs the EDIT control's scroll bars while new text is still arriving. This can be fixed via the statements:

    DWORD nChars = (DWORD)SendMessage( hwnd, WM_GETTEXTLENGTH, 0, 0 );
    SendMessage( hwnd, EM_SETSEL, (WPARAM)nChars, (LPARAM)nChars );
    SendMessage( hwnd, EM_REPLACESEL, FALSE, (LPARAM)szBuffer );
    SendMessage( hwnd, EM_SCROLLCARET, 0, 0 );

p. 817 In the third bullet item the phrase "during the BitBlt to StretchBlt call" should be "during the BitBlt or StretchBlt call".
p. 829 In the first paragraph, the reference to the "Grays1 program" should be "Grays2 program".
p. 831 The reference to QM_QUERYNEWPALETTE should be WM_QUERYNEWPALETTE.
p. 876 The statement in the PackedDibCreatePalette() function:

    plp = malloc (sizeof (LOGPALETTE) * (iNumColors - 1) * sizeof (PALETTEENTRY)) ;

should be:

    plp = malloc (sizeof (LOGPALETTE) + (iNumColors - 1) * sizeof (PALETTEENTRY)) ;

p. 911 The comment stating: "If there's an existing packed DIB, free the memory" should be: "If there's an existing bitmap object, free the memory".
p. 925 The comment above DibGetColor() states that this function is called DibSetColor(). This mistake appears again (in reverse) on p. 926.
p. 928 The DIBBLE.C program crashes on certain 24 bit/pixel bitmaps when, for instance, the operator performs a flip followed by another flip. An invalid page fault occurs due to the line of code in DibGetPixel():

    case 24: return 0x00FFFFFF & * (DWORD *) pPixel;

The crash occurs at the end of the final row when pPixel is only guaranteed to point to an RGBTRIPLE worth (3 bytes) of memory in our process's address space. But this line of code casts pPixel to a DWORD and then attempts to dereference 4 bytes which is illegal. The program does not crash on all 24 bit/pixel DIBs because, depending upon the bitmap's dimensions, the 4th byte may or may not be within our process's address space. The fix is to read only 3 bytes from pPixel rather than 4.

p. 947 The DIBHELP.H header file declares a function:

    HDIB DibCreateFromDdb( HBITMAP hBitmap );

which apparently was never implemented in DIBHELP.C .

p. 956 The DIBBLE program over scrolls by 1 pixel in the vertical direction because the statement:

    si.nMax = DibHeight (hdib);

should be:

    si.nMax = DibHeight (hdib) - 1;

This can be observed when DIBBLE is displaying a .BMP file using a vertical scroll bar and the image has been scrolled fully up (vertical scroll bar fully down). ZOOMIN will prove the presence of a single pixel wide line of white pixels at the bottom of the window. The same fault exists in the code shown on p. 957 for the horizontal scroll bar.

p. 967 In the middle of the page there is a memory leak caused by the statement:

    hBitmap = DibCopyToDdb (hdib, hwnd, hPalette);

The prior hBitmap (a static variable) needs to be freed using DeleteObject(). The correct code is shown on p. 964 in response to the IDM_EDIT_ROTATE and IDM_EDIT_FLIP messages. A similar memory leak occurs in the code that is about two-thirds of the way down p. 968.

p. 1249 The szAppName[] array is initialized with the value "StrProg" which is obviously a cut & paste error indicating that Petzold wrote the StrProg program on p. 1258 first and then modified it to become the EdrTest program on p. 1249.
p. 1265 The second passed param to the GetProcAddress() WIN32 API function is not a TCHAR and hence it should not be decorated with the TEXT() preprocessor macro.
p. 1294 The SINEWAVE.C program has a bug in it since the call to waveOutUnprepareHeader() follows the call to waveOutClose(). After the call to waveOutClose() the hWaveOut is no longer valid yet is being used in the call to waveOutUnprepareHeader().
p. 1445 The index states there is a reference to DestroyWindow() on p. 264 but this is a typo and what is discussed on p. 264 is DestroyCaret().


Return to the Petzold Discussion Page


Return to the Catalog of Programs