Monday, November 23, 2009

Message Mapping vs. Virtual Functions

Message Mapping vs. Virtual Functions

Once a message handler is created, it can be called by the application. In a purely object-oriented C++ environment, handlers are implemented as virtual member functions. MFC uses message maps to simulate this behavior. The message map avoids the lengthy virtual function tables that would be required if every class had a virtual function for every possible message it might receive. To maximize performance, the most current message map entries are cached by the application framework.

Note that there are a few handlers that are implemented as virtual member functions in MFC, such as CView::OnDraw.

d Virtual functions are not space-efficient because they require vtables, and vtables consume memory even if the functions in them are not overridden. The amount of memory used by a message map, in contrast, is proportional to the number of message entries it contains. Since it's extremely rare for a developer to implement a window class that includes handlers for all of the different types of messages, message mapping conserves a few hundred bytes of memory just about every time a CWnd is wrapped around an HWnd.

Message Mapping SystemThe message mapping system used by MFC is made up of two basic components: the CCmdTarget class and message maps. These two pieces work together to provide the same message handling capabilities as a regular Windows-based application.

The CCmdTarget class is the base class for any object that needs to receive Windows messages, command messages, or both. Any class derived from CCmdTarget can use a message map and only classes derived from CCmdTarget can receive messages. If you look at The MFC Class Hierarchy illustrations in Chapter 2, you will notice that a number of classes are derived from CCmdTarget, including CWnd, CDocument, and CWinApp.

A message map is the mechanism that connects a Windows message to the class member functions that are handling the message. In this section, you will look at several key elements of message maps so you can gain an understanding of how message maps work. This section includes the following topics:

Message Map Macros

MFC provides three macros to generate message maps: DECLARE_MESSAGE_MAP, BEGIN_MESSAGE_MAP, and END_MESSAGE_MAP. These macros expand into code that defines and implements a message map for a CCmdTarget-based class.

When using message maps in your classes, the basic strategy is to include the DECLARE_MESSAGE_MAP macro in your class header file, xxx.h, and to add the message mapping entries enclosed by the BEGIN_MESSAGE_MAP and END_MESSAGE_MAP macros to your implementation file, xxx.cpp.

The preprocessor uses the message map macros to generate message mapping support code. When used together in an implementation file, these macros actually implement the message map. The definitions for the message map macros found in the Afxwin.h file will help you understand how the message mapping system works.

To see the definition of the DECLARE_MESSAGE_MAP macro, click this icon.

#define DECLARE_MESSAGE_MAP() \

private: \

static const AFX_MSGMAP_ENTRY_messageEntries(); \

protected: \

static const AFX_MSGMAP messageMap; \

virtual const AFX_MSGMAP* GetMessageMap() const;

To see the definition of the BEGIN_MESSAGE_MAP macro, click this icon.

#define BEGIN_MESSAGE_MAP(theClass, baseClass) \

const AFX_MSGMAP* the Class::GetMessageMap() const \
{ return & the Class::messageMap; } \
AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \
{ &baseClass::messageMap, &theClass::_messageEntries[0] }; \
const AFX_MSGMAP_ENTRY theClass::_messageEntries[ ] = \
{
To see the definition of the END_MESSAGE_MAP macro, click this icon.

#define END_MESSAGE_MAP() \

{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
};

The message map entries (_messageEntries) and the message map structure (messageMap) are static members of the class. These elements of the message map are described in detail in the topics that follow.

Message Handlers

A message handler is a function that is called when a particular message is sent to an application window. MFC provides a number of macros that can be used to connect messages to their handlers in the message map. The following table lists common Windows messages and their corresponding macros and handlers.

Windows message Macro Message handler


WM_PAINT ON_WM_PAINT OnPaint

WM_CREATE ON_WM_CREATE OnCreate

WM_RBUTTONDOWN ON_WM_RBUTTONDOWN OnRButtonDown


The ON_WM_xxx macros are hard coded to link the Windows messages to the corresponding MFC message handlers. Every standard Windows message has a macro of the form ON_WM_xxx, where xxx is the name of the message. A simple convention is used to generate the name of the message handler function. The name of the handler function starts with "On." This is followed by the name of the message with the "WM_" removed and only the first letter of each word capitalized. Thus, the ON_WM_PAINT macro corresponds to the OnPaint message handler, as shown in the preceding table.

Some message handlers have parameters that provide additional information for processing the message. You can refer to the MFC online documentation to determine what kinds of parameters you can pass to a particular message handler and what kind of values it returns. For example, the OnLButtonDblClk message handler is prototyped like this:

afx_msg void CMsgView::OnLButtonDblClk(UINT nFlags, CPoint point)

The nFlags argument specifies the states of the mouse buttons as well as the states of the CTRL and SHIFT keys, and the point argument identifies the location at which the click occurred. The arguments passed to a message handler come from the wParam and lParam parameters that accompanied the Windows message. The wParam and lParam parameters are of necessity generic, whereas the parameters passed to an MFC handler are both specific and type-safe.

Note afx_msg is appended to the handler for use by ClassWizard. It currently evaluates to nothing and has no effect upon the execution of the application.

For more information, see "Message Map Macros" in the Visual C++ online documentation.

Message Map Entry Macros

In your source files, a message map consists of a sequence of predefined macros. The macros inside the message map are called "entry macros." The entry macros used in a message map depend upon the category of the message to be handled.

Each entry macro accepts zero or more parameters as predefined by the MFC Library. The following table summarizes the various kinds of entry macros used in message maps.

Message type Macro form Parameters


Predefined Windows message ON_WM_XXX None

Command message ON_COMMAND Command ID, Handler name

Update command ON_UPDATE_COMMAND_UI Command ID, Handler name

Control notification ON_XXX Control ID, Handler name

User-defined message ON_MESSAGE User-defined message ID, Handler name

Registered Windows message ON_REGISTERED_MESSAGE Registered message ID variable, Handler name

A range of command IDs ON_COMMAND_RANGE Start and end of a contiguous range of command IDs

A range of command IDs for updating ON_UPDATE_COMMAND_UI_RANGE Start and end of a contiguous range of command IDs

A range of control IDs ON_CONTROL_RANGE A control-notification code and the start and end of a contiguous range of command IDs


The following example code shows a message map for the CMyView class using several common entry macros with their parameters:

BEGIN_MESSAGE_MAP(CMyView, CView)
//{{AFX_MSG_MAP(CMyView)
ON_WM_MOUSEACTIVATE()
ON_COMMAND(ID_EDIT_CLEAR_ALL, OnEditClearAll)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR_ALL, OnUpdateEditClearAll)
ON_BN_CLICKED(ID_MY_BUTTON, OnMyButton)
ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
ON_REGISTERED_MESSAGE(WM_FIND, OnFind)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

