Electronic Review of Computer Books

[ ERCB Home | New | Feature | Brief | DDJ | Letters | Links ]

[an error occurred while processing this directive]

Vital Statistics

Title Programming Windows 95 with MFC
Author Jeff Prosise
Publisher Microsoft Press
Redmond, Washington
http://www.microsoft.com/mspress/
Copyright 1996
ISBN 1-55615-902-1
Pages 999
Price $49.95


The Road Not Taken

Most books about Windows programming tread similar paths; the organization and topics in most books about Windows programming in MFC are nearly identical. Landmarks you pass always include: how the author got into Windows, discovered MFC, realized that Visual C++ is the best compiler in the universe -- the perfect combination of encapsulation of the Windows SDK and efficiency. Then, they talk about how wonderful VC's wizards are at generating Windows applications. Then, because the wizards always generate document/view applications, before page 50, they discuss the document/view architecture, which takes up most of the rest of the book.

Jeff Prosise gets a short way down this same old path before taking a radical turn -- he decides to not start by dissecting the archetypal application that Microsoft would have us start with. Instead of encouraging us to let the wizards of Microsoft light our trails, he shows us how to strike out on our own. Once embarked on this independent path, Prosise mentions the document/view architecture, but only to promise to steer clear of it for a while. He mostly keeps his promises.

Prosise makes a pretty good guide, and over some pretty rough terrain too. He seems to be targeting his book at experienced C++ programmers who have never programmed in Windows before, like, perhaps, some of those UNIX types who've been won over by the wonders of NT, or maybe it's the former Borland C++ programmers he's after. In any case, Prosise devotes no space at all to defining or describing in the abstract object-oriented techniques or the fairly arcane C++ terminology and lore he occasionally brings up. But he does go into nicely gorey detail about the intricasies of Windows' message routing and the SDK as well as the other Windows-specific components that MFC programmers need to know about, despite the fact that MFC supposedly encapsulates the SDK so well.

Prosise's descriptions of Windows' functionality and how to take advantage of it are excellent. His expositions on GDI objects -- the scrollbar, brushes vs. pens, and the colors of controls, as well as his page on when to delete objects and when to let Windows do it (page 106) are worth the price of admission.

What Prosise is not is well-organized. Partly, this springs from the difficulty of presenting so much material in "only" 1000 pages. And, in part, it comes from Prosise's decision, which I admire immensely, to attempt to put off discussing MFC's infamous document/view philosophy until his eighth chapter. Unfortunately, he can't quite pull this off perfectly. (It's not entirely his fault; document/view infects many parts of MFC that would be healthier without it.) And, also some of the disorganization comes from Prosise's obvious enthusiasm for his subject. He can't seem to stay focused on simple programming tasks; he's got much more to share.

So, there you are, reading about dialog boxes in Chapter 6 for example. In introducing the code sample, Prosise writes, (overly modestly, you'll discover) "The DlgDemo1 application ... does the bare minimum amount of work necessary to get a dialog box up on the screen." You steel yourself for a boring read. But, lo and behold, early in the code you spot a method called DoGradientFill(). Now, what on earth does this have to do with doing the bare minimum of anything? Nothing at all, actually. It's as if your mom had come over to show you how to prepare meatloaf, and, next thing you know, Julia Child is browning a truffle soufflé with a blowtorch in your kitchen.

If all you actually wanted to do was build a plain vanilla dialog box, well then, you would not be pleased. If you just want answers to specific questions, read a different book and let Microsoft's silly old wizard generate your About boxes for you. Prosise usually gets around to introducing the main course, in this case the dialog box, but his style is to describe complicated appetizers first. After the gradients, he digresses to a useful and interesting discussion of how different display adapters dither colors under Windows and how developers can cope with this. It is way cool.

But to find it, you probably have to read from cover to page 364, because (to most people's minds, anyway) dithering has little to do with dialog boxes. The word "dithering" is entirely absent from the index. "Dithering" is absent from both of the Table of Contents as well. And, to find all the other interesting stuff buried here, you probably have to read this book from cover to cover.

Which isn't painful. It's a good book. If you are a C++ programmer by training, avocation or profession, and you are fairly new to programming in MFC, or you're just looking for medium-deep MFC, Prosise's Programming Windows 95 with MFC is definitely the tutorial for you.

If you're not already very comfortable with C++, make sure you have a good language reference at hand. That way, when Prosise throws in a dig at ANSI C++, which MFC thumbs its nose at in a number of confusing ways, you'll at least be able to parse his sentences. (Hint: Read and mark the page for "vtable" in your C++ reference before you even open Prosise. He gets his digs in early and often.)

-- Emily Berk (armadill@ix.netcom.com)


Excerpts from Programming Windows 95 with MFC

The PostNcDestroy Function

A final consideration involved in using a window class derived directly from CWnd is that once created, the window object must somehow be deleted. As described in Chapter 2, the very last message a window receives before it is destroyed is WM_NCDESTROY. CWnd provides a default OnNcDestroy handler that performs some routine cleanup chores and then, as its very last act, calls a virtual function named PostNcDestroy. CFrameWnd objects delete themselves when the windows they are attached to are destroyed by overriding PostNcDestroy and executing a delete this statement. CWnd::PostNcDestroy does not perform a delete this, so a class derived from CWnd should provide its own version of PostNcDestroy that does. TicTac includes a trivial PostNcDestroy function that destroys the CMainWindow object just before the program terminates:

void CMainWindow::PostNcDestroy (){
 
    delete this;
}

The question "who deletes it" is something you should always think about when you derive a window class from CWnd.

-- Page 131


The CLlne and CObArray Classes

As mentioned, Paint1 stores information about the lines you draw in an array of Cline objects. The CLine class is publicly derived from CObject in Paint1.h. Paint1 doesn't explicitly use any of the features CLine inherits from CObject, but as we'll see in Chapter 6, the fact that CLine is derived from CObject will make it easy for us to add serialize line support to the CLine class so that entire drawings can be saved and restored with just a few lines of code.

CLine encapsulates all the information needed to describe a line drawn in Paint1's client area: endpoint coordinates, width, and color. Its constructor initializes a Cline object with a pair of endpoints, a width, and a color, and its virtual Draw function draws the line on the screen. When Paint1's OnPaint function redraws the window's client area, it doesn't do any drawing on its own; rather, it invokes each CLine object's Draw function, commanding the line to draw itself. OnPaint's contribution to the process is a pointer to a device context object that CLine::Draw uses to do its drawing. This more object-oriented approach to storing (and displaying) an application's data leads to a more robust program design. It's also a preview of things to come in later chapters, where we'll learn to write document/view applications that store their data in document objects built from MFC's CDocument class.

-- Page 212


Changing a Control's Colors

Perhaps the most glaring deficiency of buttons, static text controls, and other built-in control types is that there's no obvious way to change their colors. You can change a control's font with SetFont, but there's no SetColor function or equivalent. Button controls and static controls look fine as long as they're displayed against a COLOR_3DFACE background because they paint their own backgrounds with COLOR_3DFACE. But display them on any other background, and they'll stick out like sore thumbs.

In MFC, there are two ways to change the colors a control uses. Both hinge on the fact that before a control paints itself it sends its parent a message with the handle of the device context that will be used to do the painting. The control's parent can change the control's color by using CDC::SetTextColor and CDC::SetBkColor to alter the attributes of the device context. In addition, the value returned by the message handler is a brush handle (HBRUSH) the control will use to paint its background. A static text control, for example, sends its parent a WM_CTLCOLORSTATIC message just before painting itself. The message's wParam holds the device context handle, and IParam contains the control's window handle. If the parent supplies a message handler that sets the text color to red and the background color to white and returns an HBRUSH value for a blue brush, the control's text will be drawn in red, the gaps in and between characters will be colored white, and the background--everything inside the control's borders not covered by text--will be blue.

-- Page 335


If you run DlgDemol on a display adapter that supports either 16- or 24-bit color, the window will look like the picture in Figure 6-2. But run it on 16- or 256-color video hardware, and it will look more like the one in Figure 6-3 on the next page. Obviously, there's a problem: instead of a smooth gradient fill, the window contains just three different colors. What happened? In Chapter 2, I mentioned that 1-pixelwide pens are not dithered but are mapped by Windows to the nearest solid color. Pens with blue values ranging from 192 through 255 get mapped to RGB (0, 0, 255), pens with blue values from 64 through 191 get mapped to RGB (0, 0, 128), and pens with blue values from 0 through 63 get mapped to RGB (0, 0, 0). Never mind that a256-color device can support a wide range of blues; unless you take special steps to make the extra shades of blue available, Windows treats a 256-color display as if it were a standard 16-color VGA device.

There are two solutions to the problem of limited color availability. One is to create a GDI palette containing 64 different shades of blue and paint with the colors in the palette. This solution would produce a smooth gradient fill on 256-color display adapters but would have no effect on 16-color devices. (Palettes will be discussed in detail in Chapter 12.) The other solution is to draw with brushes instead of pens because Windows will willingly dither brush colors to simulate a richer selection of colors. This technique has two advantages: it's simple to implement in code, and it works as well on 16-color devices as it does on 256-color devices.

-- Page 369


Tables of Contents

Prosise provides us with two different Tables of Contents.

There's the overview:

Contents at a Glance

Acknowledgments

xiii

Introduction

xv

Part I

MFC Basics

Chapter1

Hello, MFC

3

Chapter 2

Drawing in a Window

43

Chapter 3

The Mouse and the Keyboard

107

Chapter 4

Menus

185

Chapter 5

Controls

253

Chapter 6

Dialog Boxes and Property Sheets

351

Chapter 7

Timers and Idle Processing

497

Part II

The Document/View Architecture

Chapter 8

Documents, Views, and the Single Document Interface

547

Chapter 9

Multiple Documents and Multiple Views

597

Chapter 10

Printing and Print Previewing

669

Chapter 11

Toolbars, StatusBars, and Versionable Schemas

711

Part III

Advanced Topics

Chapter 12

Bitmaps, Palettes, and Regions

769

Chapter 13

The Common Controls

839

Chapter 14

Threads and Thread Synchronization

909

Index

971

And then there's the more comprehensive one:

Contents

Acknowledgments xiii

Introduction xv

Part I

MFC Basics

Chapter 1

Hello, MFC 3

The Windows Programming Model - More About Messages - Windows Programming, SDK-Style - Introducing MFC . The Benefits of Using C++ and MFC - The MFC Design Philosophy - The Document/ View Architecture - The MFC Class Hierarchy - The Afx Functions - Your First MFC Application - The Application Object - How MFC Uses the Application Object - The Window Object - The Message Map - The Big Picture

Chapter 2

Drawing in a Window 43

Drawing with the GDI - The MFC Device Context Classes - GDI Pens and the CPen Class - GDI Brushes and the CBrush Class - Deleting Pens and Brushes - The GdiDemol Application - The Application Icon - Seeing What You've Drawn - Adding a Scroll Bar to a Window - Setting a Scroll Bar's Range, Position, and Page Size - Processing Scroll Bar Messages - Scrolling the Contents of a Window - The GdiDemo2 Application _ - Scrolling Made Easy - The CScrollview Class - The GdiDemo3 Application - Loose Ends

Chapter 3

The Mouse and the Keyboard 107

Getting Input from the Mouse - Client-Area Mouse Messages - The TicTac Application - Nonclient-Area Mouse Messages - Capturing the Mouse - Mouse Capturing in Action - The Cursor - Mouse Miscellanea - Getting Input from the Keyboard - Keystroke Messages - Adding a Keyboard Interface to GdiDemo3 - Character Messages - The Caret - The VisualKB Application - Handling the Caret - Entering and Editing Text - Other Points of Interest - International Keyboard Processing Considerations

Chapter 4

Menus 185

Menu Basics - Creating a Menu - Displaying the Menu - Responding to Menu Commands - Defining Command Ranges - Keeping Menu Items in Sync with Your Application - Keyboard Accelerators - The Paintl Application - The Paintl Menus and Accelerators - Menu Magic - Creating and Modifying Menus Programmatically - Owner-Drawn Menus - Cascading Menus Context Menus - The Paint2 Application - The System Menu - Toolbars and Status Bars

Chapter 5

Controls 253

The MFC Control Classes - The CButton Class - The CListBox Class - The CStatic Class - The Font View Application - The CEdit Class - The CComboBox Class - The CScrollBar Class - Advanced Control Programming - Adding a Keyboard Interface - Modifying Control Behavior - Owner-Drawn List Boxes - Bitmap Buttons - Changing a Control's Colors - Message Reflection

Chapter 6

Dialog Boxes and Property Sheets 351

Modal Dialog Boxes and the CDlalog Class - The Dialog Template - The Dialog Class - Creating a Modal Dialog Box - Creating a Simple About Box - Building a Better About Box - A More Complex Dialog Box - Dialog Data Exchange and Validation - Using Derived Control Classes in Dialog Boxes - Modeless Dialog Boxes - The DlgDemo5 Application - Using a Modeless Dialog Box as a Main Window - Property Sheets - The PropDemo Application - The Common Dialogs - File Input and Output and the CFile Class - Serialization and the CArchive Class - The Paint3 Application - Modifying the Common Dialogs

Chapter 7

Timers and Idle Processing 497

Timers - Setting a Timer: Method 1 - Setting a Timer: Method 2 - Stopping a Timer - The Clock Application - Idle Processing - Overriding CWinApp::Onldle - The IdleDemo Application

Part II

The Document/View Architecture

Chapter 8

Documents, Views, and the Single Document Interface 547

Document/View Fundamentals - The InitInstance Function Revisited - The Document Object - The View Object - The Frame Window Object - Dynamic Object Creation - More on the SDI Document Template - Registering Document Types with the Operating System Shell - Command Routing - Predefined Command IDs and Default Command Implementations - Your First Document/View Application - The Paint4 Application - Doc + View = Less Work for You

Chapter 9

Multiple Documents and Multiple Views 597

Splitter Windows - Creating Dynamic Splitter Windows - Linking the Views with CDocument::UpdateAllViews and CView::OnUpdate - The Paints Application - Creating Static Splitter Windows - Creating Three-Way Splitter Windows - The Paint6 Application - Dynamic Splitter Windows with Multiple View Types - Splitter Windows in MDI Applications - MFC and the Multiple Document Interface - The Paint7 Application - Alternatives to MDI

Chapter 10

Printing and Print Previewing 669

Printing with Documents and Views - The Windows Print Architecture - The MFC Print Architecture - Print Previewing - A Bare-Bones Printing Application - A More Complex Printing Application - Printing Tips and Tricks - Enabling the Selection Button - Assume Nothing--And(sic) Test Thoroughly! - Adding Default Pagination Support - Enumerating Printers

Chapter 11

Toolbars, Status Bars, and Versionable Schemas 711

Toolbars - Creating and Initializing a Toolbar - Docking and Floating - Controlling a Toolbar's Visibility - Keeping Toolbar Buttons in Sync with Your Application - Adding Tooltips and Flyby Text - Adding Non-Push-Button Controls to a Toolbar - Updating Non-Push-Button Controls - Making Toolbar Settings Persistent - Status Bars - Creating and Initializing a Status Bar - Providing Context-Sensitive Help for Menu Items - Creating Custom Status Bar Panes - Putting It All Together: The MyWord Application - More About CRichEditView - Versionable Schemas - Under the Hood: How Serialization Works - Writing a Versionable Class

Part III

Advanced Topics

Chapter 12

Bitmaps, Palettes, and Regions 769

Palettes - How Windows Uses Color - Logical Palettes and the CPalette Class - WM_QUERYNEWPALETTE and WM_PALETTECHANGED - Deciding Whether a Logical Palette Is Needed - The PaletteDemo Application - Palette Animation - The ::SetSystemPaletteUse Function - Bltmaps - Device-Dependent Bitmaps and the CBitmap Class - Blitting Bitmaps to Screens and Other Devices - DIBs andDIB Sections - Blits, Raster Operations, and Color Mapping - The BitmapDemo Application - Writing a .bmp File Viewer - More on the ::Loadlmage Function - Regions - Regions and the CRgn Class - The RegionDemo Application

Chapter 13

The Common Controls 839

Common Control Fundamentals - Creating a Common Control - Processing Notifications: The WM_NOTIFYMessage - Slider, Spin Button, and Tooltip Controls - Slider Controls - Spin Button Controls - TooltipControls - The GridDemo Application - Image List, Tree View, and List View Controls - Image Lists - Tree View Controls - List View Controls - The CTreeView and CListView Classes - Putting It All Together: The Windows Wanderer - Custom Command Routing - A Word on the Other Common Controls

Chapter 14

Threads and Thread Synchronization 909

Threads - Creating a Worker Thread - Creating a User Interface Thread - Suspending and Resuming Threads - Putting Threads to Sleep - Terminating a Thread - Terminating a Thread from Another Thread - Threads, Processes, and Priorities - Sharing MFC Objects Among Threads - Using C RunTime Functions in Multithreaded Applications - Your First Multithreaded Application - ThreadSynchronization - Events - CriticalSections - Mutexes - Semaphores - The CSingleLock and CMultiLockClasses - Writing Thread-Safe Classes - The MTDemo Application - Odds and Ends - Message Pumps - Child Processes - File Change Notifications

Index 971


Quick Rating

Readability Star Star
Originality Star Star Star
Organization Star
Accuracy Star Star Star
Consistency Star Star
Depth Star Star Star
Timeliness Star Star
Editing Star Star
Design Star Star
Overall Value Star Star Star

Explanation of ERCB rating scale: No stars = unacceptable, 1 Star = marginal, 2 Stars = average, 3 Stars = above average, 4 Stars = exceptional.


Copyright ©1997 Electronic Review of Computer Books
Created 6/9/97 / Last modified 6/9/97 / webmaster@ercb.com