Table of Contents
- Chapter 1: Hello, MFC
- Chapter 2: Drawing in a Window
- Chapter 3: The Mouse and the Keyboard
- Chapter 4: Menus
- Chapter 5: The MFC Collection Classes
- Chapter 6: File 1/0 and Serialization
- Chapter 7: Controls
- Chapter 8: Dialog Boxes and Property Sheets
- Chapter 9: Documents, Views, and the Single Document Interface
- Chapter 10: Scroll Views, HTML Views, and Other View Types
- Chapter 11: Multiple Documents and Multiple Views
- Chapter 12: Toolbars, Status Bars, and Rebars
- Chapter 13: Printing and Print Previewing
- Chapter 14: Timers and Idle Processing
- Chapter 15: Bitmaps, Palettes, and Regions
- Chapter 16: The Common Controls
- Chapter 17: Threads and Thread Synchronization
- Chapter 18: MFC and the Component Object Model
- Chapter 19: The Clipboard and OLE Drag-and-Drop
- Chapter 20: Automation
- Chapter 21: ActiveX Controls
Read an Excerpt
Chapter 2: Drawing in a Window
If you've been around PCs for a while, you probably remember what graphics programming was like before Microsoft Windows came along. If you were lucky, you had a decent graphics library with routines like Drawline and Drawcircle to draw graphics primitives for you. If you weren't so lucky, you probably spent a lot of time writing your own output routines and tweaking them to shave off a few microseconds here and there. And whether it was your code or someone else's doing the drawing, you knew that when a new graphics standard emerged-in those days, that meant whenever IBM introduced a new graphics adapter like the EGA or the VGA you'd be scrambling to support the latest hardware. That invariably meant buying an updated version of the graphics library, adding new code to your own routines, or writing a driver for the new video card. For the graphics programmer, the platform was a moving target that never seemed to stand still for very long. And even if you did manage to draw a bead on the video hardware, you still had plenty of work to do to adapt your code to work with printers and other output devices.
Windows changed all that by bringing to the PC platform something it sorely needed: a device-independent graphics output model. In Windows, the graphics code you write will work on any video adapter for which a Windows driver is available. These days, that's just about every adapter on the planet. And to a large extent, the same code that sends output to the screen will also work with printers and other hardcopy devices. This one-size-fits-all approach to graphics programming has a number of advantages, chief among them the fact that programmers can now spend their time developing code for their applications rather than code for the hardware their applications will run on. Moreover, you no longer need third-party graphics libraries in order to do your work because Windows provides a wide assortment of graphics API functions that do everything from draw lines to create complex clipping regions that serve as stencils for other output routines.
The part of Windows responsible for graphics output is the Graphics Device Interface, or GDI. The GDI provides a number of services that an application can call. Together, these services constitute a powerful and robust graphics programming Ianguage whose richness rivals that of some third-party graphics libraries. MFC works on top of the graphics API and codifies the interface with C++ classes that represent the various components of the Windows GDI.
Now that you know how to create a window, it's time to do something with that window. The Hello application in Chapter 1 used CDC.:DrawText to output text to a window. DrawText is just one of many member functions that the CDC class provides for text and graphics output. This chapter looks at the CDC class and its derivative classes in more detail and introduces three of the most commonly used GDI primitives: pens, brushes, and fonts. it also demonstrates how to add scroll bars to a window.
THE WINDOWS GDI
In a single-tasking environment such as MS-DOS, the name of the game when it comes to screen output is "anything goes." A running application is free to do just about whatever it wants whenever it wants, whether that involves drawing a line on the screen, reprogramming the adapter's color palette, or switching to another video mode. In a windowed, multitasking environment such as Windows, programs can't be afforded such freedom because the output from program A must be protected from the output of program B. First and foremost, this means that each program's output must be restricted to its own window. The GDI uses a simple mechanism to make sure every program that draws in a window plays by the rules. That mechanism is the device context.
When a Windows program draws to a screen, a printer, or any other output device, it doesn't output pixels directly to the device. Instead, it draws to a logical "display surface" represented by a device context (DC). A device context is a data structure deep inside Windows that contains fields describing everything the GDI needs to know about the display surface, including the physical device with which it is associated and assorted state information. Before it draws anything on the screen, a Windows program acquires a device context handle from the GDI It then passes that handle back to the GDI each time it calls a GDI output function. Without a valid device context handle, the GDI won't draw the first pixel. And through the device context, the GDI can make sure that everything the program draws is clipped to a particular area of the screen. Device contexts play a huge role in making the GDI device-independent because, given a handle to a device context, the same GDI functions can be used to draw to a diverse assortment of output devices.
When you program Windows with MFC, the device context has even greater significance. In addition to serving as the key that unlocks the door to output devices, a device context object encapsulates the GDI functions that programs use to generate output. In MFC, you don't grab a handle to a device context and call GDI output functions, at least not directly; instead, you create a device context object and call its member functions to do your drawing. MFC's CDC class wraps a Windows device context and the GDI functions that require a device context handle into one convenient package, and CDC-derived classes such as CPaintDC and CClientDC represent the different types of device contexts that Windows applications use.
The MFC Device Context Classes
One way to get a device context in an MFC application is to call CWnd::GetDC, which returns a pointer to a CDC object representing a Windows device context. A device context pointer acquired with CWnd::GetDC should be released with CWnd::ReleaseDC when drawing is completed. The following code gets a CDC pointer from GetDC, does some drawing, and calls ReleaseDC to release the device context:...