For detailed information about message map entry macros and their parameters, see "Technical Note 6: Message Maps," available in the Microsoft Foundation Class Reference section of the Visual C++ online documentation.

How Message Maps Work

In this topic, you'll take a look at what goes on behind the scenes when you use message mapping macros in your code, and how MFC uses the code and data that are generated by the macros to convert messages into calls to the corresponding message handlers.

When you use the DECLARE_MESSAGE_MAP macro in the class declaration, it adds three members to the class:

® An array of data structures that contain information to link messages to message handlers

® A static data structure that contains a pointer to the array of message map entry macros for the class and a pointer to the message map for the base class

® A virtual function named GetMessageMap

Where the Message Map Begins

Let's look at an example. The following example code is the class declaration for the application class CMyClass:
class CMyClass : public CWinApp{
...
DECLARE_MESSAGE_MAP
};

Based on this class declaration, the preprocessor generates the following example code for message mapping:

private: static const AFX_MSGMAP_ENTRY _messageEntries[];
protected: static const AFX_MSGMAP messageMap;
virtual const AFX_MSGMAP* GetMessageMap() const;

To generate preprocessor output, use the cl /P filename on a command line. It writes preprocessor output to a file with the same base name as the source file, but with the .i extension.

The first statement from the code generated by the preprocessor is the _messageEntries array and contains information linking messages to message handlers. The next statement is the messageMap structure, which contains a pointer to the class's _messageEntries array and a pointer to the base class's messageMap structure. The last statement adds the virtual function GetMessageMap and returns the address of the messageMap for the base class.

Where the Message Macros Fit In
The BEGIN_MESSAGE_MAP macro contains the implementation for the GetMessageMap function and code to initialize the messageMap structure. The macros that appear between BEGIN_MESSAGE_MAP and END_MESSAGE_MAP fill in the _messageEntries array, and END_MESSAGE_MAP marks the end of the array with a NULL entry.

Message Mapping Data Structures
To keep things simple, the implementation details of the message mapping data structures and functions are not shown here. You can look at the definitions of the message map macros in the Afxwin.h file and examine the code in the source files to find out more about the message mapping data structures.

Putting It All Together
The following illustration shows how the key elements of a message map fit together and indicates the path the framework follows to search for a message handler to match a given message ID.



To start processing a message, the framework calls the GetMessageMap function to get a pointer to CMainFrame's message map structure. It then scans the messageEntries array to see if there is a handler for the message. In the preceding illustration, the message being processed is WM_PAINT. If necessary, GetMessageMap can use the pointer to the base class (in this case, the CFrameWnd class) to search its message map to see if there is a message handler available. GetMessageMap will continue to search through the class hierarchy for a message handler until it reaches the last base class. The pointer for the last base class in the hierarchy is NULL. If GetMessageMap gets a NULL pointer, no message handler was found and the message is passed to Windows for processing

Handling Messages









Untitled Document







Chapter 6: Handling Messages



This chapter describes how MFC processes messages and explains how to connect messages to their corresponding handler functions using the ClassWizard and WizardBar tools.


While there are many different types of messages, this chapter focuses on Windows messages (those generated by the Microsoft Windows operating system) and command messages (those coming from user interface objects, such as menus, toolbar buttons, and accelerator keys). Other types of MFC messages are also briefly introduced.


After completing this chapter, you will be able to:


®  Define what a message is in the Windows operating system.


®  List the types of Microsoft Foundation Class (MFC) Library messages.


®  Describe the purpose and benefits of message maps.


®  Declare and implement a message map.


®  Describe how messages are processed by the MFC framework.


®  Create the framework for a simple MDI application.


®  Use ClassWizard and the WizardBar to add or delete an event's message handler.


®  Implement a handler member function.


®  Add a message box to a handler function to provide information to the end user.


 



Introduction to Messages



Messages are the primary way that MFC applications are notified of events; they are central to the event-driven programming model used in the Windows operating system. The purpose of messages is to notify your application that an event has occurred. The application's behavior is defined by how it responds to a message.


MFC applications process Windows messages much as any other application for Windows does. But MFC simplifies and enhances the Windows message handling functionality by using a message mapping system and the command target class, CCmdTarget.


This section explores the types of messages generated by the Windows operating system and introduces the message mapping system used in MFC applications. This section includes the following topics:


®  Types of Messages


®  Message Maps


®  Message Mapping vs. Virtual Functions


 


For a complete list of standard Windows messages, see the Visual C++ online book, Win32 Programmer's Reference, "Volume 5: Messages, Structures, and Macros."





  1. Types of Messages




Communication between the operating system, applications, and application components is conducted through various types of messages. For example, when creating an instance of an application, the operating system will send a series of messages to the application, which will then respond appropriately to initialize itself. Keyboard and mouse activity will cause the operating system to generate messages and send them to the proper application. User-interface components, like command buttons and list boxes, will generate messages and send them to their parent windows.


MFC extends and organizes the concept of messages by dividing them into the following categories:


®  Windows messages


®  Command messages


®  User interface update command messages


®  Event-notification messages


®  Custom control messages


®  System-registered messages


®  User-defined messages


 


This topic focuses primarily on the first two types of messages: Windows messages and command messages.


Windows Messages


Windows messages are generally defined as those messages generated by the Windows operating system. They inform the application about window creation, impending window destruction, mouse and keyboard events, changes to the system default colors, and anything else that may impact the operation of the application. For example, one of the most important messages is WM_PAINT. This message is sent by Windows to an application window to indicate that a portion of the window's drawing area needs repainting.


A very important fact is that Windows messages are sent to the window and can only be handled by a window object. These messages are not routed to other classes for processing.


Command Messages


Command messages are generated by the user when selecting menu items, clicking toolbar buttons, or pressing shortcut keys (accelerator keys). Whenever one of these events occurs, a WM_COMMAND or WM_message containing command-specific information is sent to the application.


In contrast to Windows messages, command messages get routed to various application objects or classes for processing. This allows your application to handle the message in the class most closely associated with the message.


User Interface Update Command Messages


User interface update command messages are created within an application by the application framework; that is, they are MFC specific. They signal the application to update the state of user-interface elements such as menu items, toolbar buttons, and status-bar panes. For example, before a menu is displayed, the application framework will send the application an appropriate update command message that gives it an opportunity to modify the menu item state (i.e., enabled/disabled/grayed/checked) based upon the current status of the application.


