diff --git a/MigrateDocumentation/Program.cs b/MigrateDocumentation/Program.cs index 472e39c..ecffa1f 100644 --- a/MigrateDocumentation/Program.cs +++ b/MigrateDocumentation/Program.cs @@ -11,29 +11,13 @@ namespace MigrateDocumentation { public static class Program { - private class Replacement - { - Replacement(int start, int length, string value) - { - Start = start; - Length = length; - Value = value; - } - - public int Start { get; } - - public int Length { get; } - - public string Value { get; } - } - public static void Main() { DirectoryInfo solutionFolder = GetSolutionFolder(); DirectoryInfo docsFolder = new DirectoryInfo(Path.Combine(solutionFolder.FullName, "docs")); Environment.CurrentDirectory = docsFolder.FullName; - ISet fileNames = new HashSet(); + IDictionary nameToFile = new Dictionary(); IEnumerable docFiles = docsFolder.GetFiles().ToList(); foreach (FileInfo docFile in docFiles) @@ -47,7 +31,8 @@ public static void Main() } int dot = newName.LastIndexOf('.'); - fileNames.Add(newName.Substring(0, dot)); + string key = newName.Substring(dot) == ".md" ? newName.Substring(0, dot) : newName; + nameToFile.Add(key, newName); } docFiles = docsFolder.GetFiles(); @@ -73,10 +58,10 @@ public static void Main() string innerValue = match.Value.Substring(1, match.Length - 2); string link = innerValue; string newName = TransformName(link); - if (fileNames.Contains(newName)) + if (nameToFile.TryGetValue(newName, out var fileName)) { - Console.WriteLine(newName); - sb.Append(newName).Append(')'); + Console.WriteLine(fileName); + sb.Append(fileName).Append(')'); } else { diff --git a/docs/Appendix-A-TextEdit-Command-Index.md b/docs/Appendix-A-TextEdit-Command-Index.md index 750405f..150fb72 100644 --- a/docs/Appendix-A-TextEdit-Command-Index.md +++ b/docs/Appendix-A-TextEdit-Command-Index.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: The End of the Road](Chapter-21-The-End-of-the-Road) — [Next: Bibliography and Recommended Reading »](Appendix-B-Bibliography-and-Recommended-Reading) +[« Previous: The End of the Road](Chapter-21-The-End-of-the-Road.md) — [Next: Bibliography and Recommended Reading »](Appendix-B-Bibliography-and-Recommended-Reading.md) # Appendix A: TextEdit Command Index || Command || Description || Location || Accelerator || diff --git a/docs/Appendix-B-Bibliography-and-Recommended-Reading.md b/docs/Appendix-B-Bibliography-and-Recommended-Reading.md index 284401b..1b43320 100644 --- a/docs/Appendix-B-Bibliography-and-Recommended-Reading.md +++ b/docs/Appendix-B-Bibliography-and-Recommended-Reading.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: TextEdit Command Index](Appendix-A-TextEdit-Command-Index) +[« Previous: TextEdit Command Index](Appendix-A-TextEdit-Command-Index.md) # Appendix B: Bibliography and Recommended Reading || _2008 update: Some of these recommendations are a bit outdated. I'll update this page when I get some spare time._ || diff --git a/docs/Chapter-1-The-Road-Ahead.md b/docs/Chapter-1-The-Road-Ahead.md index 96a76f3..fc9c690 100644 --- a/docs/Chapter-1-The-Road-Ahead.md +++ b/docs/Chapter-1-The-Road-Ahead.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Introduction](Introduction) — [Next: Designing for Users »](Chapter-2-Designing-for-Users) +[« Previous: Introduction](Introduction.md) — [Next: Designing for Users »](Chapter-2-Designing-for-Users.md) # Chapter 1: The Road Ahead This book is the story of a Windows application. I considered several alternatives for this application, and eventually landed on TextEdit, a Notepad replacement with a twist in the usability department. This chapter explains the how, the why and the wherefore. diff --git a/docs/Chapter-10-Customization-and-Persistence.md b/docs/Chapter-10-Customization-and-Persistence.md index cd87b10..5182ca9 100644 --- a/docs/Chapter-10-Customization-and-Persistence.md +++ b/docs/Chapter-10-Customization-and-Persistence.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: The Main Window](Chapter-9-The-Main-Window) — [Next: Wait a Moment »](Chapter-11-Wait-a-Moment) +[« Previous: The Main Window](Chapter-9-The-Main-Window.md) — [Next: Wait a Moment »](Chapter-11-Wait-a-Moment.md) # Chapter 10: Customization and Persistence Customization and persistence are closely linked. If J. Random Hacker’s customization settings aren’t preserved between sessions, she’ll lose interest very quickly. @@ -14,7 +14,7 @@ Before we look at TextEdit-specific customization, let’s look at some of the t Figure 12 shows the Appearance tab of the Display Control Panel applet. This dialog allows you to change colors, fonts and various metrics such as border widths. -![](Chapter 10 — Customization and Persistence_Figure12.bmp) +![](Chapter-10-Customization-and-Persistence-Figure12.bmp) **Figure 12: Customizing the Appearance of Windows.** Check out GetSystemMetrics and GetSysColor before deciding on colors, fonts and metrics for your application. @@ -50,7 +50,7 @@ Standard APIs to retrieve the various UI fonts would be appreciated. This could The Windows Explorer, too, allows itself to be customized, and some of these customizations afflict – er, affect – TextEdit. -![](Chapter 10 — Customization and Persistence_Figure13.bmp) +![](Chapter-10-Customization-and-Persistence-Figure13.bmp) **Figure 13: Customizing the Windows Explorer.** Some of these settings are useful to applications; unfortunately, there aren’t always documented ways to retrieve them. diff --git a/docs/Chapter-11-Wait-a-Moment.md b/docs/Chapter-11-Wait-a-Moment.md index 2ae2046..30e8cc1 100644 --- a/docs/Chapter-11-Wait-a-Moment.md +++ b/docs/Chapter-11-Wait-a-Moment.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Customization and Persistence](Chapter-10-Customization-and-Persistence) — [Next: File I/O »](Chapter-12-File-I-O) +[« Previous: Customization and Persistence](Chapter-10-Customization-and-Persistence.md) — [Next: File I/O »](Chapter-12-File-I-O.md) # Chapter 11: Wait a Moment Before I get into potentially time-consuming operations such as File I/O and printing, I’ll digress into the subject of the wait cursor. I’ll describe a problem with the typical implementation, and discuss enhancements to the standard hourglass. diff --git a/docs/Chapter-12-File-I-O.md b/docs/Chapter-12-File-I-O.md index 6f4e07e..55a2ce7 100644 --- a/docs/Chapter-12-File-I-O.md +++ b/docs/Chapter-12-File-I-O.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Wait a Moment](Chapter-11-Wait-a-Moment) — [Next: About Dialogs »](Chapter-13-About-Dialogs) +[« Previous: Wait a Moment](Chapter-11-Wait-a-Moment.md) — [Next: About Dialogs »](Chapter-13-About-Dialogs.md) # Chapter 12: File I/O Figure 14 gives the highlights of how TextEdit handles files. On opening the file sample.txt, TextEdit immediately creates a copy of the file. In the figure, this copy is labeled “original copy of sample.txt,” but in fact, the name is a pseudo-garbage string generated by GetTempFileName, for example “te0123.tmp.” diff --git a/docs/Chapter-13-About-Dialogs.md b/docs/Chapter-13-About-Dialogs.md index e4b12b3..9c519cd 100644 --- a/docs/Chapter-13-About-Dialogs.md +++ b/docs/Chapter-13-About-Dialogs.md @@ -1,8 +1,8 @@ ### Programming Industrial Strength Windows -[« Previous: File I/O](Chapter-12-File-I-O) — [Next: File Management »](Chapter-14-File-Management) +[« Previous: File I/O](Chapter-12-File-I-O.md) — [Next: File Management »](Chapter-14-File-Management.md) # Chapter 13: About Dialogs -The logical continuation of the TextEdit story is really Chapter 13, File Management. That subject, however, involves dialog boxes. Let’s ease into the subject of dialog boxes through some easy ones, such as the About dialog and the Options dialog (and defer file management to [Chapter 14](Chapter-14-File-Management)). +The logical continuation of the TextEdit story is really Chapter 13, File Management. That subject, however, involves dialog boxes. Let’s ease into the subject of dialog boxes through some easy ones, such as the About dialog and the Options dialog (and defer file management to [Chapter 14](Chapter-14-File-Management.md)). ## What is a Dialog Box, Anyway? @@ -82,7 +82,7 @@ The “About TextEdit” dialog box is about as simple as they come. The only co The only possible interaction is to dismiss the dialog, which is why I call it simple in spite of the rather extensive initialization. -![](Chapter 13 — About Dialogs_Figure15.bmp) +![](Chapter-13-About-Dialogs-Figure15.bmp) **Figure 15: The About Dialog.** Some STATIC widgets have been subjected to a WM{"_"}SETFONT message, while others have been subclassed. @@ -98,7 +98,7 @@ More interesting is the boldfacing of individual words in the IDC{"_"}COMMENTS a The Options dialog box looks like this: -![](Chapter 13 — About Dialogs_Figure16.bmp) +![](Chapter-13-About-Dialogs-Figure16.bmp) **Figure 16: The Options Dialog.** The icons on the left are illustrative only; they do not reflect state in any way. @@ -166,6 +166,6 @@ What happens if we disable the IDC{"_"}APPLY button, but omit the gotoDlgItem( I One of the possible flag parameters to the MessageBox function is MB{"_"}NOFOCUS, which ensures that no button has the initial focus. This is useful if you want to protect the MessageBox against accidental dismissal. To create a really obnoxious dialog box, let it respond to all WM{"_"}COMMAND messages with SetFocus( 0 ). -The most complex examples of dialog interaction that TextEdit has to offer are the Find and Replace dialogs, described in [Chapter 15](Chapter-15-Search-and-Replace). +The most complex examples of dialog interaction that TextEdit has to offer are the Find and Replace dialogs, described in [Chapter 15](Chapter-15-Search-and-Replace.md). [Sidebar: Default Buttons and Multi-line Edit](Sidebar_-Default-Buttons-and-Multi-line-Edit) diff --git a/docs/Chapter-14-File-Management.md b/docs/Chapter-14-File-Management.md index 35ad7b1..81c00a7 100644 --- a/docs/Chapter-14-File-Management.md +++ b/docs/Chapter-14-File-Management.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: File Management](Chapter-13-About-Dialogs) — [Next: Search and Replace »](Chapter-15-Search-and-Replace) +[« Previous: File Management](Chapter-13-About-Dialogs.md) — [Next: Search and Replace »](Chapter-15-Search-and-Replace.md) # Chapter 14: File Management File management in the context of TextEdit is the management of a single file. It includes the ability to change file attributes such as the read-only flag, it includes renaming and repositioning of the file, and it includes deleting the file (and, incidentally, closing TextEdit). @@ -12,13 +12,13 @@ TextEdit also manages properties such as “Unicode.” TextEdit detects whether The Properties dialog displays information about the currently loaded file: File name, location, file type, file size, time stamps, file attributes, Unicode and line separators. The layout of this dialog is similar to the Windows Explorer’s Properties dialog (see Figure 17). -![](Chapter 14 — File Management_Figure17.bmp) +![](Chapter-14-File-Management-Figure17.bmp) **Figure 17: The Properties Dialog.** It is similar to the Exlorer’s corresponding dialog. The dialog lets you change some of the attributes displayed in the dialog. You can change the file name on the fly, by typing a different name in the File Name field. To move the file to a different location, you must press the Move buttons to invoke a second dialog box (Figure 18); the Location field is read-only. This offloads everything to do with directories onto a common dialog designed for the purpose, and avoids issues of how to handle non-existent directories, invalid path names and so forth. A better solution would be one that allowed both approaches. -![](Chapter 14 — File Management_Figure18.bmp) +![](Chapter-14-File-Management-Figure18.bmp) **Figure 18: Move or Rename File Dialog.** This is really a Save As dialog, with extra information on the top. @@ -45,7 +45,7 @@ TextEdit’s Delete command deletes the current file. Since the unified file mod The Delete command may or may not open the confirmation dialog shown in Figure 19. The ShowDeleteDialog registry variable defined in persistence.h controls this. The user, in turn, controls the registry variable. You can turn it off by unchecking the lower checkbox in Figure 19 (the one labeled “Show this dialog the next time you delete a file”). For obvious reasons, you can’t turn it back on using the same checkbox. To prevent the user from getting lost, the dialog explains how you can turn it back on. (Note how the functional part of the “confirm file delete” confirmation dialog stops at the horizontal line – what’s below is concerned with management of the dialog itself, and has nothing to do with deleting files.) -![](Chapter 14 — File Management_Figure19.bmp) +![](Chapter-14-File-Management-Figure19.bmp) **Figure 19: The Delete File Dialog.** The upper icon is static and helps identify the dialog; the trash can icon is dynamic and changes according to the setting of its corresponding checkbox. @@ -84,13 +84,13 @@ The icon serves as a visual reinforcement of the setting of the checkbox. In add The Open File and Save File common dialogs are little Explorers in their own right. Figure 20 shows TextEdit’s Open File dialog in action. As you can see, it has four extra controls – one static label, one edit control used to show a preview of the selected file, one icon to show the type of the selected file and one checkbox that lets you open the file in a new window. -![](Chapter 14 — File Management_Figure20.bmp) +![](Chapter-14-File-Management-Figure20.bmp) **Figure 20: The Open File Dialog.** The extra controls on the right come from the dialog template IDD{"_"}PREVIEW{"_"}CHILD. You change the look of most common dialogs by specifying a resource template that replaces the default dialog. The Open and Save dialogs are exceptions; you specify, instead, the template of a child dialog that is added to the system-supplied dialog. The template must have the WS{"_"}CHILD style bit set, and it should include a static control with the ID stc32. This is a placeholder for the system-supplied dialog, and tells GetOpenFileName and GetSaveFileName how to place the child dialog in relation to predefined controls. Figure 21 shows the child dialog (IDD{"_"}PREVIEW{"_"}CHILD); its relationship to Figure 20 should be clear. -![](Chapter 14 — File Management_Figure21.bmp) +![](Chapter-14-File-Management-Figure21.bmp) **Figure 21: The Open File Child Dialog.** The STATIC control labeled stc32 is a placeholder for the standard contents of the Open File dialog. diff --git a/docs/Chapter-15-Search-and-Replace.md b/docs/Chapter-15-Search-and-Replace.md index 801f76e..e0d6cbf 100644 --- a/docs/Chapter-15-Search-and-Replace.md +++ b/docs/Chapter-15-Search-and-Replace.md @@ -1,16 +1,16 @@ ### Programming Industrial Strength Windows -[« Previous: File Management](Chapter-14-File-Management) — [Next: Printing »](Chapter-16-Printing) +[« Previous: File Management](Chapter-14-File-Management.md) — [Next: Printing »](Chapter-16-Printing.md) # Chapter 15: Search and Replace Windows offers a common dialog for straight searching and for search and replace. I have a strong dislike for this dialog. I dislike the modelessness of it, I dislike the simple edit field for the search string, and I dislike the dim-witted way it paints a default border on a disabled button (see Figure 22). Above all, I dislike the API, which is an invitation to spread related functionality around all the dark corners of a program. -![](Chapter 15 — Search and Replace_Figure22.bmp) +![](Chapter-15-Search-and-Replace-Figure22.bmp) **Figure 22: The Common Find Dialog.** Note the disabled default button, and cringe. Given such strong feelings, you won’t be surprised when I tell you that TextEdit doesn’t use the common dialog for search and replace. You can see TextEdit’s Find dialog, implemented by the class FindDlg, in Figure 23. It looks quite similar to the common dialog, but there are differences more than skin deep. -![](Chapter 15 — Search and Replace_Figure23.bmp) +![](Chapter-15-Search-and-Replace-Figure23.bmp) **Figure 23: The TextEdit Find Dialog.** Although the presence of the drop-down list is the most obvious difference from the previous dialog, some of the less obvious differences are much more important. @@ -32,7 +32,7 @@ One solution to this user interface glitch would be to catch the Enter key and a Actually implementing this functionality was more of a puzzle than I had expected, chiefly because the combobox notifications are peculiar. The CBN{"_"}DROPDOWN notification is sent before the list opens, while its opposite number, the CBN{"_"}CLOSEUP notification, is sent after the list has closed. In other words, the list is always closed at notification time. This precludes an elegant, common solution for all cases, in which I wouldn’t care whether the message was CBN{"_"}DROPDOWN or CBN{"_"}CLOSEUP. Instead, I would just ask the combobox by sending it the CB{"_"}GETDROPPEDSTATE message (using the ComboBox{"_"}GetDroppedState macro from windowsx.h). -At this point, it occurred to me that this problem is not specific to FindDlg, but completely general. I removed all this code from FindDlg, and instead used global subclassing (as described in [Chapter 4](Chapter-4-The-Mechanics-of-Subclassing)) to subclass the dialog window class. The result is in dlgSubclasser.cpp, and has a couple of interesting properties: +At this point, it occurred to me that this problem is not specific to FindDlg, but completely general. I removed all this code from FindDlg, and instead used global subclassing (as described in [Chapter 4](Chapter-4-The-Mechanics-of-Subclassing.md)) to subclass the dialog window class. The result is in dlgSubclasser.cpp, and has a couple of interesting properties: * No header file is associated with this file; it has, in a manner of speaking, no interface. The mere existence of the dlgSubclasser static variable is enough to initialize the subclassing. * The subclassing works on all dialogs within TextEdit, including “system” dialogs such as printer properties. @@ -55,7 +55,7 @@ As for all other dialogs, Dialog::dispatchDlgMsg takes care of the initial place FindDlg has a memory. We’ve already seen how it remembers its position; it also remembers the ten most recently used search strings, the status of the “Match whole word only” and “Match case” checkboxes, and the search direction (up or down). -The list of recently used search strings is read from the registry by the loadStrings method and saved to the registry by the saveStrings method. This “historical combobox” has a close kinship with the list of recently used files discussed in [Chapter 10](Chapter-10-Customization-and-Persistence), but is actually simpler in its implementation. How so? In addition to being a GUI component, a drop-down list box (or any list box, for that matter) can also be thought of as part of your data structure. Not only can you put strings into it; you can get them out again as well. Here’s another design principle: +The list of recently used search strings is read from the registry by the loadStrings method and saved to the registry by the saveStrings method. This “historical combobox” has a close kinship with the list of recently used files discussed in [Chapter 10](Chapter-10-Customization-and-Persistence.md), but is actually simpler in its implementation. How so? In addition to being a GUI component, a drop-down list box (or any list box, for that matter) can also be thought of as part of your data structure. Not only can you put strings into it; you can get them out again as well. Here’s another design principle: **“Don’t duplicate data storage.”** @@ -69,21 +69,21 @@ One final detail, while I’m on the subject of the combobox: The CB{"_"}FINDSTR When Notepad fails to find the text you’re searching for, it displays a message box, as depicted in Figure 24. Notepad is in good company using a message box for this; others include Word for Windows (Figure 25) and Visual {"C++"} (Figure 26). -![](Chapter 15 — Search and Replace_Figure24.bmp) +![](Chapter-15-Search-and-Replace-Figure24.bmp) **Figure 24: Notepad didn’t find “Glory Hallelujah!”** -![](Chapter 15 — Search and Replace_Figure25.bmp) +![](Chapter-15-Search-and-Replace-Figure25.bmp) **Figure 25: Microsoft Word fails to find “Glory Hallelujah!”** The message box doesn’t tell you what Word failed to find. -![](Chapter 15 — Search and Replace_Figure26.bmp) +![](Chapter-15-Search-and-Replace-Figure26.bmp) **Figure 26: Visual {"C++"} fares no better.** These message boxes are perfect examples of what Alan Cooper terms _excise_, user interface elements that contribute nothing towards fulfilling the user’s goals. If a message box were the only way the program could possibly communicate the failure of the search, we would have to accept this excise as necessary. It isn’t, though. TextEdit displays the information in the search dialog itself, as depicted in Figure 27. -![](Chapter 15 — Search and Replace_Figure27.bmp) +![](Chapter-15-Search-and-Replace-Figure27.bmp) *Figure 27: Glory be! TextEdit can’t find “Glory Hallelujah!” either. @@ -105,13 +105,13 @@ I decided to use the same dialog function for these two dialogs on the assumptio Before I describe the TextEdit Replace dialog, I’d like to discuss its counterpart in Visual {"C++"}. I investigated this dialog quite thoroughly in preparation for my own design, and was left with a surreal feeling of having visited a Salvador Dali landscape, where the normal laws of logic don’t apply. -![](Chapter 15 — Search and Replace_Figure28.bmp) +![](Chapter-15-Search-and-Replace-Figure28.bmp) **Figure 28: The Visual {"C++"} Replace dialog without “iString” selected in the text window.** Since “iString” is not selected, Find Next is the default. No replacement is even possible, and if you click on Replace, it will do a Find Next, in spite of its label. Figure 28 shows the V{"C++"} Replace dialog in action. At this point, the Find Next button is the default button, and no text is selected in the editor. If I hit return, the first occurrence of “iString” will be selected in the editor, and the Replace button becomes the default button, as depicted in Figure 29. -![](Chapter 15 — Search and Replace_Figure29.bmp) +![](Chapter-15-Search-and-Replace-Figure29.bmp) **Figure 29: The Visual {"C++"} Replace dialog with “iString” selected in the text window.** The Replace button is now the default. @@ -131,19 +131,19 @@ The TextEdit Replace dialog is shown in Figure 30. It bears a passing resemblanc In Figure 30, the text “Pocket” is not selected in the editor. Thus, no replacement is possible, and the Replace button is disabled. -![](Chapter 15 — Search and Replace_Figure30.bmp) +![](Chapter-15-Search-and-Replace-Figure30.bmp) **Figure 30: The TextEdit Replace dialog without “Pocket” selected in the edit widget.** In contrast to the Visual {"C++"} dialog in Figure 28, the Replace button is disabled. In Figure 31, the user has hit Find Next, and the text “Pocket” has been selected in the editor. The Replace button has been enabled, and it has become the default button as well. The TextEdit Replace button, by the way, has an implicit Find Next built into it, just like Visual {"C++"}. Since we now have a selection, the “Replace in Selection” radio button has been enabled. -![](Chapter 15 — Search and Replace_Figure31.bmp) +![](Chapter-15-Search-and-Replace-Figure31.bmp) **Figure 31: The TextEdit Replace dialog with “Pocket” selected in the edit widget.** Its behavior now equals that of the Visual {"C++"} dialog in Figure 29. In Figure 32, the user has checked “Replace in Selection.” In this case, Replace All is the only available action. -![](Chapter 15 — Search and Replace_Figure32.bmp) +![](Chapter-15-Search-and-Replace-Figure32.bmp) **Figure 32: The TextEdit Replace dialog with “Replace in Selection” selected**. Replace All is the only possible action. diff --git a/docs/Chapter-16-Printing.md b/docs/Chapter-16-Printing.md index 2fbe049..d8ec69a 100644 --- a/docs/Chapter-16-Printing.md +++ b/docs/Chapter-16-Printing.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Search and Replace](Chapter-15-Search-and-Replace) — [Next: Changing Fonts »](Chapter-17-Changing-Fonts) +[« Previous: Search and Replace](Chapter-15-Search-and-Replace.md) — [Next: Changing Fonts »](Chapter-17-Changing-Fonts.md) # Chapter 16: Printing In one sense, printing under Windows is similar to displaying stuff on the screen: You use GDI commands to draw text and graphics in a display context. You don’t obtain (or release) a printer display context the same way you obtain a screen display context, but once you have that display context, you use the same familiar set of GDI functions. @@ -35,7 +35,7 @@ TextEdit uses the standard common dialog for page setup. The setupPage function You invoke the standard page setup dialog by calling PageSetupDlg with a pointer to a suitably initialized PAGESETUPDLG as its lone parameter. The result looks like Figure 33. -![](Chapter 16 — Printing_Figure32.bmp) +![](Chapter-16-Printing-Figure32.bmp) **Figure 33: The Page Setup Dialog Box.** @@ -49,7 +49,7 @@ TextEdit uses the standard common dialog for printing. The printFile function is You invoke the standard print dialog by calling PrintDlg with a pointer to a suitably initialized PRINTDLG as its lone parameter. The result looks like Figure 34. -![](Chapter 16 — Printing_Figure32.bmp) +![](Chapter-16-Printing-Figure32.bmp) **Figure 34: The Print Dialog Box.** diff --git a/docs/Chapter-17-Changing-Fonts.md b/docs/Chapter-17-Changing-Fonts.md index af3aa5b..dddd791 100644 --- a/docs/Chapter-17-Changing-Fonts.md +++ b/docs/Chapter-17-Changing-Fonts.md @@ -1,12 +1,12 @@ ### Programming Industrial Strength Windows -[« Previous: Printing](Chapter-16-Printing) — [Next: Going Abroad »](Chapter-18-Going-Abroad) +[« Previous: Printing](Chapter-16-Printing.md) — [Next: Going Abroad »](Chapter-18-Going-Abroad.md) # Chapter 17: Changing Fonts TextEdit allows the user to select one proportional font and one fixed-width font. These selections are global across all instances of TextEdit, but it is quick to switch between proportional and fixed-width font, and the selected font is retained for individual files and for file types. The TextEdit Font Dialog is an example of implementation problems overpowering user requirements, a problem I talked about in Chapter 2. My original plan called for a single dialog for font customization, looking something like Figure 35: -![](Chapter 17 — Changing Fonts_Figure35.bmp) +![](Chapter-17-Changing-Fonts-Figure35.bmp) **Figure 35: The Font dialog that never was.** Is there a bug in WM_CHOOSEFONT_SETLOGFONT, or am I all thumbs? diff --git a/docs/Chapter-18-Going-Abroad.md b/docs/Chapter-18-Going-Abroad.md index 9c7e5d8..55fdc60 100644 --- a/docs/Chapter-18-Going-Abroad.md +++ b/docs/Chapter-18-Going-Abroad.md @@ -1,22 +1,22 @@ ### Programming Industrial Strength Windows -[« Previous: Changing Fonts](Chapter-17-Changing-Fonts) — [Next: Meanwhile, in the Background »](Chapter-19-Meanwhile-in-the-Background) +[« Previous: Changing Fonts](Chapter-17-Changing-Fonts.md) — [Next: Meanwhile, in the Background »](Chapter-19-Meanwhile-in-the-Background.md) # Chapter 18: Going Abroad Even though I’m running the US edition of Windows NT 4 Workstation, I can nevertheless create files with Greek names; my file system is NTFS, so file names are Unicode. The question is – can I display those file names? The answer is – it depends. -![](Chapter 18 — Going Abroad_Figure36.bmp) +![](Chapter-18-Going-Abroad-Figure36.bmp) **Figure 36: Γρεεκ Φιλε.log (Greek File.log – English written using the Greek alphabet. An even Greeker file name would be Εκθεσι Ελληνικον.log.)** The file name is Unicode, the program is Unicode and the Unicode title font contains the required Greek characters. Figure 36 shows a screen from a Unicode build of TextEdit, using a font (Tahoma) that contains the Greek Unicode characters (0x0370–0x03cf). In Figure 37, I’ve switched to MS Sans Serif, which does not, and the Greek characters can’t be displayed. A default character – a black rectangle – is displayed instead. It would be a different matter if Greek were installed as the system default language. In that case, a different code page of MS Sans Serif would be installed, and character codes between 128 and 255 would be used to display the Greek characters, even though the file name characters are actually from the Greek Unicode page. The Unicode character code for upper-case alpha, for example, is 0x0391; it obviously can’t be represented in an 8-bit code. -![](Chapter 18 — Going Abroad_Figure37.bmp) +![](Chapter-18-Going-Abroad-Figure37.bmp) **Figure 37: A Truly Greek File Name.** (Apologies to all Greeks. This is Chinese to you, of course.). In this case, the problem lies with the MS Sans Serif font. Figure 38 shows a Tahoma menu. Note item 2, a beautiful rendition of a Greek file name. Even more interesting are items 5 and 6, leftovers from an ANSI build. They show how difficult life can be for an ANSI application on a Unicode file system. The WideCharToMultiByte function has mapped the Gamma, Epsilon and Phi characters with a modicum of success. The rest were deemed untranslatable, and thus replaced by the default character. Since I didn’t specify a default character, the default default character was used, and, since this doubly default character is a question mark, the file name is more than merely wrong: The question mark is a wild-card character, so the file name is illegal. -![](Chapter 18 — Going Abroad_Figure38.bmp) +![](Chapter-18-Going-Abroad-Figure38.bmp) **Figure 38: Tahoma Menu in Unicode Build.** Items five and six show how badly Unicode-to-ANSI translations can screw things up. diff --git a/docs/Chapter-19-Meanwhile-in-the-Background.md b/docs/Chapter-19-Meanwhile-in-the-Background.md index b61f89e..e6584b9 100644 --- a/docs/Chapter-19-Meanwhile-in-the-Background.md +++ b/docs/Chapter-19-Meanwhile-in-the-Background.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Going Abroad](Chapter-18-Going-Abroad) — [Next: Setup, and Down Again »](Chapter-20-Setup-and-Down-Again) +[« Previous: Going Abroad](Chapter-18-Going-Abroad.md) — [Next: Setup, and Down Again »](Chapter-20-Setup-and-Down-Again.md) # Chapter 19: Meanwhile, in the Background Multi-threading is used for many different purposes. In a server application, a typical purpose is to service multiple requests in parallel, while in a client application, a typical purpose is to perform background processing while keeping the user interface responsive. diff --git a/docs/Chapter-2-Designing-for-Users.md b/docs/Chapter-2-Designing-for-Users.md index a5dcdb8..e5c94d7 100644 --- a/docs/Chapter-2-Designing-for-Users.md +++ b/docs/Chapter-2-Designing-for-Users.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: The Road Ahead](Chapter-1-The-Road-Ahead) — [Next: Designing for Programmers »](Chapter-3-Designing-for-Programmers) +[« Previous: The Road Ahead](Chapter-1-The-Road-Ahead.md) — [Next: Designing for Programmers »](Chapter-3-Designing-for-Programmers.md) # Chapter 2: Designing for Users From the Unix world comes a text editor named **vi**. It’s powerful and fast – provided you know how to use it. The problem with vi is that it is difficult to learn. A host of keyboard commands must be learned by heart – the user interface doesn’t give you a clue as to what you can and can’t do. The problem is compounded by vi’s several modes – it has different modes for text insertion and text manipulation, for example. The modes are in themselves no disaster, but their invisibility is. Nothing indicates whether your keystrokes will be interpreted as text to be inserted or commands to be executed. @@ -43,11 +43,11 @@ Some message boxes are just plain unnecessary. TextEdit uses the status bar to d The status bar has one big problem in this role: Most people don’t pay it much attention. To remedy this problem, TextEdit’s status bar displays highlighted text whenever it has something substantial to say (as shown in Figure 1). -![](Chapter 2 — Designing for Users_Figure1.bmp) +![](Chapter-2-Designing-for-Users-Figure1.bmp) **Figure 1: Status bar with a message.** Highlighting makes the user pay attention. -In [Chapter 15](Chapter-15-Search-and-Replace), I’ll show you how to do away with message boxes in connection with search and replace. +In [Chapter 15](Chapter-15-Search-and-Replace.md), I’ll show you how to do away with message boxes in connection with search and replace. ## Robustness @@ -66,7 +66,7 @@ First, you need to know the following about TextEdit: If the user opens the properties dialog, changes the file extension from .txt to .cpp and clicks the Apply button, the icon on the dialog should change (see Figure 2). In addition, the textual type description should change, the dialog title should change, and the time stamp of last file access should change. -![](Chapter 2 — Designing for Users_Figure2.bmp) +![](Chapter-2-Designing-for-Users-Figure2.bmp) **Figure 2: TextEdit displays different icons for different file types.** diff --git a/docs/Chapter-20-Setup-and-Down-Again.md b/docs/Chapter-20-Setup-and-Down-Again.md index 8c319e9..ef36406 100644 --- a/docs/Chapter-20-Setup-and-Down-Again.md +++ b/docs/Chapter-20-Setup-and-Down-Again.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Meanwhile, in the Background](Chapter-19-Meanwhile-in-the-Background) — [Next: The End of the Road »](Chapter-21-The-End-of-the-Road) +[« Previous: Meanwhile, in the Background](Chapter-19-Meanwhile-in-the-Background.md) — [Next: The End of the Road »](Chapter-21-The-End-of-the-Road.md) # Chapter 20: Setup, and Down Again Installation and setup of TextEdit is less of a chore than installation and setup of, say, Microsoft Office. TextEdit is distributed as a single file, rather than umpteen zillion. Still, a number of issues must be dealt with, including version control, registry entries, shortcuts to the application and how to uninstall cleanly. @@ -10,7 +10,7 @@ The TextEdit installation is hand coded, mainly because I want to show you some In its installation incarnation, TextEdit looks like Figure 39 when it starts. -![](Chapter 20 — Setup, and Down Again_Figure39.bmp) +![](Chapter-20-Setup-and-Down-Again-Figure39.bmp) **Figure 39: TextEdit Setup in Action.** This is the standard TextEdit executable, started with the **/setup** switch. @@ -35,7 +35,7 @@ The first thing the setup dialog does is check for a previous installation. If i Invoking the Install button in Figure 39 starts the installation. The first step is customization, handled by InstallDlg1, as shown in Figure 40. -![](Chapter 20 — Setup, and Down Again_Figure40.bmp) +![](Chapter-20-Setup-and-Down-Again-Figure40.bmp) **Figure 40: The Installation dialog.** The check marks in the list are communicated back to SetupDlg through the FileType class. @@ -113,7 +113,7 @@ The user does not know about the /setup switch. How, then, does she invoke unins The currently recommended approach is to use the Add/Remove Programs applet in the Control Panel (see Figure 41). The title of this dialog is passing strange, by the way – why “Properties?” And, when the keyboard focus is in the list of removable software, why isn’t the Add/Remove button the default button? -![](Chapter 20 — Setup, and Down Again_Figure41.bmp) +![](Chapter-20-Setup-and-Down-Again-Figure41.bmp) **Figure 41: The Add/Remove Programs Control Panel Applet.** Given that the keyboard focus is in the list, why isn’t the Add/Remove button the default? Eh? diff --git a/docs/Chapter-21-The-End-of-the-Road.md b/docs/Chapter-21-The-End-of-the-Road.md index 3b22e76..155ebb9 100644 --- a/docs/Chapter-21-The-End-of-the-Road.md +++ b/docs/Chapter-21-The-End-of-the-Road.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Setup, and Down Again](Chapter-20-Setup-and-Down-Again) — [Next: TextEdit Command Index »](Appendix-A-TextEdit-Command-Index) +[« Previous: Setup, and Down Again](Chapter-20-Setup-and-Down-Again.md) — [Next: TextEdit Command Index »](Appendix-A-TextEdit-Command-Index.md) # Chapter 21: The End of the Road This is it. We’ve reached the end of the road; TextEdit is done. At least, version 1 of TextEdit is done. There are many things I’d like to change, and there are many features that I’d like to add. In spite of blemishes and imperfections, however, I think the overall design and implementation of TextEdit illustrate my basic arguments. My intention with this book has not been to present TextEdit as an example of a perfect Windows program, but rather to make you think. diff --git a/docs/Chapter-3-Designing-for-Programmers.md b/docs/Chapter-3-Designing-for-Programmers.md index 424186e..55e1eea 100644 --- a/docs/Chapter-3-Designing-for-Programmers.md +++ b/docs/Chapter-3-Designing-for-Programmers.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Designing for Users](Chapter-2-Designing-for-Users) — [Next: The Mechanics of Subclassing »](Chapter-4-The-Mechanics-of-Subclassing) +[« Previous: Designing for Users](Chapter-2-Designing-for-Users.md) — [Next: The Mechanics of Subclassing »](Chapter-4-The-Mechanics-of-Subclassing.md) # Chapter 3: Designing for Programmers In the previous chapter, I discussed software usability from the user’s point of view. Programmers are users, too, albeit with a different worldview. Programmers, including yourself, are users of your source code. @@ -407,7 +407,7 @@ int WINAPI WinMain( {code:C#} The resulting window lacks even the sense to paint its own client area, but it does have a title bar, and it responds correctly to resizing, maximizing and minimizing (see Figure 3). -![](Chapter 3 — Designing for Programmers_Figure3.bmp) +![](Chapter-3-Designing-for-Programmers-Figure3.bmp) **Figure 3: The DefWindowProc window, with its client area full of garbage.** diff --git a/docs/Chapter-4-The-Mechanics-of-Subclassing.md b/docs/Chapter-4-The-Mechanics-of-Subclassing.md index 58430ea..74e3a55 100644 --- a/docs/Chapter-4-The-Mechanics-of-Subclassing.md +++ b/docs/Chapter-4-The-Mechanics-of-Subclassing.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Designing for Programmers](Chapter-3-Designing-for-Programmers) — [Next: The Bare Bones »](Chapter-5-The-Bare-Bones) +[« Previous: Designing for Programmers](Chapter-3-Designing-for-Programmers.md) — [Next: The Bare Bones »](Chapter-5-The-Bare-Bones.md) # Chapter 4: The Mechanics of Subclassing In an ideal world, at least for C++ programmers, Windows would be C++ throughout. Subclassing a window would be a matter of subclassing a C++ class, creating a window would be a matter of invoking the window’s constructor, message handling would be a matter of overriding virtual functions. @@ -22,7 +22,7 @@ Subclassing comes in several variants: Instance subclassing (a.k.a. local subcla When a dialog’s **WM_INITDIALOG** message handler is invoked, all the edit controls exist already. The InstSub program is a complete example of instance subclassing an edit control to create a numeric input field. The resulting dialog is depicted in Figure 4: -![](Chapter 4 — The Mechanics of Subclassing_Figure4.bmp) +![](Chapter-4-The-Mechanics-of-Subclassing-Figure4.bmp) **Figure 4: Instance Subclassing in Action.** The upper edit field accepts only digits. @@ -262,7 +262,7 @@ int APIENTRY WinMain( HINSTANCE hinst, HINSTANCE, LPSTR, int ) { Thus endeth the subclassing tutorial. That’s all there is to it, really, except for various esoteric techniques used to subclass windows in other processes, which I won’t go into. -The next section presents the code that TextEdit uses to accomplish instance and global subclassing. The code uses other classes that I haven’t described yet. For now, I’ll just use the String and Exception classes without further ado; I’ll go into more detail about them in Chapters [5](Chapter-5-The-Bare-Bones) and [6](Chapter-6-Exceptions). +The next section presents the code that TextEdit uses to accomplish instance and global subclassing. The code uses other classes that I haven’t described yet. For now, I’ll just use the String and Exception classes without further ado; I’ll go into more detail about them in Chapters [5](Chapter-5-The-Bare-Bones.md) and [6](Chapter-6-Exceptions.md). ## General Mechanism for Global Subclassing diff --git a/docs/Chapter-5-The-Bare-Bones.md b/docs/Chapter-5-The-Bare-Bones.md index e0a72d3..5b0d2f3 100644 --- a/docs/Chapter-5-The-Bare-Bones.md +++ b/docs/Chapter-5-The-Bare-Bones.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: The Mechanics of Subclassing](Chapter-4-The-Mechanics-of-Subclassing) — [Next: Exceptions »](Chapter-6-Exceptions) +[« Previous: The Mechanics of Subclassing](Chapter-4-The-Mechanics-of-Subclassing.md) — [Next: Exceptions »](Chapter-6-Exceptions.md) # Chapter 5: The Bare Bones This chapter gives you an overview of the TextEdit application architecture – the skeleton of the application, if you like. But first, this message from our sponsors: @@ -44,7 +44,7 @@ The core of TextEdit consists of one window function and three {"C++"} classes. The relationships between these are shown in Figure 5. -![](Chapter 5 — The Bare Bones_Figure5.bmp) +![](Chapter-5-The-Bare-Bones-Figure5.bmp) **Figure 5: Application Architecture Overview.** diff --git a/docs/Chapter-6-Exceptions.md b/docs/Chapter-6-Exceptions.md index 15f81cc..531cbd1 100644 --- a/docs/Chapter-6-Exceptions.md +++ b/docs/Chapter-6-Exceptions.md @@ -1,12 +1,12 @@ ### Programming Industrial Strength Windows -[« Previous: The Bare Bones](Chapter-5-The-Bare-Bones) — [Next: Off the Launch Pad »](Chapter-7-Off-the-Launch-Pad) +[« Previous: The Bare Bones](Chapter-5-The-Bare-Bones.md) — [Next: Off the Launch Pad »](Chapter-7-Off-the-Launch-Pad.md) # Chapter 6: Exceptions When your application calls a function, there’s always a chance that the function fails to carry out its assigned duties. Possible causes are multifarious – a file was not found, a network file server crashed, the system could not allocate memory, a computation overflowed, the system is corrupt, your application is corrupt, the government is corrupt – the list is endless. The occasional failure is unavoidable. Failing gracefully is, however, infinitely preferable to falling flat on your face. -Sometimes you don’t care if a function failed. Perhaps it wasn’t terribly important, perhaps the function has already reported the problem to the user, or perhaps no reasonable course of action exists. The WaitCursor class (see [Chapter 11](Chapter-11-Wait-a-Moment)) is an example of no-fail software. Its methods don’t need to communicate success or failure to the caller, because the caller doesn’t care one way or another. +Sometimes you don’t care if a function failed. Perhaps it wasn’t terribly important, perhaps the function has already reported the problem to the user, or perhaps no reasonable course of action exists. The WaitCursor class (see [Chapter 11](Chapter-11-Wait-a-Moment.md)) is an example of no-fail software. Its methods don’t need to communicate success or failure to the caller, because the caller doesn’t care one way or another. Other times, you do care, if for no other reason that you must tell the user that you failed to print his file. Failure can be reported through two basic mechanisms: return codes and exceptions. From modern computer literature, one often gets the impression that exceptions are in some way “better” than return codes, but that distinction is meaningless. The goal is to reduce total complexity to a minimum. Often enough, exceptions support that goal best, but by no means always. diff --git a/docs/Chapter-7-Off-the-Launch-Pad.md b/docs/Chapter-7-Off-the-Launch-Pad.md index 231ab05..7831767 100644 --- a/docs/Chapter-7-Off-the-Launch-Pad.md +++ b/docs/Chapter-7-Off-the-Launch-Pad.md @@ -1,8 +1,8 @@ ### Programming Industrial Strength Windows -[« Previous: Exceptions](Chapter-6-Exceptions) — [Next: Child Windows »](Chapter-8-Child-Windows) +[« Previous: Exceptions](Chapter-6-Exceptions.md) — [Next: Child Windows »](Chapter-8-Child-Windows.md) # Chapter 7: Off the Launch Pad -As with skinning a cat, there is more than one way to start a Win32 app­li­ca­t­ion. There are GUI ways and there are console ways; some of them have to do with shell integration, a con­cept that is also touched in [Chapter 20, Setup](Chapter-20-Setup-and-Down-Again). +As with skinning a cat, there is more than one way to start a Win32 app­li­ca­t­ion. There are GUI ways and there are console ways; some of them have to do with shell integration, a con­cept that is also touched in [Chapter 20, Setup](Chapter-20-Setup-and-Down-Again.md). **Listing 24: Exploring the Command Line** @@ -30,7 +30,7 @@ You can also drag multiple files onto the TextEdit icon. This is where it starts {{ **c:\sample1.txt c:\sample2.txt** }} -![](Chapter 7 — Off the Launch Pad_Figure6.bmp) +![](Chapter-7-Off-the-Launch-Pad-Figure6.bmp) **Figure 6: Notepad in Action.** @@ -44,7 +44,7 @@ The problem here appears to be the second colon, which makes the file name synta {{ notepad sample1.txt sample2.txt }} -![](Chapter 7 — Off the Launch Pad_Figure7.bmp) +![](Chapter-7-Off-the-Launch-Pad-Figure7.bmp) **Figure 7: Notepad in Action again.** @@ -174,7 +174,7 @@ Neverthe­less, one par­ti­cu­lar kind of file does require spe­cial treat­ This is all handled by the func­tion resolveName (see resolveName.cpp); its job is to figure out if the file is a link, and if so, to figure out which file the link references. All files pass through resolveName; the special handling is hidden on the inside. The in­side, by the way, uses the IShellLink COM in­ter­fa­ce to resolve the link. -Resolving links is an issue with the Open common dia­log as well. This dia­log is dis­cus­sed in Chapter 14, [File Management](Chapter-14-File-Management). +Resolving links is an issue with the Open common dia­log as well. This dia­log is dis­cus­sed in Chapter 14, [File Management](Chapter-14-File-Management.md). Consider the following command line: @@ -187,7 +187,7 @@ Handling all possible variations in a reasonable way requires unreasonable con­ ## File Not Found -![](Chapter 7 — Off the Launch Pad_Figure8.bmp) +![](Chapter-7-Off-the-Launch-Pad-Figure8.bmp) Figure 8: TextEdit can’t find a file. @@ -198,14 +198,14 @@ What if a file doesn’t exist? There are several ways to handle this, and Notep * Exit TextEdit. * If the file name contains wildcard characters, the pro­ce­du­re is slightly dif­fe­rent, as you can’t create a file with wildcard characters in the file name. TextEdit explains that no matching files where found, and goes on to explain what a wildcard character actually is. -![](Chapter 7 — Off the Launch Pad_Figure9.bmp) +![](Chapter-7-Off-the-Launch-Pad-Figure9.bmp) **Figure 9: No files match a wild­card pat­tern.** Since some users will be unfamiliar with wildcards, the mes­sage box explains the con­cept. The explanation is not so intrusive as to bother power users. From there, the choices are as above, except that creating the file as named is obviously out of the question. -Even if a file does exist, there are potential problems. The user may have limited access rights, or per­haps the file has been locked by a dif­fe­rent app­li­ca­tion. [Chapter 12 (File I/O](Chapter-12-File-I-O)) deals with this. +Even if a file does exist, there are potential problems. The user may have limited access rights, or per­haps the file has been locked by a dif­fe­rent app­li­ca­tion. [Chapter 12 (File I/O](Chapter-12-File-I-O.md)) deals with this. ## Read Only A file can be read-only in many ways, some more permanent than others: * The read-only file attribute is set diff --git a/docs/Chapter-8-Child-Windows.md b/docs/Chapter-8-Child-Windows.md index 5d74c17..993685f 100644 --- a/docs/Chapter-8-Child-Windows.md +++ b/docs/Chapter-8-Child-Windows.md @@ -1,10 +1,10 @@ ### Programming Industrial Strength Windows -[« Previous: Off the Launch Pad](Chapter-7-Off-the-Launch-Pad) — [Next: The Main Window »](Chapter-9-The-Main-Window) +[« Previous: Off the Launch Pad](Chapter-7-Off-the-Launch-Pad.md) — [Next: The Main Window »](Chapter-9-The-Main-Window.md) # Chapter 8: Child Windows The TextEdit main windows is a standard SDI (Single Document Interface) application window with optional tool– and status bars, and a big, fat text editing window in the middle. -![](Chapter 8 — Child Windows_Figure10.bmp) +![](Chapter-8-Child-Windows-Figure10.bmp) **Figure 10: TextEdit in Action, with eight of its nine windows visible.** @@ -21,7 +21,7 @@ How many windows do you count in Figure 10? There are nine of them, eight of whi }} The ninth window is the toolbar’s ToolTip window, which was not present when the picture in Figure 10 was taken. The individual bitmaps on the toolbar are not windows; neither are the panes on the status bar. The scroll bars are part of the non-client area of the editing window. If this were OS/2 presentation manager, the scroll bars would be windows in their own right. Since this is Windows, they are not. -TextEdit has more windows than these, though. Dialog boxes and their controls are windows too, and I’ll have more to say about them later, starting in [Chapter 13](Chapter-13-About-Dialogs). +TextEdit has more windows than these, though. Dialog boxes and their controls are windows too, and I’ll have more to say about them later, starting in [Chapter 13](Chapter-13-About-Dialogs.md). ## Window Creation @@ -93,7 +93,7 @@ Most of the **Statusbar** class is devoted to providing convenient ways of setti Like the tool bar, the status bar subclasses the main window to intercept messages. The status bar is interested in {"WM_SIZE"} and {"WM_DRAWITEM"}. (Subclassing a window to listen in on the message traffic is different from MFC’s message reflection mechanism, but the result is similar – improved encapsulation.) -The first pane is **{"SBT_OWNERDRAW"}**, because I want to display rich text in the pane, and because I want to highlight some messages. The **paintHTML** function (in HTML.cpp) handles both; I’ll get back to the details in [Chapter 13](Chapter-13-About-Dialogs). +The first pane is **{"SBT_OWNERDRAW"}**, because I want to display rich text in the pane, and because I want to highlight some messages. The **paintHTML** function (in HTML.cpp) handles both; I’ll get back to the details in [Chapter 13](Chapter-13-About-Dialogs.md). The final item of interest is the recalcParts method, which (re-) calculates the sizes of the status bar panes in response to size changes in the main window. This is necessary because the first pane is the one that stretches. diff --git a/docs/Chapter-9-The-Main-Window.md b/docs/Chapter-9-The-Main-Window.md index a3bb5a7..7772fa5 100644 --- a/docs/Chapter-9-The-Main-Window.md +++ b/docs/Chapter-9-The-Main-Window.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Previous: Child Windows](Chapter-8-Child-Windows) — [Next: Customization and Persistence »](Chapter-10-Customization-and-Persistence) +[« Previous: Child Windows](Chapter-8-Child-Windows.md) — [Next: Customization and Persistence »](Chapter-10-Customization-and-Persistence.md) # Chapter 9: The Main Window The **mainWndProc** function (in mainwnd.cpp) implements the window function for TextEdit’s main window, and is the central switchboard of TextEdit. To do the switching, it employs the message cracker macros in windowsx.h. Even though mainWndProc contains the big switch statement of traditional window functions, the {"HANDLE_MSG"} macro delegates each message to an appropriate handler function in a – sort of – type-safe manner. At least the programmer doesn’t need to worry about the parameter packing for the various messages. Furthermore, the macros are portable between Win16 and Win32. This is particularly important for messages such as {"WM_COMMAND"}, where the parameter packing changed. diff --git a/docs/Documentation.md b/docs/Documentation.md index 13cb841..9a8aae2 100644 --- a/docs/Documentation.md +++ b/docs/Documentation.md @@ -1,3 +1,3 @@ I'm posting an entire book here, in the hope that this will provide sufficient documentation, and perhaps some additional value: -[Programming Industrial Strength Windows](Programming-Industrial-Strength-Windows) \ No newline at end of file +[Programming Industrial Strength Windows](Programming-Industrial-Strength-Windows.md) \ No newline at end of file diff --git a/docs/Home.md b/docs/Home.md index 00ece30..098e9c9 100644 --- a/docs/Home.md +++ b/docs/Home.md @@ -8,12 +8,12 @@ TextEdit demonstrates a number of things: * There is no _Save_ command. TextEdit follows Allan Cooper's unified file model, where all changes are committed directly to disk. * Error handling and robustness. -* [Persistence everywhere](Chapter-10-Customization-and-Persistence). +* [Persistence everywhere](Chapter-10-Customization-and-Persistence.md). * Send as email. -* [Installation and registration](Chapter-20-Setup-and-Down-Again) (under the hood, as it were). +* [Installation and registration](Chapter-20-Setup-and-Down-Again.md) (under the hood, as it were). * Utilizing the SendTo folder. -* [The myriad ways of starting a Windows app and receiving arguments](Chapter-7-Off-the-Launch-Pad). -* [The fine points of dialogs](Chapter-13-About-Dialogs) +* [The myriad ways of starting a Windows app and receiving arguments](Chapter-7-Off-the-Launch-Pad.md). +* [The fine points of dialogs](Chapter-13-About-Dialogs.md) * [Simple HTML parsing and rendering](Sidebar_-The-HTML-Static-Control). * Snap window to edges of work area during move and resize @@ -23,9 +23,9 @@ TextEdit demonstrates a number of things: I'm posting an entire book here, in the hope that this will provide sufficient documentation, and perhaps some additional value: -[Programming Industrial Strength Windows](Programming-Industrial-Strength-Windows) +[Programming Industrial Strength Windows](Programming-Industrial-Strength-Windows.md) -![](Home_pisw.jpg) +![](Home-pisw.jpg) The logo, by the way, was made with [Microsoft Expression Design 2.](http://www.microsoft.com/expression/products/Overview.aspx?key=design) [Further info about me.](http://petterhesselberg.com/) \ No newline at end of file diff --git a/docs/Introduction.md b/docs/Introduction.md index 477cf45..0e5d451 100644 --- a/docs/Introduction.md +++ b/docs/Introduction.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[Next: The Road Ahead »](Chapter-1-The-Road-Ahead) +[Next: The Road Ahead »](Chapter-1-The-Road-Ahead.md) # Introduction **“Error handling has been omitted for clarity.”** @@ -35,7 +35,7 @@ If you are a programmer with some knowledge of {"C++"} and some Windows experien It does, however, cover many aspects of application design, target platform and implementation language selection, usability issues and a myriad implementation details, including error handling and recovery, installation, internationalization and registry handling. Along the way, I touch upon enough programming issues to make this book interesting for programmers at many levels of experience. Both neophytes and experienced Windows programmers will find things of interest here. -The book also has something to offer MFC programmers and even Visual Basic programmers – in short, all programmers working with Windows. [Chapter 1](Chapter-1-The-Road-Ahead) discusses the relationship between several approaches to Windows programming. +The book also has something to offer MFC programmers and even Visual Basic programmers – in short, all programmers working with Windows. [Chapter 1](Chapter-1-The-Road-Ahead.md) discusses the relationship between several approaches to Windows programming. This is not a reference manual, but more of an exploratory trip into nooks and crannies of the Windows API. If I don’t exhaustively explain everything found along the way, you will at least learn something about what’s out there, and can find the reference material for yourself – in the material included with your compiler or on the Net. diff --git a/docs/Programming-Industrial-Strength-Windows.md b/docs/Programming-Industrial-Strength-Windows.md index f11f431..ea76119 100644 --- a/docs/Programming-Industrial-Strength-Windows.md +++ b/docs/Programming-Industrial-Strength-Windows.md @@ -8,37 +8,37 @@ Once, TextEdit was a companion program for a book. Now, that book serves as the _I've uploaded all the chapters, adapting to the Wiki formatting as best I could. Formatting and cross-references is a bit haphazard, but it's all readable. Most of the code listings are just placeholders, but you can find them all under the **Source Code** tab. Which is sort of the point, here on CodePlex..._ -[Introduction](Introduction) +[Introduction](Introduction.md) ## Part I : Background -[Chapter 1 — The Road Ahead](Chapter-1-The-Road-Ahead) -[Chapter 2 — Designing for Users](Chapter-2-Designing-for-Users) -[Chapter 3 — Designing for Programmers](Chapter-3-Designing-for-Programmers) -[Chapter 4 — The Mechanics of Subclassing](Chapter-4-The-Mechanics-of-Subclassing) +[Chapter 1 — The Road Ahead](Chapter-1-The-Road-Ahead.md) +[Chapter 2 — Designing for Users](Chapter-2-Designing-for-Users.md) +[Chapter 3 — Designing for Programmers](Chapter-3-Designing-for-Programmers.md) +[Chapter 4 — The Mechanics of Subclassing](Chapter-4-The-Mechanics-of-Subclassing.md) ## Part II: Foreground -[Chapter 5 — The Bare Bones](Chapter-5-The-Bare-Bones) -[Chapter 6 — Exceptions](Chapter-6-Exceptions) -[Chapter 7 — Off the Launch Pad](Chapter-7-Off-the-Launch-Pad) -[Chapter 8 — Child Windows](Chapter-8-Child-Windows) -[Chapter 9 — The Main Window](Chapter-9-The-Main-Window) -[Chapter 10 — Customization and Persistence](Chapter-10-Customization-and-Persistence) -[Chapter 11 — Wait a Moment](Chapter-11-Wait-a-Moment) -[Chapter 12 — File I/O](Chapter-12-File-I-O) -[Chapter 13 — About Dialogs](Chapter-13-About-Dialogs) -[Chapter 14 — File Management](Chapter-14-File-Management) -[Chapter 15 — Search and Replace](Chapter-15-Search-and-Replace) -[Chapter 16 — Printing](Chapter-16-Printing) -[Chapter 17 — Changing Fonts](Chapter-17-Changing-Fonts) -[Chapter 18 — Going Abroad](Chapter-18-Going-Abroad) -[Chapter 19 — Meanwhile, in the Background](Chapter-19-Meanwhile-in-the-Background) -[Chapter 20 — Setup, and Down Again](Chapter-20-Setup-and-Down-Again) -[Chapter 21 — The End of the Road](Chapter-21-The-End-of-the-Road) - -[Appendix A — TextEdit Command Index](Appendix-A-TextEdit-Command-Index) -[Appendix B — Bibliography and Recommended Reading](Appendix-B-Bibliography-and-Recommended-Reading) +[Chapter 5 — The Bare Bones](Chapter-5-The-Bare-Bones.md) +[Chapter 6 — Exceptions](Chapter-6-Exceptions.md) +[Chapter 7 — Off the Launch Pad](Chapter-7-Off-the-Launch-Pad.md) +[Chapter 8 — Child Windows](Chapter-8-Child-Windows.md) +[Chapter 9 — The Main Window](Chapter-9-The-Main-Window.md) +[Chapter 10 — Customization and Persistence](Chapter-10-Customization-and-Persistence.md) +[Chapter 11 — Wait a Moment](Chapter-11-Wait-a-Moment.md) +[Chapter 12 — File I/O](Chapter-12-File-I-O.md) +[Chapter 13 — About Dialogs](Chapter-13-About-Dialogs.md) +[Chapter 14 — File Management](Chapter-14-File-Management.md) +[Chapter 15 — Search and Replace](Chapter-15-Search-and-Replace.md) +[Chapter 16 — Printing](Chapter-16-Printing.md) +[Chapter 17 — Changing Fonts](Chapter-17-Changing-Fonts.md) +[Chapter 18 — Going Abroad](Chapter-18-Going-Abroad.md) +[Chapter 19 — Meanwhile, in the Background](Chapter-19-Meanwhile-in-the-Background.md) +[Chapter 20 — Setup, and Down Again](Chapter-20-Setup-and-Down-Again.md) +[Chapter 21 — The End of the Road](Chapter-21-The-End-of-the-Road.md) + +[Appendix A — TextEdit Command Index](Appendix-A-TextEdit-Command-Index.md) +[Appendix B — Bibliography and Recommended Reading](Appendix-B-Bibliography-and-Recommended-Reading.md) # þe Olde Blurbe diff --git a/docs/Sidebar-Conceptual-Models.md b/docs/Sidebar-Conceptual-Models.md index e8799b1..807e635 100644 --- a/docs/Sidebar-Conceptual-Models.md +++ b/docs/Sidebar-Conceptual-Models.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Back: Designing for Users](Chapter-2-Designing-for-Users) +[« Back: Designing for Users](Chapter-2-Designing-for-Users.md) ## Sidebar: Conceptual Models A conceptual model is a mental map of the most important parts of a system and how they relate to each other. The term mental model is sometimes used as a synonym. diff --git a/docs/Sidebar-Default-Buttons-and-Multi-line-Edit.md b/docs/Sidebar-Default-Buttons-and-Multi-line-Edit.md index 8546294..af1cd07 100644 --- a/docs/Sidebar-Default-Buttons-and-Multi-line-Edit.md +++ b/docs/Sidebar-Default-Buttons-and-Multi-line-Edit.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Back: About Dialogs](Chapter-13-About-Dialogs) +[« Back: About Dialogs](Chapter-13-About-Dialogs.md) ## Sidebar: Default Buttons and Multi-line Edit I'd like to draw your attention to a user interface bug that runs rampant through the world of Windows applications. It involves the interaction of multi-line edit controls and default push buttons. diff --git a/docs/Sidebar-Messy-Menus.md b/docs/Sidebar-Messy-Menus.md index 6dbbd58..22720a5 100644 --- a/docs/Sidebar-Messy-Menus.md +++ b/docs/Sidebar-Messy-Menus.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Back: The Main Window](Chapter-9-The-Main-Window) +[« Back: The Main Window](Chapter-9-The-Main-Window.md) ## Sidebar: Messy Menus The keyboard interface to the menu has its problems. Hold down the Alt key, press F, and the File menu pops up (or rolls down, whichever you prefer). Don’t let go of that Alt key yet; look instead at the line that says “Properties… Alt{"+"}Enter.” diff --git a/docs/Sidebar-The-HTML-Static-Control.md b/docs/Sidebar-The-HTML-Static-Control.md index 62ca7fc..f906819 100644 --- a/docs/Sidebar-The-HTML-Static-Control.md +++ b/docs/Sidebar-The-HTML-Static-Control.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Back: About Dialogs](Chapter-13-About-Dialogs) +[« Back: About Dialogs](Chapter-13-About-Dialogs.md) ## Sidebar: The HTML Static Control The resource script for the About TextEdit dialog box includes this line: diff --git a/docs/Sidebar-The-Open-File-Common-Dialog-Bug.md b/docs/Sidebar-The-Open-File-Common-Dialog-Bug.md index 00321d6..bb5e6e5 100644 --- a/docs/Sidebar-The-Open-File-Common-Dialog-Bug.md +++ b/docs/Sidebar-The-Open-File-Common-Dialog-Bug.md @@ -1,5 +1,5 @@ ### Programming Industrial Strength Windows -[« Back: File Management](Chapter-14-File-Management) +[« Back: File Management](Chapter-14-File-Management.md) ## Sidebar: The Open File Common Dialog Bug The Win32 Open File common dialog has a curious bug – at least it does under Windows NT 4.0. It is not even close to being a showstopper, but it is nevertheless a bug. To manifest the bug, do the following: