Programming Microsoft Windows with C#

Typos, Quirks, and Bitty Bugs

  • Page 12: At the start of the fifth paragraph, "Date types" should be "Data types".

  • Page 14: In the AddFive method, the statement should be:
         i += 5;
    
  • Page 23: The second sentence of the last paragraph makes reference to the DayOfMonth function. That should be the DayOfYear function.

  • Page 45: Towards the middle of the page I indicate that the C# int data type is an alias for the System.Int16 structure. It's actually an alias for the System.Int32 structure.

  • Page 46: The Signed and Unsigned headings on the table should be removed.

  • Page 47: In the table heading, "Date Type" should be "Data Type".

  • Page 51: The last paragraph on the page describes a technique to copy reference files from one project to another. This technique worked in beta versions of Visual Studio .NET but doesn't work in the release version.

  • Page 56: The switch statement is missing a final right parenthesis.

  • Page 60: In the parenthetical sentence in the paragraph following the code listing, I assert that because Visual Basic is a case-insensitive language, you can't use the object name form. That's not true. Visual Basic .NET allows class names to be used as variable names.

  • Page 94: In the penultimate paragraph, the statement "You need to reference the Point class" should be "You need to reference the Point structure".

  • Page 95: In the table of Point methods, the definition to Equals should be:
         bool Equals(object obj)
    
  • Page 99: The paragraph that begins "The Round method..." says that it rounds "to the nearest positive integer for fractional parts of 0.5." That should be "to the nearest even integer for fractional parts of 0.5."

  • Page 102: In the partial sentence at the top of the page, the phrase "Bottom can be greater than Top" should be "Top can be greater than Bottom".

  • Page 102: In the second table, the second Offset method should be defined:
         void Offset(Point pt)
    
  • Page 103: In the second table, the first Contains method should be defined:
         bool Contains(Point pt)
    
  • Page 106: In the last sentence of the paragraph following the table, the phrase "Rectangle can be used for this purpose" should be "ClientRectangle can be used for this purpose".

  • Page 108: To be consistent with the rest of the book, the method definitions in the two tables should not conclude with semicolons.

  • Page 113: To be consistent with the rest of the book, the method definitions in the table should not include the Color class name.

  • Page 116, 118: In the code snippets, SystemColor should be SystemColors.

  • Page 158: In the source code listing of SysInfoUpdate.cs, the data type of cySpace should be "int" rather than "in". The program on the CD-ROM is correct.

  • Page 161: In the SysInfoEfficient.cs listing, there is no reason why the assignment statements of iFirst and iLast need to include a cast to int.

  • Page 177: In the HelloPrinter.cs listing, the constructor should include the statement:
         ResizeRedraw = true;
    
  • Page 195: To be consistent with my variable naming conventions, in the first table, the first point argument should be apoint (or apt), and the second should be apointf (or aptf).

  • Page 203: In the first paragraph, the reference to Chapter 11 should be Chapter 13.

  • Page 220: In the first table, the value of NumPad6 should be 102.

  • Page 227: In the second code snippet, key should be kea.

  • Page 233: To be consistent with the rest of the book, the KeyExamine class should not include the public access modifier. It's not needed.

  • Page 244: In the Caret.cs listing, the attributes "DLLImport" should be "DllImport". The program on the CD-ROM is correct.

  • Page 245: In the Caret.cs listing, I explicitly define a private default constructor. I did this to emphasize that a Caret object must be created with an argument specifying the Control object to which it applies. (And perhaps I mistakenly thought that C# would automatically supply a public default constructor if I didn't include a private one.) The code defining this default constructor can be deleted without affecting the program. C# automatically supplies a default public constructor only if the class has no other constructors (Microsoft C# Language Specifications, section 10.10.4).

  • Page 249: In the TypeAway constructor, the statement setting FontHeight should be deleted. This is evidently the remnants an experiment to determine if FontHeight affects the Font property. It does not.

  • Page 252, 253: My source for the spelling of the Hebrew phrase for "good morning" was Hebrew Phrase Book (Hugo's Language Books Ltd, 1991). Other phrase books have a different (more accepted) spelling: בוקר טוב. To type this phrase into the TypeAway program, you need to type the letters in this order: bet (the c key), vav (the u key) qof (the e key), resh (the r key), space, tet (the y key), vav (the u key), and bet (the c key).

  • Page 253: A Web source for back issues of Microsoft Systems Journal is www.microsoft.com/msj.

  • Page 289: In the table, the square root of 2 should be the square root of 1/2.
  • Page 298: In the partial paragraph at the bottom of the page, the two references to the OnPage method should be DoPage.

  • Page 309: At the end of the first paragraph after the heading, I say you can "define your own const variable." That should read something like "define your own constant." A const is, of course, not a variable.

  • Page 316: In the MouseConnect.cs listing, OnMouseMove method, the if statement should read:
         if (mea.Button == MouseButtons.Left && iNumPoints < iMaxPoints)
    
  • Page 318: In the paragraph following the table, I suggest that you can't force a mouse capture by setting the Capture property to true. Actually, after setting the property the true, you'll get MouseMove events when you pass the mouse over children of the form. However, these events stop when you move the mouse outside the boundary of the form. This restriction serves to prevent a rogue application from blocking mouse input to other applications.

  • Page 335: Four lines from the top I mention the "Beziers program." That should be "Bezier program."

  • Page 347: In the OnPaint method, the DrawRectangle call draws only the left and top of the rectangle. (The last code snippet on page 193 warns about this very problem!) To draw all four sides of each child window, the call should be:
         grfx.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
    
  • Page 357: In the OnPaint method, the DrawLines method will raise an exception if the Point array contains just one point. (You can demonstrate this by clicking in the client area without moving the mouse, and then forcing a repaint.) The problem can be fixed by changing the for body to:
         {
              Point[] apt = (Point[]) arrlstApts[i];
              if (apt.Length > 1)
                   grfx.DrawLines(pen, apt);
         }
    
  • Page 374: The second code snippet that reads:
         new Font(strFamily, float fSize, GraphicsUnits.Point)
    
    should read:
         new Font(strFamily, fSize, GraphicsUnits.Point)
    
  • Page 382: In the AllAboutFont.cs listing, there's an extraneous space between "GdiVerticalFont" and the semicolon.

  • Page 403: In the table of the TextRenderingHint enumeration, AntiAlias should have a value of 4, and AntiAliasGridFit a value of 3.

  • Page 405: In the first sentence after the heading, the reference should be to chapter 3, not 2.

  • Page 405: In the table, the method definitions should not conclude with a semicolon.

  • Page 424: In the first full paragraph, the code snippet should be:
         strfmt.FormatFlags |= StringFormatFlags.NoClip;
    
  • Page 438: In the large central paragraph, the phrase "eventually adapted worldwide" should be "eventually adopted worldwide".

  • Page 454 and 456: To be consistent with the rest of the book, the TimerOnTick methods should not include the private access modifier. It's private by default.

  • Page 485: To be consistent with the rest of the book, the method definitions in the table should not include the Image class name.

  • Page 510: To be consistent with the rest of the book, the method definition in the table should not include the Image class name.

  • Page 515: In the second table, there's a missing right parenthesis on GetThumbnailImage, RotateFliptype should be RotateFlipType, and the terminating semicolon shouldn't be there.

  • Page 530: In the first line of the Wink.cs listing, there's a missing dash in the comment.

  • Page 548: In the large central paragraph, the phrase "any descendent of Control" should be "any descendant of Control".

  • Page 559: In the last sentence of the paragraph following the table, "ContentAlignment.MiddleButton" should be "ContentAlignment.MiddleCenter".

  • Page 582: In the table, the last line should read:
         void DrawFocusRectangle(Graphics grfx, Rectangle rect, 
                                 Color clrForeground, Color clrBackground)
    
  • Page 587: The fourth line of code on the page should read:
         Color clr = (Color) chkbox.Tag;
    
  • Page 592: In the table, the second Scale definition is missing the float type for the second argument.

  • Page 600: Near the bottom of the second paragraph, the phrase "If you set AutoCheck to false," should be "If you set AutoCheck to false."

  • Page 606: In the paragraph between the two tables, the three references to the enumeration "ScrollEventArgsType" should be "ScrollEventType".

  • Page 607: In the central two tables, the eight references to "sb.Maximum" should be "(sb.Maximum + 1 - sb.LargeChange)".

  • Page 624: In the penultimate paragraph, the phrase "the Bézier program" should be "the Bezier program" because the program name doesn't have the accent mark.

  • Page 638, 642, 643, and 644: The tables of DrawCurve, DrawClosedCurve, and DrawFillCurve methods are missing the void return type.

  • Page 644: To be consistent with the rest of the book, the ClosedCurveFillModes constructor should include the public access modifier.

  • Page 678: About midway down the page, I show how to calculate a variable called index from the Count property of the MenuItems property. It's also possible to conveniently obtain this value when calling the Add property of MenuItems:
         index = Menu.MEnuItems.Add(mi);
    
  • Page 684: In the first table, the method definitions should not conclude with a semicolon.

  • Page 702: In the second line of the code snippet, the AddRectangle call is missing a concluding parenthesis.

  • Page 708: The first code snippet should be:
         path.Transform(matrix);
    
  • Page 730: In the program listing, the first line of the constructor should be:
         Text = "Simple Dialog";
    
  • Page 760: In the FontAndColorDialogs.cs listing, the DrawString call includes the argument this.ClientRectangle. To be consistent with the rest of the book, this should be just ClientRectangle.

  • Page 770: In the second to last paragraph, I make reference to "the Single class". That should be "the Single structure".

  • Page 773: In the HeadDump.cs listing, OnPaint method, the for body should begin with the statement:
         if (iCount == 0)
              break;
    
  • Page 776: The long string defined by the first code snippet should not conlude with a semicolon.

  • Page 804: To be consistent with the rest of the book, the TwoPointLinearGradientBrush constructor should include the public access modifier.

  • Page 866: The small comment is a remnant of an earlier version of the program and should be deleted.

  • Page 867: The set accessor of the FindDown property is incorrect. The Down button should be checked if value is true, and the Up button otherwise.

  • Page 893: The statement that sets the Anchor property of the Label control should be:
         label.Anchor |= AnchorStyles.Right;
    
  • Page 905: In the Transform.cs listing, the definition of the bits array requires only six lines of eight values. The last 16 initializers can be removed.

  • Page 935: The AddString methods in the table are missing the void return type.

  • Page 959: In the StatusBarAndAutoScroll constructor, The second Label control gets its AutoSize property set to true, but the first one does not. The first Label control should be set consistently.

  • Page 960: The SimpleStatusBarWithPanel constructor has the same problem.

  • Page 977, second paragraph: The directory created by Visual Studio .NET that contains various useful images is not included with Visual C# .NET.

  • Page 996: In the paragraph right under the screen shot, the reference to DrawItem should be to MeasureItem.

  • Page 1024: In the StatusBarPrintController constructor, the call to the constructor initializer base() is not necessary. As the Microsoft C# Language Specifications (section 10.10.1) states: "If a constuctor has no constructor initializer, a constructor initializer of the form base() is implicitly provided."

  • Page 1029: In the SimplePrintDialog.cs program, the PrintDialogHelloWorld class should be named SimplePrintDialog.

  • Page 1041: The penultimate comment should be "Reset StringFormat to display header and footer."

  • Page 1042: In the second paragraph after the code listing, the reference to PrintDialog should be to PrintDocument.

  • Page 1057: The table at the bottom of the page should include the Height property.

  • Page 1058: In the third paragraph, the discussion of the Width property only applies to vertical splitters. For horizontal splitters, the Height property describes the thickness of the splitter. Also, the BorderStyle.Fixed3D property does indeed produce a 3D effect, but only when the thickness of the splitter is greater than the default 3 pixels.

  • Page 1072, first paragraph: See comment for page 977.

  • Page 1073: In the second full paragraph, I complain how the GetDirectories method of the DirectoryInfo class displays a message box for drive A: if the drive is empty. First, the first sentence of the paragraph should refer to the GetDirectories method rather than DirectoryInfo, which is the class name. More significantly, a reader suggests avoiding the problem by inserting the following statement right before the try block in the AddDirectories method of the DirectoryTree class:
         if (!dirinfo.Exists) 
              return;
    

  • Page 1083, paragraph at bottom: See comment for page 977.

  • Page 1088: In the last line of the last table, clrText should be clrBack.

  • Page 1103, first paragraph: See comment for page 977.

  • Page 1105: In the three code snippets, DrawImage should be grfx.DrawImage.

  • Page 1115: In the second and third code snippets on this page, GetDC and ReleaseDC should be GetHdc and ReleaseHdc, respectively.

  • Page 1118: In the last line "saved as a file" should be "saved as a field".

  • Page 1134: In the assignment of the Dock property of the Splitter control, the comment should be deleted.

  • Page 1142: The code snippet near the top of the page is missing a semicolon. The fourth code snippet from the bottom should probably have a lowercase string argument for stylistic consistency with much of the rest of the book.

  • Page 1154: The penultimate code snippet is missing a concluding semicolon.

  • Page 1187, last paragraph: The use of a long for the Length and Position properties of a Stream object implies maximum file sizes of 263 bytes, which is approximatly 9 × 1018 bytes, or 9 exabytes.

  • Page 1198: The second paragraph describes a way to redirect HexDump output to the printer. This technique no longer works in the release version of the .NET framework. An exception is raised that reports that a FileStream object (which is obviously created by the StreamWriter constructor) can only refer to a file and not a device. The exception message further indicates you must open the printer device using the Win32 API function CreateFile, then create a FileStream object from that handle. I have not been able to get this to work, however.

  • Page 1209: In the third paragraph, the last sentence should conclude: "you create an instance of FileInfo by specifying a filename in the constructor."

  • Page 1243: In the final code snippet on this page, Equals should be String.Equals.

  • Page 1251: In the first table, last Sort definition, the iCount argument is missing the int data type.

    © Charles Petzold, 2003
    cp@charlespetzold.com
    This page last updated January, 2003