Event Notification Messages


Event notification messages are sent from a child common-control window to its parent. For example, when the user types a character in an edit box, the edit box control sends an EN_UPDATE message to the parent window (usually a dialog box). This notifies the parent window that its contents are about to change.


Custom Control Messages


Custom control messages are similar to event notifications, but are used by custom controls to send messages to their owner window — usually a dialog box. One of the best examples of this is the WM_CTLCOLOR message. This message is sent to a parent to allow it to become involved in the control's painting process.


System-Registered Messages


The Windows messaging system can be extended by the creation of new program-defined messages that are registered with the operating system at run time. These system-registered messages are available to all applications.


User-Defined Messages


A user-defined message is any message that is not a standard Windows message. By creating a user-defined message (as opposed to using a function call), you can take advantage of the Microsoft Windows messaging system.


Although not commonplace in an MFC application, a window object can define its own private messages to allow other objects to communicate with it through the Windows messaging system. Message numbers that begin with the WM_USER value (0X400) are designed for this purpose.


In general, a window object provides access functions instead of using these private messages.





  1. Message Maps




A message map is a table that correlates messages with the member functions an application provides to handle those messages. Each entry in the table consists of a message-specific macro. Message maps are used to handle both Windows messages and command messages.


What MFC does internally to implement message maps is hidden behind some fairly complex macros and processes. However, creating and using a message map is a simple process. In fact, most of the work is done for you by AppWizard. Here are the steps to add a message map to a class:


       1.   Declare the message map by adding a DECLARE_MESSAGE_MAP statement to the class declaration. AppWizard adds this code to the header file, xxx.h.


       2.   Create and initialize the message map by placing message map macros identifying the messages that the class will handle between the statements BEGIN_MESSAGE_MAP and END_MESSAGE_MAP. AppWizard adds this code near the beginning of the implementation file, xxx.cpp.


       3.   Add member functions to the implementation file to handle the messages.



Example of a Message Map


The following is an example of a message map for the view class CMyView.


BEGIN_MESSAGE_MAP(CMyView, CView)


                     ON_WM_CREATE()


                     ON_COMMAND(ID_APPLY_SEQUENCE, OnApplySequence)


END_MESSAGE_MAP()


 


This message map has two entries: one to handle the Windows message WM_CREATE, and one to handle the command message, ON_COMMAND. The BEGIN_MESSAGE_MAP macro includes the base class CView as one of its arguments so that the framework can continue searching for a given handler if one does not exist within the derived class.







Adding MFC Debugging Support

Adding MFC Debugging Support

The Microsoft Foundation Class (MFC) Library and Visual C++ help you debug your applications in various ways. This section presents a few useful general debugging techniques, followed by more detailed debugging topics.

This section includes the following topics:

Using MFC Functions and Macros

Microsoft Visual C++ 5.0 introduces debug support for the C run-time library. The new debug version of the library supplies many diagnostic services that make debugging programs easier. This section describes some of the debugging routines and macros used for diagnostic purposes.

This section includes the following topics:

C Run-Time Library Debugging Support

Visual C++ adds extensive debugging support to the C run-time library, enabling you to step directly into run-time functions when debugging an application. The library also provides a variety of tools to keep track of heap allocations, locate memory leaks, and find other memory-related problems.

Much of the heap-checking technology included in the debug version of the C run-time library has been moved from the Microsoft Foundation Class Library. To use the heap-checking technology, you must now link debug builds of MFC applications with a debug version of the run-time library.

The library contains debug reporting functions, including:

® _CrtDbgReport and _CrtIsValidPointer; macros for verification and reporting

® _ASSERT and _RPTn; functions that use a debug heap

® Debug versions of malloc, free, calloc, realloc, new and delete

® Heap-monitoring functions, such as _CrtCheckMemory and _CrtDumpMemoryLeaks


The library also includes functions, such as _CrtSetDumpClient and _CrtSetAllocHook, which enable you to write and install your own hook functions with special features you need when debugging a complex application.

To use these routines, you must define the_DEBUG flag. These routines do nothing in a retail build of an application. The C run-time debug functions are available for Windows 95 and Windows NT. For more information about how to use the new debug routines, see "Using C Run-Time Library Debugging Support" in the Visual C++ online documentation.

Run-Time Debugging Routines

The run-time debugging routines are only active when you run an application built with debug information included. Unlike error-checking, assertions do not decrease execution speed, because the code "disappears" in release builds. This section describes the ASSERT routine, the VERIFY routine, the CObject::AssertValid function, and the ASSERT_VALID macro.

ASSERT Routine

The ASSERT routine is used to ensure a specific assumption. If the assertion is false, the macro displays an assertion message box containing the source file name and line number. The user is given the choice of terminating or debugging the program. This macro is commonly used to validate function arguments and return values.

CWnd* pWnd = GetParent();

ASSERT(pWnd != NULL);

Note Debug versions of the MFC Library make extensive use of assertions. A list of common MFC assertions and their causes can be found in the article "Foundation Classes Common Asserts, Causes, and Solutions” in the Visual C++ online documentation.

VERIFY Routine

The VERIFY routine evaluates the condition in the Debug and Release environments, but prints and terminates (if appropriate) only in the Debug environment. VERIFY is very similar to ASSERT when you are in Debug mode. In Release mode, however, the contained expression is executed — but not verified. VERIFY is useful for wrapping function calls that return a pointer.

CObject::AssertValid Function

This debug function determines whether the associated object is internally valid. All MFC Library classes override this function to provide for internal consistency checking. When you create a reusable class, you should override CObject::AssertValid.

ASSERT_VALID Macro

MFC uses the ASSERT_VALID macro to force a call to an object's AssertValid function. Typically, whenever a function is expecting a valid CObject or CObject pointer as a parameter, the function should use the ASSERT_VALID macro to validate the object. As with the ASSERT macro, ASSERT_VALID is called only in a Debug build, as shown in the following sample code:

CShapesDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

Debugger-Enhancing Routines

When you run an application under the integrated debugger, you may find debugger-enhancing routines useful. The information that these functions provide is displayed in the output window of the debugger. This topic briefly describes the TRACE macro and the CObject::Dump function.

TRACE Macro

The TRACE macro provides a way to place formatted output strings into the debug stream; it is similar to the C run-time printf statement. For example,

TRACE("The number of rectangles is now %d", nRect);

CObject::Dump Function

The Dump function causes the internal state of an associated object to be displayed in an output window.

Under Debug mode, the MFC framework automatically calls the Dump function for any CObject objects not properly destroyed on application termination. Therefore, when you write your own class, you should override the Dump function for the base class to provide diagnostic services for your derived class. The overridden Dump usually calls the Dump function of its base class before printing data members unique to the derived class. CObject::Dump prints the class name if your class uses the IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL macros.

Note Your Dump function should not print a newline character at the end of its output.

When you call Dump for an object, you must supply a single argument of type CDumpContext. The global object afxDump is provided for this purpose.

For more information about the MFC diagnostic services, see "Diagnostics" in the online MFC Encyclopedia, and the MFC Technical Note TN7: "Debugging Trace Options" in the Visual C++ online documentation.

Using Tracer

To help debug Windows-based programs, MFC provides a Tracer program. Tracer.exe is a small MFC Programming Utilities sample program that displays, in a debugging output window or console window, messages about the internal operation of the MFC Library, as well as warnings and errors if something goes wrong in your application. You can view as much or as little debugging information as you want.

Tracer will often warn you about problems, and provide more detailed explanations of errors.

Using Tracer

Tracer enables you to set the options in Afx.ini, and is installed in your Bin directory by Visual C++ Setup. A sample Afx.ini file is provided in the Mfc\Src subdirectory. This .ini file turns on diagnostic messages and uses the standard options. You should place this Afx.ini file in your Windows directory, or run Tracer.exe to create a new Afx.ini file and set options. Changes to Afx.ini will take effect in any debug MFC application launched after the changes are saved.

The global integer afxTraceFlags is used to turn on the built-in reporting features of MFC and to store all flags. Global integer afxTraceFlags uses each bit to select a trace reporting option. You can turn any bit on or off, thereby altering the generated report information. The numeric values associated with each option are provided in the Afxwin.h header file.

To run Tracer, click MFC Tracer on the Tools menu. The MFC Trace Options dialog box will appear, providing eight trace options. The first option, Enable tracing, turns tracing on or off. The other seven options enable you to select which types of trace messages will be sent to the debugging window or console.



For more information about Tracer options, see Technical Note 7: "Debugging Trace Options" in the Visual C++ online documentation.

u To turn on Tracer output

1. Compile your program with the _DEBUG symbol defined, and link with a debug version of the MFC Library. Debugging and trace options are available only in the debug version of the Library.

2. Enable the afxTraceEnabled flag. You can do this in several ways; using Tracer to do so is recommended.

3. Customize afxTraceFlags to determine the level of detail you want in Tracer messages.

Where the Output Goes

When afxTraceEnabled is true, then Tracer output (and default afxDump output) will go to the output window if present. When afxTraceEnabled is false, Tracer output and afxDump output will not be displayed.

If a debugger is present, Tracer output will go to the debugger's output window. If no debugger is present, you will not be able to see Tracer output.

Using Spy++

Spy++ (Spyxx.exe) is a Win32-based utility that gives you a graphical view of the system's processes, threads, windows, and messages.

Spy++ has a toolbar and hyperlinks to help you work faster. It also provides a Refresh command to update the active view, a Window Finder Tool to make spying easier, and a Font dialog box to customize view windows. Additionally, Spy++ saves and restores user preferences.

Similar to Spy++, the PView process viewer (PView.exe) enables you to examine and modify many characteristics of the processes and threads running on your system.

To see a demonstration showing how to use the Spy++ utility to view the system's processes, threads, windows, and messages, click this icon.

v

For more information about the Spy++ or PView process viewer utilities, see "Spy++ Home Page" in the Visual C++/Windows Utilities online documentation.


Self-Check Questions



1. After preparing a debug version of your project, why is it necessary to rebuild the project for release?

v A. When a project is compiled for a Debug build, the _DEBUG preprocessor is defined. In a Release build, the

_NDEBUG preprocessor is defined.

v B. The Debug version uses a different set of DLLs than the Release version.

v C. The default for the Release version of a project is optimized for speed and performance.

v D. All of the above.



2. Which one of the following statements is false when using the Developer Studio debugger to set and manage breakpoints?

v A. You can disable an individual breakpoint or you can disable all breakpoints in an application.

v B. The breakpoints you set cannot be saved as part of your project.

v C. To set a breakpoint on a source statement extending across two or more lines, you must set the breakpoint

on the last line of the statement.

v D. An asterisk (*) in the Breakpoint check box indicates that the breakpoint is not supported on the current

platform.



3. What kind of information do Visual C++ browse information files provide?

v A. Information about the symbols (classes, functions, data, macros, and types) in a program.

v B. The relationships between all the files in a project.

v C. Debugging messages for ActiveX components.

v D. All of the above.



4. Which one of the following statements applies to the MFC VERIFY macro?

v A. Used to validate function arguments that return a value rather than a pointer.

v B. VERIFY is very similar to ASSERT when you are in Release mode.

v C. Evaluates a condition or expression in Debug and Release mode.

vvvvvvv D. Prints an error message and terminates (if appropriate) in Debug and Release mode.


Lab 5.1: Using Debugger


In this lab, you will fix errors, build, and run an MFC application using the Developer Studio debugger.

To see a demonstration that shows what you will accomplish during the lab, click this icon.

v

Estimated time to complete this lab: 35 minutes

To complete the exercises in this lab, you must have the required software. For detailed information about the labs and setup for the labs, see Labs in this course.

Objectives

After completing this lab, you will be able to:

® Build and run debug versions of a sample MFC application.

® Use debugging techniques to fix application errors.

® Use the Tracer program to monitor the values of a variable in the application.

® Use the Step Into debugging feature to step through the functions in a sample application.



Prerequisites

There are no prerequisites for this lab.

Exercises

The following exercises provide practice with the concepts and techniques covered in this chapter.

® Exercise 1: Fixing Application Errors

In this exercise, you will use the Microsoft Developer Studio debugger to find and fix a printing problem in a sample application.

® Exercise 2: Stepping Through an Application

In this exercise, you will use the Step Into debugging feature to explore a sample application function by function.



  1. Exercise 1: Fixing Application Errors


In this exercise, you will use the debugging techniques to correct a printing problem in a sample application, TextReader. The TextReader application is similar to the Reader application discussed in Chapter 4: Analyzing a Document/View Application.

You can find the code that forms the basis for this exercise in \Labs\Ch05\Lab01\Baseline. Copy these files to your working directory.

u Build the application in Debug mode

1. In Developer Studio, open the TextReader project.

2. On the Build menu, click Set Active Configuration. Select the Debug version of the TextReader application, and then click OK.

3. Build the TextReader application.



u Run the application

1. In Developer Studio, on the Build menu, point to Start Debug, and then click Go.

2. On the File menu, click Open, and then open any text file. View the file on the screen.

3. On the File menu, click Print Preview. Notice that the lines are chopped in the print preview.

4. Close the application.



u Debug the application

1. Switch back to Developer Studio.

2. In the ClassView pane, double-click the member function CTextReaderView::OnDraw to open the code associated with it.

3. Add the following lines of code before the For loop to correct the chopped lines problem:

int nYDelta = 0;TEXTMETRIC tm;

pDC->GetTextMetrics(&tm);

nYDelta = tm.tmHeight;



The TEXTMETRIC structure contains basic information about a physical font. And GetTextMetrics retrieves the metrics for the current font.

4. Insert a TRACE statement inside the For loop to enable tracing:

TRACE( "nYDelta = %d\n",nYDelta );



5. On the Tools menu, click MFC Tracer. Select the Enable tracing check box, and then click OK. This will start the Tracer application.

6. Build and run the application in Debug mode.

7. Open a text file in your TextReader application.

8. From the View menu, click Output. Monitor the value of nYDelta in the output window located at the bottom of the screen. This variable indicates the height of the character.

9. On the File menu, click Print Preview.

10. Monitor the value of nYDelta. Notice the change in the nYDelta value.

11. Exit the TextReader application and the Tracer application.

12. Open the CTextReaderView::OnDraw member function. Change the nYPos statement from the following:

nYPos +=15;



to:

nYPos +=nYDelta;



u Build and run the TextReader application

— Rebuild and run the project. When printing the text or viewing the text on the screen, the output should be correct; in other words, the lines should not be chopped.



You can find the completed code for this exercise in \Labs\Ch05\Lab01\Ex01.



  1. Exercise 2: Stepping Through an Application



In this optional exercise, you will use the debugger to step through the application created in Lab 4.1: Hand-Coding a Minimal MFC Application. You can explore WinMain and the built-in MFC functions supplied by the framework using the debugger.

You can find the code that forms the basis for this exercise in \Labs\Ch04\Lab01\Ex01. Copy these files to your working directory.

u Explore MFC function using the integrated debugger

1. On the Build menu, point to Start Debug, and then click Step Into (or press F11).

2. The debugger will start and place you in the WinMain function of the implementation file, AppModul.cpp, as follows:

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance, LPTSTR lpCmdLine,

int nCmdShow)

{

// call shared/exported WinMain

return AfxWinMain(hInstance, hPrevInstance,

lpCmdLine, nCmdShow); }



3. Press F11 two more times and you will be exploring AfxWinMain. As you step through the code, you will find all the expected calls.

Jessica Beil














Jessica Beil jessica beil jessica's beil's collection of screen saver huge Photo Gallery of Share hot Sexy clip of video of Movies Videos Watch video about boom hott,scene fearless myspace FEARLESS Lyrics - Music site for music videos, songs, photos, live performances and more Music video Pictures, Biography, Discography, News, Ringtones American Music Awards Nominees ... one of country-pop's brightest ! Picture, Video, Wallpaper, Profile, Gossip, and News at Celebrity Women Celebrities Profile – Biography, Latest Photos, Pics, News, Gossip, Comments, Success and Sexiness Rating! Check out Get the latest news, pictures and videos and learn all about from Hollyscoop, your celebrity news source Picture, Video, Wallpaper, Profile, Gossip, and News at Celebrity sports illustrated project pictures of Recent images Hot! View the latest photos. Large gallery of pics hot photos, hot pictures, news, videos, movies, songs, lyrics, music albums, filmography, discography, biography Photos, Bio, News and Message Board on TVGuide pictures and photos in a high quality gallery of the beautiful born supermodel Fansite with blogs, news, filmography, awards, video, wallpaper and anything and everything about Super sexy model Gallery - Home Gallery Videos Forum Personal News Links Contact Editorial Covers Campaigns Events Extras Secret News - SEXY EVENING GOWN Pictures, Videos, Wallpapers, Screensavers, Downloads, News Headlines and Linkshe - photo galleries, information, tags, stats picture sexy bikni free celebrities, 3d , actress, art nature, travel, abstract, game, car Get free Desktop Wallpapers for your PC. Fast and Easy Satanic Celebrities?The Horned Hand - Not Just Rock? Free to Join - Online Fellowships Celebrity Charity Profile - Check out the latest Cecile de France photo gallery, biography, pics, pictures, interviews, news, forums and blogs Sexy Pictures, Sexy Girls naked, beautiful girls sexy, black girls sexy, asian girls sexy, Lesbians pictures, big small images, lady pictures ownload latest bollywood actor, fan club, biography, roles, images, photos, profile news, gossip, photos of biography, boyfriend and relationship info Hindi music, Indian songs, Bollywood Movie soundtracks, desi videos, trailors and news. Hindi, Tamil, Telugu and Malayalam Songs MUMBAI, India: Bollywood beauty got engaged to London-based millionaire businessman at his Mumbai apartment Bollywood Actors Actresses Directors Bollywood Movies, Bollywood DVD, Hindi Movies, Hindi DVD, Punjabi Movies, Punjabi DVD, DVD, Songs Check out Actress Latest News, Photos, Videos, Actress Images, Pictures, Gallery, Photo Gallery information about of Cruise with Celebrity Cruises - Voted one of the World's Best Cruise Lines by Condé Nast Traveler - Cruise deals on top-rated vacation cruises to premier Celebrity photo, video, and gossip blog featuring the latest hot celebrities including Nude Celebrities, celebrity Sex, Pussy, Upskirts, Thong Slips, Tit Slips, Celebrity Sex Tapes, Sex Pictures Offers celebrity news, new movie reviews, trailers and celeb photos lyrics, Profile, Biography, Credits, Image Gallery

Thursday, November 19, 2009

Using Developer Studio Debugger

Using Developer Studio Debugger

The debugging tools in Developer Studio enable you to test your C++, MFC, and mixed-language applications. You can set and manage breakpoints, view and modify variables, step through your application, and interpret the call stack. The Visual C++ browse windows described later in this section enable you to view the relationships between symbols, variables, and classes. "Just-in-time" debugging, described later in this section, enables you to run your application outside the Developer Studio environment.

During debugging, you can stop the process to examine the state of an executable application, a dynamic-link library (DLL), threads, or an ActiveX control, at nearly any point during application execution.

Debugging is a two-step process. First, you correct compile-time errors that prevent you from building your project, such as incorrect syntax, misspelled keywords, or type mismatches. Then you use the Developer Studio debugger to detect and correct logic errors and errors in sequencing, branching, and interaction between application components.

This section describes the debugging tools and techniques used to resolve common programming problems with MFC projects written in Visual C++. This section includes the following topics:

Setting and Managing Breakpoints

Use the Breakpoints dialog box to set, remove, disable, enable, or view breakpoints. On the Edit menu, click Breakpoints. The Breakpoints dialog box will appear.

Setting Breakpoints

The breakpoints you set will be saved as a part of your project. You can set breakpoints in the following places:

® At a source-code line

® At the beginning of a function

® At the return point of a function

® At a label

To set a breakpoint at a source-code line

1. In a source window, move the insertion point to the line where you want the program to break.

2. Click the Insert/Remove Breakpoint toolbar button (a hand) on the Build MiniBar toolbar.

A red dot appears in the left margin, indicating that the breakpoint has been set. To see an illustration that shows an example of code with a breakpoint set, click this icon.

Note If you want to set a breakpoint on a source-code statement extending across two or more lines, you must set the breakpoint on the last line of the statement.

To set a breakpoint at the beginning of a function

1. In the Find box on the Standard toolbar, type the function name.

2. Click the Insert/Remove Breakpoint toolbar button.

In the source code, a red dot appears in the left margin at the beginning of the function, indicating that the breakpoint has been set.
To set a breakpoint at the return point of a function

1. On the View menu, point to Debug Windows, and then click Call Stack.

2. In the Call Stack window, move the insertion point to the function where you want the program to break.

3. Click the Insert/Remove Breakpoint toolbar button.

A red dot appears in the left margin, indicating that the breakpoint has been set.

To set a breakpoint at a label

1. In the Find box on the Standard toolbar, type the name of the label.

2. Click the Insert/Remove Breakpoint toolbar button.

A red dot appears in the left margin at the line containing the label, indicating that the breakpoint has been set.

If you set more than one location breakpoint on a line, and some breakpoints are disabled while others are enabled, a gray dot will appear in the left margin. The first time you click the Enable/Disable Breakpoint toolbar button, all breakpoints on the line will become disabled, and the gray dot will change to a hollow circle. If you click the Enable/Disable Breakpoint button again, all breakpoints on the line will become enabled, and the hollow circle will change to a red dot.

An asterisk (*) in the Breakpoint check box indicates that the breakpoint is not supported on the current platform.

Viewing Breakpoints

You can view the list of current breakpoints or you can view the source code or disassembled code where a breakpoint is set.

To view the list of current breakpoints

1. On the Edit menu, click Breakpoints.

2. Use the scroll bar to move up or down the Breakpoints list.

To view the source code or disassembled code where a breakpoint is set

1. In the Breakpoints list, select a line-number breakpoint.

2. Click Edit Code.

You will see the source code for the breakpoint set at the line number.

Disabling Breakpoints

You can disable an individual breakpoint, or you can disable all breakpoints in an application.

To disable a single breakpoint

1. For a location breakpoint in a source-code window or in the Call Stack or Disassembly window, move the insertion point to the line containing the breakpoint you want to disable.

2. Click the Enable/Disable Breakpoint toolbar button, or click the right mouse button, and click Disable Breakpoint on the shortcut menu.

– or –

1. In the Breakpoints dialog box, find the breakpoint you want to disable in the Breakpoints list.

2. Clear the check box corresponding to the breakpoint that you want to disable, and then click OK.

When a location breakpoint is disabled, the red dot in the left margin changes to a hollow circle.

– or –

— Use the SPACEBAR to toggle the state of one or more breakpoints in the Breakpoints list.
To disable all breakpoints

— Click the Disable All Breakpoints toolbar button.

The red dots in the left margin change to hollow circles.

Stepping Through an Application

The Developer Studio debugger enables you to step through your application in two ways. You can:

® Run the application and execute the next statement (Step Into).

® Step into a specific function.


To run the application and execute the next statement (Step Into)

1. While the application is paused at a breakpoint, click Step Into on the Debug menu.

The debugger executes the next statement, then pauses execution. If the next statement is a function call, the debugger steps into that function, then pauses execution at the beginning of the function.

2. Repeat Step 1 to continue executing the application one statement at a time.

If you step into a nested function call, the debugger steps into the most deeply nested function. For more information and examples about debugging nested functions, see "Stepping Into Functions" in the Developer Studio online documentation.

To step into a specific function

1. Set a breakpoint just before the nested function call, or use the Step Into, Step Over, or Run To Cursor command to advance the application execution to that point.

2. In a source window, select the function that you want to step into.

3. On the Debug menu, or on the shortcut menu associated with a source window, click Step Into Name, where Name is the selected function.

The debugger executes the function call and pauses execution at the beginning of the selected function.

Step Into Specific Function works for any number of nesting levels. You can sometimes use Step Into Specific Function to step into a member function — for example, MemberFn in the line of C++ code CMyClass::MemberFn();.

Viewing and Altering Variables

You can use the Developer Studio debugger to view and alter variables.

Viewing Variables

The Developer Studio debugger gives you several options for viewing variables and expressions. You can view:

® The value of a variable or expression.

® The value of a variable using QuickWatch.

® A variable or expression in the Watch window.

® Type information for a variable in the Watch window.

® A variable in the Variables window.

® Type information for a variable in the Variables window.

To view the value of a variable or expression

— Pause the mouse pointer over the variable or expression until a pop-up window displays the variable's value.

To view the value of a variable using QuickWatch

1. When the debugger is stopped at a breakpoint, switch to a source window and right-click a variable (Var, for example).

2. On the shortcut menu, click QuickWatch.

3. Click Recalculate.

The value will be displayed in the spreadsheet field.

4. Click Close.


To view a variable or expression in the Watch window

1. On the View menu, point to Debug Windows, and then click Watch.

2. Select a tab for the variable or expression.

3. Type, paste, or drag the variable name or expression into the Name column on the tab. If you typed the variable name, press ENTER.

The Watch window evaluates the variable or expression immediately and will display the value or an error message.

If you add an array or object variable to the Watch window, plus sign (+) or minus sign (–) boxes will appear in the Name column. Use these boxes to expand or collapse your view of the variable. You can change the display format (to display Unicode characters, for example) of variables in the QuickWatch dialog box or in the Watch window using formatting symbols. For more information, see "Symbols for Watch Variables" in the Developer Studio online documentation.

To view type information for a variable in the Watch window

1. In the Watch window, select the line containing the variable whose type you want to see.

2. On the View menu, click Properties.

To view a variable in the Variables window

1. On the View menu, point to Debug Windows, and then click Variables.

2. Click the Auto tab, Locals tab, or This tab, according to the type of variables you want to see.

To view type information for a variable in the Variables window

1. In the Variables window, click the Auto tab, Locals tab, or This tab.

2. Select the line containing the variable whose type you want to see.

3. On the View menu, click Properties.

Altering Variables

The Developer Studio debugger gives you several options for altering variables and expressions. You can modify the value of a variable:

® Using QuickWatch.

® Using the Watch window.

® In the Variables window.

To modify the value of a variable using QuickWatch

1. On the Debug menu, click QuickWatch.

2. In the Expression text box, type the variable name.

3. Click Recalculate.

4. If the variable is an array or object, use the plus sign (+) box to expand the view until you see the value you want to modify.

5. Use the TAB key to move to the value you want to modify.

6. Type the new value, and then press ENTER.

7. Click Close.

Note To change the value of an array, modify the individual fields or elements. You cannot edit an entire array at once.

To modify the value of a variable using the Watch window

1. In the Watch window, double-click the value, or use the TAB key to move the insertion point to the value you want to modify.

2. If the variable is an array or object, use the plus sign (+) box to expand the view until you see the value you want to modify.

3. Type the new value, and press ENTER.

To modify the value of a variable in the Variables window

1. In the Variables window, click the Auto tab, Locals tab, or This tab.

2. Select the line containing the value you want to modify.

3. If the variable is an array or object, use the plus sign (+) box to expand the view until you see the value you want to modify.

4. Double-click the value, or use the TAB key to move the insertion point to the value you want to modify.

5. Type the new value, and press ENTER.


  • Viewing the Call Stack

You can use the Developer Studio debugger to view and change the call stack for a function.


To view the call stack for a function

1. Place the insertion point in the function.

2. On the Debug menu, click Run to Cursor to execute your application to the location of the insertion point.

The Locals tab of the Variables window is updated automatically to display the local variables for the function or procedure.

3. On the View menu, point to Debug Windows, and then click Call Stack.

The calls are listed in the calling order, with the current function (the most deeply nested) at the top. To jump to the location in the code where a function is implemented, double-click the function name in the call stack. To see an illustration that shows how an application, a call stack, and the floating debugger can be displayed together, click this icon.


Note To run the application to the return address, select the function in the Call Stack window, and click Run to Cursor on the Debug menu.

To set or remove a breakpoint at a function return address, select the function in the Call Stack window, and click the Insert/Remove Breakpoint toolbar button.

To change the call stack display


1. On the Tools menu, click Options.

2. Click the Debug tab.

3. In the Call Stack window, select Parameter Values or Parameter Types, according to the information you want to display.

Note The Context box at the top of the Variables window contains a drop-down list of call stack functions. If you select one of these, the debugger window views will change accordingly. You cannot use the call stack to trace back through Windows messages.

Running to a Specific Location

When debugging your application, you can choose to run the application until you reach a specific location. You can:

® Run until a breakpoint is reached.

® Run to the cursor location.

® Run to the cursor location in object code.

® Run to the cursor location in the call stack.

® Run until reaching a specified function.

® Set the statement you want to run next.

To run until a breakpoint is reached

1. Set a breakpoint.

2. On the Build menu, point to Start Debug, and then click Go.

To run to the cursor location

1. Open a source file, and move the insertion point to the location where you want the debugger to break.

2. On the Build menu, point to Start Debug, and then click Run to Cursor.

To run to the cursor location in object code

1. On the View menu, point to Debug Windows, and then click Disassembly.

2. In the Disassembly window, move the insertion point to the location where you want the debugger to break.

3. On the Debug menu, click Run to Cursor.

To run to the cursor location in the call stack

1. On the View menu, point to Debug Windows, and then click Call Stack.

2. In the Call Stack window, select the function name.

3. On the Debug menu, click Run to Cursor.

To run until reaching a specified function

1. In the Find box on the Standard toolbar, type the function name.

2. On the Build menu, point to Start Debug, and then click Run to Cursor.


Note You can use the Run to Cursor command to return to an earlier statement to retest your application, using different values for variables.

To set the statement you want to run next

1. In a source window, move the insertion point to the statement or instruction that you want to run next.

2. Right-click the mouse, then click Set Next Statement on the shortcut menu.

Using Visual C++ Browse Windows

The Visual C++ browse windows display information about the symbols (classes, functions, data, and macros) in a program. If you turn on browse information when building a project, the compiler creates .sbr files with information about each program file in the project. The BSCMAKE utility (BSCMake.exe) assembles these .sbr files into a single browse information file that includes the project's base name and the extension .bsc.

You view browse information in browse windows that have different appearances and different controls, depending on the type of information displayed. By using browse commands, you can examine:

® Information about all the symbols in any source file.

® The source-code line in which a symbol is defined.

® Each source-code line where there is a reference to a symbol.

® The relationships between base classes and derived classes.

® The relationships between calling functions and called functions.

When you open a project workspace, the project browse file will open automatically. You can enable the browser, disable the browser, and open or close the browse information files.

To enable or disable creation of the .sbr files at compile time

1. Open the project if it is not open.

2. On the Project menu, click Settings. To see an illustration that shows the Project Settings dialog box, click this icon.





3. Click the C/C++ tab.

4. Select or clear the Generate browse info check box, and then click OK.


To enable or disable updating of the .bsc file at compile time

1. Open the project if it is not open.

2. On the Project menu, click Settings.

3. Click the Browse Info tab.

4. Select or clear the Build browse info file check box, and then click OK.

Note Once browse files have been generated for the project, you can access a floating Browse menu. Right-click anywhere on the Developer Studio toolbar to display a pop-up menu. Click Browse, and the Browse toolbar will appear. Use the Browse toolbar buttons to obtain browse information for your project.

If you do not need browse information, you can speed up the build process by turning off browse information. When the browse option is off, .sbr files are not generated, and the .bsc file is not updated.

To speed up your builds and update your browse information file quickly, turn on creation of .sbr files and turn off updating of the .bsc file. When you want to update your browse information file, turn on .bsc file updating, and then build your project.

To open or close the browse information file

— On the Tools menu, click Source Browser to open browse files or Close Source Browser File to close browse files, and then click OK.

Note When you use a browse information file, the .bsc file stays open for the duration of the session unless you close it. If you run NMAKE outside the development environment, you should close the .bsc file to allow updating. As long as the .bsc file remains open, it cannot be updated.

Enabling Just-in-Time Debugging

In Developer Studio, you can edit, compile, link, debug, and test an application in a single integrated environment. However, sometimes you may want to test an application outside the Developer Studio environment. With just-in-time debugging, you can run an application outside Developer Studio; when an application error occurs, just-in-time debugging calls the Developer Studio debugger.

To use just-in-time debugging, set the just-in-time debugging option before you execute your program. If you do not set this option, the debugger cannot respond to errors.
To enable just-in-time debugging

1. On the Tools menu, click Options.

2. Click the Debug tab.

3. Select the Just-In-Time Debugging check box, and then click OK.

4. On the Build menu, click Build <projectname>.exe.

Note If you are running Windows NT, you must have Administrator privileges to set the just-in-time option

Wednesday, November 18, 2009

Chapter 5: Debugging

Chapter 5: Debugging

This chapter examines the tools available for debugging Microsoft Foundation Class-based applications. You will learn how to prepare a project for debugging, build a project in debug mode, and enable various debugging options.

After completing this chapter, you will be able to:

® Prepare MFC projects for debugging.

® Use Developer Studio debugger and Visual C++ debugging tools.

® Add MFC debugging support to an application.

The Debugging Environment

Debugging is the process of correcting or modifying your code so that your project can build cleanly, run smoothly, perform as expected, and be easy to maintain.

The Developer Studio debugger provides menus, windows, dialog boxes, and spreadsheet fields to help you track down errors. You can use drag-and-drop functionality to move debug information between components.
This section includes the following topics:

Debug Build vs. Release Build

When you create a project in Developer Studio, you can build a debug version or a release version of a project. The debug version uses a different set of DLLs than the release version. Only release versions of a project can be distributed due to licensing restrictions on the DLLs used for debugging.

When you create a debug version of a project using the default settings, Developer Studio provides full symbolic debugging information in Microsoft Format. By default, no optimization features are set; generally, optimization makes debugging your program more difficult. By default, the release version of a project is optimized for maximum speed and performance; it includes no symbolic debugging information.

To build a debug version of your project using the default settings

1. On the Project menu, click Settings.

2. In the Project Settings dialog box, select Win32 Debug, and then click OK to select the default settings.

3. On the Build menu, click Set Active Configuration.

4. Build your program.

You can change the default debug options ; for example, you can instruct the compiler to output line numbers only, to generate a mapfile, or to redirect output.

Debugger Menus

Commands for debugging can be found on the Build menu, the Debug menu, the View menu, and the Edit menu. The following table describes the debugging menus.

Menu name Description

Build Contains a command called Start Debug, which contains a subset of the commands on the Debug menu. This subset of commands (Go, Step Into, and Run to Cursor) starts the debugging process.

Debug Appears in the menu bar while the debugger is running (even if it is stopped at a breakpoint); the floating Debug toolbar also appears. From the Debug menu, you can control program execution and open the QuickWatch window. When the debugger is not running, the Debug menu is replaced by the Build menu.

View Contains commands that display the various debugger windows, such as the Variables window and the

Call Stack window.

Edit Provides access to the Breakpoints dialog box, from which you can insert, remove, enable, or disable breakpoints.

For more information about the debugger menus, see "Debugger Menu Items" in the Developer Studio online documentation.

Debugger Toolbars

Developer Studio provides a floating debugger toolbar and a miniature debugger toolbar to make most common debugging tasks easier. To access the debugger toolbars, right-click in any blank area on the Developer Studio menu bar. A pop-up menu will appear. To see an illustration that shows the Developer Studio environment with the pop-up menu displayed, click this icon.




Click Debug on the pop-up menu to display the floating debugger toolbar.



You can keep the Debug toolbar open while debugging your applications. The Debug toolbar also can be moved, docked, or closed to suit your debugging needs. If you forget what a particular symbol on the Debug toolbar means, pause the mouse pointer over the symbol and its function will appear.

Click Build MiniBar on the pop-up menu to display the miniature debugging toolbar. To see what functions are available, pause the mouse pointer over the symbols and descriptions will appear. The MiniBar is useful for setting breakpoints, stepping through applications, and viewing variables.

Debugger Windows

Several specialized windows display debugging information for your program. The following table lists the available debugging windows: Output, Watch, Variables, Registers, Memory, Call Stack, and Disassembly, and describes what they do.

Window name Description

Output Displays information about the build process, including any compiler, linker, or build-tool errors, as well as output from the OutputDebugString function or the afxDump class library; thread termination codes; and first-chance exception notifications.


Watch Displays names and values of variables and expressions.

Variables Displays information about variables used in the current and previous statements and function return values (on the Auto tab); variables local to the current function (on the Locals tab); and the object pointed to by the specified address (on the This tab).

Registers Displays the contents of the general-purpose and CPU status registers.

Memory Displays the current memory contents.

Call Stack Displays the stack of all function calls that have not returned.

Disassembly Displays the assembly-language code derived from disassembly of the compiled program.

When you are debugging, you can access the Output window by clicking Output on the View menu. You can access the other debugging windows by pointing to Debug Windows on the View menu and then clicking on the appropriate debugging window.

Debugger windows can be docked or floating. When a window is in floating mode, you can resize or minimize the window to increase the visibility of other windows.

You can copy information from any debugger window. You can print information only from the Output window.

To set formatting and other options for these windows, on the Tools menu, click Options, then click the Debug tab.

For more information about debugger windows, see "Working with Floating or Docking Windows" and "Debugger Windows" in the Developer Studio online documentation.

® Debugger Dialog Boxes

You can use a number of debugger dialog boxes to manipulate breakpoints, variables, threads, and exceptions. Available debugger dialog boxes include Breakpoints, Exceptions, QuickWatch, and Threads. To access the Breakpoints dialog box, click the Breakpoints command on the Edit menu. All other debugging dialog boxes are available on the Debug menu. The following table describes the debugger dialog boxes.

Dialog box Description

Breakpoints Displays a list of all breakpoints assigned to your project. Use the tabs in the Breakpoints dialog box to create new breakpoints of various types.

Exceptions Displays system and user-defined exceptions for your project. Use the Exceptions dialog box to control how the debugger handles exceptions.

QuickWatch Displays a variable or expression. Use the QuickWatch dialog box to quickly view or modify a variable or expression, or to add it to the Watch window.

Threads Displays application threads available for debugging. Use the Threads dialog box to suspend and resume threads, and to set focus.

For more information about specific debugger dialog boxes, see "The Debugger Interface" in the Developer Studio online documentation.