1. Introducing Digital Mars C++

User Guide & Reference
User Guide & Reference

Welcome to the Digital Mars C++ for Windows 95, 98, ME, NT, 2000, XP, Visa, 7, Windows 3.1, DOS and DOS32. For a list of the Digital Mars C++ features, see features.

Table of Contents

This manual is divided into the following six parts:
Part 1: "Welcome to Digital Mars C++"
In addition to the current chapter, introducing the Integrated Development and Debugging Environment (IDDE).
Part 2: "Creating an Application with Digital Mars C++"
Guide to creating a first application in Digital Mars C++.
Part 3: "Learning Digital Mars C++ by Example"
Tutorial chapters on building DOS and Windows hypertext file reader applications.
Part 4: "More about Creating Programs"
IDDE settings, workspaces, the application framework designers, the class browsers, the text editor, and version control.
Part 5: "More about Testing Programs"
Debugging features of Digital Mars C++.
Part 6: "About Managing Resources"
How to use the Digital Mars ResourceStudio to create and edit resources.
Part 7: "Appendixes"
Appendixes on expression evaluation, the relationship between IDDE settings and command-line options, and the NetBuild feature.

Suggestions for the new users of Digital Mars C++

If you are new to Digital Mars C++, congratulations and welcome. We hope you find our product powerful and easy to use. Check out Introducing the IDDE and work through the tutorials in Part 3 to become proficient with Digital Mars C++ quickly.

Suggestions for users new to Windows development

If you are starting to program for Windows, Digital Mars C++ is a great platform. Read Generating an Application Framework, and Adding Look and Feel with Resources. Also you should read the tutorials in Part 3, which guide you through the development of a Windows application.

Suggestions for users porting to Digital Mars C++

If you need to port your code from another compiler or from a previous version of C++, read the Switching to Digital Mars C++ chapter in the Compiler & Tools Guide.

Suggestions for users upgrading to Digital Mars C++

If you are upgrading from a previous version of Digital Mars C++ and want to learn about the new product features, read Generating an Application Framework, Defining Classes and Their Hierarchies, Adding Look and Feel with Resources, More about AppExpress, and More about ClassExpress.

2. Introducing the IDDE

The IDDE is the Integrated Development and Debugging Environment. The IDDE comes with the CD version of the development system. This chapter introduces the Digital Mars C++ development system. The first part of the chapter describes the IDDE main window and toolboxes. The second part introduces Part Two of this manual, and outlines the steps involved in developing an application in the IDDE.

Running Digital Mars C++ under Windows 3.1, Windows 95, and Windows NT

Digital Mars C++ ships with three different integrated development and debugging environments (IDDEs), each tailored to a specific operating system and target. All IDDEs share the same user interface, and can build applications for DOS, Windows 3.1, Windows 95, Windows NT, and DOSX. Minor differences between the three IDDEs are noted throughout this manual, as appropriate. Not every IDDE can debug every kind of executable. To debug a Windows NT program, for example, you need the full 32-bit IDDE running under Windows NT.

Screen images in this manual may vary in appearance from one operating system to another.

Starting and exiting the IDDEs

To start the IDDE from the Program Manager, make sure that Digital Mars C++ is installed properly, then double-click on the appropriate IDDE icon in the Digital Mars C++ program group. The IDDE main window opens at the top of the screen.

To exit the IDDE, choose one of three commands from the IDDE File menu: Exit, Exit & Save All, or Exit & Discard. Exit leaves the IDDE and returns to the Program Manager. Exit & Save All exits and saves all the changes to the current project and options. Exit & Discard exits the IDDE without saving any changes to the current project or options.

IDDE Windows and Toolboxes

You can create, edit, and debug an application within the IDDE. The IDDE provides a variety of tools for use throughout the development process.

Unlike most Windows applications, the IDDE offers more than a single window in which to work. The IDDE is a feature-rich environment in which you work with multiple windows and toolboxes on the desktop. This section describes the general characteristics of those windows and toolboxes.

IDDE main window

The IDDE main window, shown in Figure 2-1, is positioned at the top of the desktop (workspace), which is the entire screen area. From the IDDE main window, open other windows on the desktop, load projects, set project options, and perform additional tasks. Most of the actual work, such as editing program code, is done in other windows on the desktop.

Figure 2-1 IDDE main window
[Figure 2-1 IDDE main window]

As shown in Figure 2-1, the IDDE main window has the following parts: system menu, title/status bar, main menu bar, and the minimize button. (Also shown is the Workspace toolbox docked below the main window. Docking means that the toolbox is attached to the IDDE main window, or the desktop edge.) The system menu and the minimize button are the standard Windows user interface elements. The other elements of the main window as well as the IDDE toolboxes are described in the following sections.

The title/status bar

The top line of the IDDE main window serves as both a title bar and a status bar. When you start the IDDE, the title bar displays the program name, Digital Mars C++. As actions occur in the IDDE, the title bar changes to a status bar and displays the status of the session, including the following information:

The menu bar

The IDDE main window menu bar is located below the title bar. Table 2-1 summarizes the functions of the IDDE menus.

Table 2-1 The IDDE menu functions
Menu Function
File Opening and closing text files, exiting the IDDE
Project Opening, closing, and editing projects, building the project, setting project options
Debug Switching into debugging mode, controlling program execution while debugging, setting debugging options
Environment Creating and using workspaces, customizing the IDDE
Resource Creating and editing resources
Tools Accessing AppExpress, ClassExpress, Global Find, and your own tools
Window Opening and arranging windows and toolboxes
Help Accessing online help

For information on how to choose menu commands, see your Windows, Windows 95, or Windows NT documentation.

The IDDE toolboxes

The IDDE includes the following four toolboxes:

Open a toolbox through the IDDE's Window menu. If the toolbox's name is checked, it appears in the workspace. If the name is not checked, select it to open the toolbox. The following sections describe the toolboxes in detail.

The Views toolbox

The Views toolbox, shown in Figure 2-2, is used to open the IDDE windows. Each of the IDDE windows is represented by an icon in the toolbox.

Figure 2-2 Views toolbox
[Figure 2-2 Views toolbox]

To open a window from the Views toolbox, click and drag the appropriate icon from the toolbox onto the desktop. Alternatively, double-click on the icon to open the window. To replace one window on the screen with another, drag the icon of the window you want into a window on the desktop. Table 2-2 lists the IDDE windows.

(Windows NT only)
Table 2-2 IDDE windows and their functions
Window name Function
Assembly Debugging; shows assembly-level source
Breakpoint Debugging; used to work with breakpoints
Call Debugging; shows call chain
Class Editor Used to edit class hierarchies
Command Line Debugging; provides CodeView-like interface to the debugger
Data/Object Debugging; shows local or global data
Function Debugging; shows the functions in the application
Graphic Data Debugging; shows a graphic representation of a data structure
Hierarchy Editor Used to edit class hierarchies
Inspector Debugging; shows local and global data
Output Shows output of compiler, linker, and parser
Memory Debugging; shows memory contents
Project Displays the files in the project
Register Debugging; shows contents of registers
Source Used to create and edit source code
Spy Debugging; used to view Windows messages
Thread Debugging; shows the program's threads
Trace Debugging; shows trace messages
Watch Debugging; used to work with watchpoints

You can open multiple Data and Source windows. When you have more than one Data or Source window open, and then minimize more than one of them, the IDDE adds a pop-up menu to the Data or Source icons in the Views toolbox (see Figure 2-3). A small triangle in the lower-right corner of the icon indicates that a Source or Data window is minimized.


[Figure 2-3 Pop-up menu in Source icon]

To open a minimized Data or Source window:

  1. Move the cursor over the triangle in the lower-right corner of the Data or Source window icon.
  2. Click to open the pop-up menu.
  3. Choose the window title you want from the pop-up menu. That window becomes active.

Alternatively, move the cursor over the window title in the pop-up menu, then click and hold the mouse button. A window icon appears to the right (see Figure 2-3). Drag the cursor over the icon, then move the cursor over either the desktop or an open window and release the mouse button.

The Build toolbox

The Build toolbox, shown in Figure 2-4, provides quick access to project build commands.


[Figure 2-4 Build toolbox]

To use the Build toolbox, click on the appropriate button in the toolbox. These buttons perform the following tasks:

The Debug toolbox

Debug toolbox icons (shown in Figure 2-5) let you efficiently choose debugging commands during a debugging session. The commands available in the Debug toolbox correspond to the commands on the IDDE Debug menu and are described in detail in the section "Debug Toolbox Icons," in Controlling and Configuring the Debugger.


[Figure 2-5 Debug toolbox]

The Workspace toolbox

When you first open the IDDE, the Workspace toolbox appears docked below the IDDE main window menu bar. The Workspace toolbox is used for switching between workspaces, which are customized layouts of windows that you define. The Workspace toolbox is shown in Figure 2-6.


[Figure 2-6 Workspace toolbox]

As you create new workspaces, their names appear on tabs in the Workspace toolbox. To switch to a different workspace, click on its tab. For more information on defining workspaces, see Starting a Project and Defining Workspaces.

Using toolboxes

The IDDE's Window menu lists the names of all toolboxes. When a checkmark is displayed next to the toolbox name, the toolbox appears in the current workspace. To open a toolbox, select the toolbox name from the IDDE's Window menu.

You can position a toolbox on the desktop by clicking on its title bar and dragging the toolbox to the desired position on the screen. To dock a toolbox, position it on the IDDE main window or on the edge of the screen. To undock the toolbox, click on the toolbox and drag it away from the IDDE main window or the desktop edge.

You can change the shape of a toolbox by clicking the toolbox edge and dragging the outline of the toolbox to the desired shape.

If you want to remove an icon from a toolbox, right-click on the icon you want to remove, drag it from the toolbox, and drop it.

Toolboxes can be configured with commands in their pop-up menus. To access a toolbox's pop-up menu, right-click on an empty part of the toolbox (as shown in Figure 2-7). When the first menu item, Dockable, is checked, you can dock the toolbox. The next three items (Small, Medium, and Large) let you change the size of the toolbox and its icons. The last item on the menu, Reset Palette, lets you restore any icons or buttons you have removed from the toolbox.


[Figure 2-7 toolbox pop-up menu]

To identify a toolbox icon, hold the mouse cursor over the icon for a few seconds. A small yellow tag appears, showing the name of the icon.

To close a toolbox, click on the Close box. Each toolbox has a Close box in the upper-right corner, as shown in Figure 2-8.


[Figure 2-8 Close box]

The IDDE windows

This section describes the general properties of the IDDE windows and how to work with them.

Opening and closing windows in the IDDE

Digital Mars C++ supports both standard Windows methods and a few unique methods for displaying and managing windows. In the IDDE, open a window in any of the following ways:

When you open a Source window to edit a specific source file, the filename is added to the Window List dialog box. You can then activate this particular window from the Window List dialog box.

Each window has a Close box similar to that of a toolbox (see Figure 2-8). Click on the box to close the window.

Using the drag-and-drop feature

The Digital Mars C++ IDDE provides a drag-and-drop feature that lets you execute commands by dragging from one window onto another or onto the desktop. For example, you can drag a module's name from the project window onto the desktop in order to edit that module in a Source window. When something cannot be dropped on a particular window or the desktop, the cursor changes from that icon to a "No" sign (a circle with a diagonal line through it). Most of the drag-and-drop functionality is available in debugging mode and is described in Commands Available in Debugging Mode.

Using the IDDE

The following sections serve as an overview of Part Two of this manual and introduce you to the process involved with creating an application in the Digital Mars C++ environment.

Creating a project

Projects are integral to the Digital Mars C++ development system. You cannot build an application without creating a project. A project is a collection of source files, headers, resource files, and other components that you need to build an application.

To help you create a new project, a new tool called ProjectExpress is included. This tool lets you select the project target (the result of your development efforts), the directory for the project files, and other options. While in ProjectExpress, you can also use AppExpress to generate the framework for the application.

AppExpress is a tool that automatically generates an application framework. AppExpress lets you select from a variety of application types, then creates a working skeleton of source code and resource definitions. After the framework is generated, then concentrate on customizing the framework and implementing the features of the application.

Using workspaces

Because the IDDE provides a variety of windows used for specialized tasks, you probably do not need all of them open simultaneously. The IDDE workspaces provide a convenient way to switch from one screen layout to another. Workspaces are task-oriented, as opposed to project-oriented. You create workspaces for different tasks, such as editing, browsing, or debugging, which you perform in different projects. The Workspace submenu of the IDDE's Environment menu provides access to workspace commands.

Creating and editing your application

Once you have created a project, you can start working on the program's code. This section introduces the IDDE tools.

Creating and editing resources

If writing a Windows application, you probably need to create resources such as menus and dialog boxes. Commands on the IDDE's Resource menu access the Digital Mars C++ ResourceStudio, a powerful tool for creating and editing resources.

Binding resources to classes

ClassExpress is a tool for binding resources, such as dialog box controls, to the classes in the program. This is needed in order to be able to respond to user actions. Launch ClassExpress by choosing ClassExpress from the IDDE's Tools menu, or from within ResourceStudio.

Editing class hierarchies

The IDDE provides two tools for editing class hierarchies: Class Editor and Hierarchy Editor. Open a Class or Hierarchy Editor window from the Views toolbox, or from the Goto View submenu of the IDDE's Window menu. Both editors have the same functionality, but different interfaces. The Class Editor emphasizes member editing, while the Hierarchy Editor emphasizes inheritance relationships.

Editing code

While you can greatly reduce the amount of work needed to write a complex application using the tools Digital Mars C++ provides, eventually you need to edit the raw source code. The IDDE includes a powerful, scriptable text editor with features such as customizable key bindings, automatic token coloring, delimiter matching, and other features. Edit code in the Source window, which can be opened from the Views toolbox or the Goto View submenu of the IDDE's Window menu.

Debugging your application

After writing most or all of the application's source code, it is time to test and debug it. Do this by switching the IDDE into debugging mode and using the commands on the IDDE's Debug menu, the Debug toolbox, and various debugging windows opened from the Views toolbox.

Using help

The following sections describe several ways to get online help in the IDDE.

The title/status bar

When you click and hold on a command in a menu, the IDDE main window title/status bar shows a brief description of the menu command.

The IDDE Help menu

The IDDE provides several online help systems through the IDDE Help menu. The first items on the IDDE Help menu access the IDDE Help system, shown in Figure 2-9. To navigate the IDDE Help system, click on the icon representing the type of help needed.

Alternatively, choose Search from the IDDE Help menu to find a particular topic in the IDDE Help system.


[Figure 2-9 IDDE Help system]

Other commands on the Help menu access Windows API and Microsoft Foundation Class reference material.

Finally, the About Digital Mars C++ command on the IDDE Help menu displays a dialog box with version information on the Digital Mars C++ Development System.

Other ways to launch online help

To view help information for a run-time library function, highlight the name of the function in a Text Editor window and type CTRL+ALT+F1.

To view frequently used help topics without navigating IDDE Help, associate specific .hlp files with key combinations. (For example, to view help for ResourceStudio, map rstudio.hlp with the key combination CTRL+ALT+F4.)

To associate a key combination with a help file, choose Edit/Browsing Settings from the IDDE's Environment menu. Click Text, then click Help files.

3. Starting a Project and Defining Workspaces

This chapter describes the initial steps involved in writing an application: creating the project that defines your target and then defining workspaces used in working on a project. These topics are covered here in sufficient depth to get you started; more detailed information is presented in More about Projects and Workspaces.

What Are Projects and Workspaces?

A project is a collection of files from which an executable or library is generated. The IDDE automatically generates a file (called the makefile) that tracks the dependencies in your project. This makefile is configured using the project option settings you specify. The IDDE executes the makefile when you build your project. File extensions are used to determine which tool is needed to build each component. Project building is discussed in Testing an Application.

Workspaces, which are among the IDDE's most useful features, are window configurations used for particular tasks. To create a workspace, you name and save the exact arrangement of windows on your screen. Any time you need to perform a similar task, you can instantly open that workspace, with the windows organized the way you want them. For more information on workspaces, refer to More about Projects and Workspaces.

Starting a Project

This section describes how to start a new project, how to open an existing project, and how to edit the project contents.

Purpose of a project

The project is central to building an application with the IDDE. A project is a container for the application you are building. It contains the various components necessary for building an application or a library, as well as information about how to build it.

Projects speed development time because they let you recompile only the source files that have changed, or whose header files have changed, since the last time the project was built. For example, if your program has five source files and you have changed one of them since the last build, only that file is recompiled when you build the project. (You can, however, choose to recompile all the files.) The project management system does this by automatically analyzing the dependencies of the source files and constructing or updating the makefile each time the project is built.

Contents of a project

A project can contain several different types of files, including C and C++ source, assembly language source, resource scripts, object files, libraries, and module definition files. And because a project is built in a hierarchical manner, you can include projects within projects.

The IDDE stores information about a project on disk as a project file with a .prj extension. Among other information, this file includes a list of the source files contained in a project. When you build the project, the IDDE constructs a makefile (.mak) or updates the existing makefile based on the files the project contains. Project options are stored in an option set file (.opn) that is referenced in the project file. The option set file can be loaded into another project, making it easy to transfer all option settings from one project to another.

Creating a new project

To create a new project, choose New from the Project menu. The ProjectExpress dialog box opens. ProjectExpress lets you specify the project name, initial project options, and initial project contents of the new project. The ProjectExpress dialog box contains four pages of options, described in the following sections.

Naming the project

Initially ProjectExpress displays the Project Name page (see Figure 3-1).

Figure 3-1 ProjectExpress Project Name page
Figure 3-1 ProjectExpress Project Name page

Select the directory in which you want to create the project from the Directories listbox, or click on New Directory to make a new directory for this project. Enter the name of the new project in the Project Name textbox.

If you select Use AppExpress to create new application, then click on Finish, AppExpress will start. AppExpress is discussed in Generating an Application Framework.

Setting the project type

To set the target operating system, target type, and other options, click on Next, or select Set project type from the left listbox, to switch to the Project Type page (Figure 3-2).

Figure 3-2 ProjectExpress Project Type page
Figure 3-2 ProjectExpress Project Type page

After the project is created, you can modify these settings by choosing Settings from the Project menu. These options are discussed in more detail in More about Projects and Workspaces.

Adding files to the project

To add pre-existing source, header, or other files to the new project, click on Next, or select Add files to project from the left listbox, to continue to the Project Edit page (Figure 3-3).

Figure 3-3 ProjectExpress Project Edit page
Figure 3-3 ProjectExpress Project Edit page

If you are creating a new project, you do not need to do anything on this page. After the project is created, you can open a similar dialog box by choosing Edit from the Project menu (see the section "Adding and deleting project files" later in this chapter).

Setting defines and include directories

To define macros, specify search paths, or exclude a directory from parsing, click on Next, or select Initial settings, to continue to the last page of the ProjectExpress dialog box (Figure 3-4).

Figure 3-4 ProjectExpress Initial Settings page
Figure 3-4 ProjectExpress Initial Settings page

To define a macro on the compiler command line, enter the macro in the Defines textbox (for example, COLOR=1). Separate multiple macro definitions with semicolons. Type any #include file search paths you want on the compiler command line in the Include Directories textbox. Type any directories to be excluded from parsing in the Browser Exclude Directories textbox. (For more information about parsing, see Defining Classes and Their Hierarchies).

In general, you can leave these fields blank. You may change these options later by choosing Settings from the Project menu.

After the project is set up the way you want, click on Finish to create the new project.

Opening an Existing Project

To open a project that already exists, choose Open from the Project menu. The IDDE displays the Open Project dialog box. Select the desired project filename and click OK.

IDDE lets you work with only one project at a time. If you're already working with a project when you open a new one, the IDDE closes the project in process.

An additional method for opening existing projects is to choose one from the list of projects at the bottom of the Project menu. Projects are added to this menu as they're opened or created. This makes it easier for you to switch back and forth between projects as you work.

Adding and deleting project files

To add or remove files from your project, choose Edit from the Project menu. The IDDE opens the Edit Project dialog box, shown in Figure 3-5.

Figure 3-5 Edit Project dialog box
Figure 3-5 Edit Project dialog box

The Project Files listbox contains the files in your project.

To make the changes to your project, click OK. To leave your project as it was before, click Cancel.

After you click OK, the IDDE checks your project for dependencies and creates a makefile. While checking for dependencies, the IDDE adds the additional files it needs to build your project. For example, it adds all the header files that your source files reference with the #include directive.

The Project window

The Project window, shown in Figure 3-6, displays a list of files in the current project. You can open the Project window by choosing Project from the Goto View submenu of the IDDE's Window menu.

Figure 3-6 Project window
Figure 3-6 Project window

You can double-click on the name of a source file in the right pane to open that file for editing in a Source window. (See Editing Program Code, for a description of text editing functions.)

You can see the current project's subprojects, or open a subproject, by double-clicking on the project name in the left pane.

The icon to the left of each filename indicates certain properties of the file. If the icon is blue, the file was explicitly added to the project; if the icon is gray, the file is included in the project by a dependency relationship or by parsing.

The icon next to each filename contains different information during debugging. An asterisk indicates that the module contains debug information. A "T" at the right of the icon indicates that tracing is enabled in the module. Dots indicate that the module contains breakpoints: a green dot indicates enabled breakpoints, and a red dot indicates disabled breakpoints.

Closing a project

To close a project that is currently open, choose Close from the Project menu. The project will be saved automatically.

Importing a Microsoft or Borland project

You can import an existing Microsoft or Borland project into the IDDE project system, by using the other product's makefile.

First, choose Open from the Project menu. In the "List files of type" listbox, choose Import Make. When you open a Microsoft or Borland makefile, the IDDE lets you work with it as you would a Digital Mars C++ project.

To build the project with the original Microsoft or Borland makefile, use the Make page under the Build tab in the Project Settings dialog box (see More about Project Build Settings) to call the original makefile or batch file.

Defining Workspaces

This section describes how to set up and save your own workspaces.

The purpose of workspaces

The IDDE's workspace feature lets you set up multiple screen configurations, each of which is optimized for a specific task. For example, you can have a workspace for editing source files, another for working with project resources, and another for debugging DLLs. You can define up to five different workspaces.

Creating a workspace

To start a new workspace, choose New from the Workspace submenu of the IDDE's Environment menu. Type the name of the new workspace in the Workspace Name dialog box. This name appears in the Workspace toolbox, as shown in Figure 3-7. You can then configure the screen as you like by opening the windows you need and positioning and sizing them to suit your requirements. You can refine the workspace as you work; the IDDE automatically saves changes to a workspace configuration when you exit the workspace.

Figure 3-7 Workspace toolbox
Figure 3-7 Workspace toolbox

Selecting a workspace

To change workspaces, click on a tab in the Workspace toolbox, or choose from the list of workspaces in the Environment menu. Changing your workspace does not affect your project; it just changes the way information is presented on the screen.

More options for workspaces

For more information on how to create, edit, clone, and delete workspaces, and to find out how to change workspace options, refer to More about Projects and Workspaces.

4. Generating an Application Framework

This chapter introduces application frameworks and the steps necessary to generate and build on such a framework. This process uses two tools: AppExpress and ClassExpress.

Before reading this chapter, take look at the material in Starting a Project and Defining Workspaces in the IDDE. AppExpress creates both an application framework (according to specifications you provide) and the project in which that framework resides.

More about AppExpress and More about ClassExpress are the reference chapters for the AppExpress and ClassExpress tools.

What Is an Application Framework?

An application framework is a standardized skeleton architecture for an object-oriented application. The framework is composed of C++ classes derived from base classes in the Microsoft Foundation Class (MFC) library.

Using a framework to build an application dramatically shortens its development time. All the files needed to create the application are included in the skeleton program. Standard user interface components such as windows, menus, and toolbars are already defined. Some of the necessary connections between the defined C++ classes are established automatically.

With a framework as a starting point and using the MFC library, you can build many different types of applications by:

As you build application frameworks with AppExpress and ClassExpress, you will become familiar with message maps. Message maps summarize, within a data structure or table, all of the links between Windows messages and the methods (also called functions) of a particular class that process those messages. Each entry in a message map is a pair, consisting of a message identifier and a method that responds to that message. The method is said to handle the message. Methods referenced in message maps are also called message handlers, or simply handlers.

Because message maps are used by MFC to route Windows messages to the messages' handlers, they provide the essential translations needed to present the event-driven model of the Windows API in an object-oriented guise. By automating the creation and maintenance of message maps, AppExpress and ClassExpress relieve you of much error-prone drudgery, and allow you to spend more of your development time writing code that implements functionality.

The following sample message map was automatically generated by AppExpress for an MDI-style application framework:

    BEGIN_MESSAGE_MAP( CMainView, CView)
	//{{ AFX_MSG_MAP( CMainView) 
	// NOTE -ClassExpress will add and
	// remove mapping macros here. 
	// DO NOT EDIT what you see in these
	// blocks of generated code ! 
	//}} AFX_MSG_MAP
	// Standard printing commands 
	ON_COMMAND( ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND( ID_FILE_PRINT_PREVIEW, 
		CView:: OnFilePrintPreview)
	END_MESSAGE_MAP() 

Creating a Framework with AppExpress

This section describes how to launch AppExpress and use it to generate an application framework.

Launching AppExpress

From the IDDE main window, choose AppExpress from the Tools menu. This opens the window shown in Figure 4-1.

[Figure 4-1 AppExpress window]

Looking at the AppExpress window

The AppExpress window contains: To navigate through the six pages of options, click on the name of a step in the steps list, or click on the Next or Previous button. Alternatively, press Control-n, where n is a number between 1 and 6 representing the selected step's position in the steps list.

Specifying an application framework

AppExpress divides the process of building a framework into six steps: These steps, which are briefly outlined here, do not have to be completed in this order. However, you will find it convenient to complete the first step specifying application type options before proceeding to any other step. All later steps contain some options that depend upon your choices in this step.

Selecting an application type

To select an application type:
  1. Select Application Type from the steps list in the AppExpress window.
  2. Select an application type by clicking on a radio button in the Applications group. There are six categories of applications, two of which SDI and MDI can be made OLE clients and/or servers.
Check the Include Help box if you want AppExpress to generate files from which a Windows help file can be created. Check the 32- Bit Project box if you are building a 32-bit application. See Chapter 17, "More about AppExpress" for the details of how the 32-Bit Project check box combines with the selected application type to determine what AppExpress generates.

Selecting application type options sets default options for many of the other steps in AppExpress. For example, if you select Dialog Box, AppExpress automatically creates three C++ classes with default class names in your skeleton program. You can change these defaults; for example, you can modify the default class names by selecting Names from the steps list.

Selecting a directory for the project

To select a directory for your source files and project file:
  1. Select the Select Directory item from the steps list. The Select Directory options page opens as shown in Figure 4-2.
  2. Select the appropriate drive and directory. Or, click on Create New Directory to create and name a new directory. AppExpress suggests the project name as the new directory name, but you may change that default.

    [Figure 4-2 Select Directory options]

Providing copyright information and project options

You can supply copyright information for your source code, and set the project's name, stack size, and heap size as follows:
  1. Select Miscellaneous from the steps list. The Miscellaneous options page opens as shown in Figure 4-3.

    [Figure 4-3 Miscellaneous options]

  2. Provide copyright information in the appropriate fields. AppExpress uses this information to write a copyright notice in the comment header of all of your application's source files, and to construct the application's About dialog box.
  3. Specify the project name in the appropriate field. Stack and heap sizes can be changed later in the Project Settings dialog box.

Specifying class names

To view and change the names of C++ classes or their associated source files:
  1. Select Names from the steps list. The Names options page opens as shown in Figure 4-4.
  2. In the options pane, select a class from the Name drop-down list automatically created by AppExpress. The class names included in this list depend on the application type you have selected.
  3. If you like, you can edit the selected class name. Note, however, that C++ class names follow a standardized naming convention. Using the default names allows your program's structure to be easily understood by others.
  4. In the appropriate field, type the names of the header and source files in which AppExpress should place the class source code.
Note: The CAboutDlg class, which represents your application's About Box class, is always created in the same header and implementation files as the CWinApp-derived class (for example, CSDIAPP).

To discard any changes you have made on this page, click on the Set Default Names button.

[Figure 4-4 Names options]

Naming source files

To edit filenames automatically generated by AppExpress:
  1. Select File Names from the steps list. The File Names options page opens as shown in Figure 4-5.
  2. In the options pane, click on the filename you want to change. The files listed depend on the application type you have selected. Their names correspond to their functionality within the application.
  3. Edit the filename, but remember that these changes could make it harder for someone else to identify the purpose of the file.

    [Figure 4-5 File Names options]

Specifying help file names

To view or change the names of the files that the help compiler uses to generate online help files for your application:
  1. Select Help Options from the steps list. The Help Options options page opens as shown in Figure 4-6.

    [Figure 4-6 Help Options options]

    Note If you selected Quick Console or Dialog Box as the application type, or if Include Help is not selected in the Application Type options page, then you have no help options.

  2. Edit the filenames if you want. Note, however, that any changes could make it harder for someone else to identify the purpose of the file.

Generating an application framework

At this point, you have selected an application type and the directory in which the application project files will reside, and you may have customized various class names or filenames. AppExpress can now generate your application framework in the form of a skeleton program.

Click on the Finish button in the AppExpress window. AppExpress generates the project and its source files, as you specified, hands it off to the project system, and closes.

Note If you checked the Include Help box among the Application Type options, then you will need to build the help file for your application. You do this by running the makehelp. bat file that AppExpress creates in your project directory.

Your skeleton program is ready. You can now build the program from within the IDDE, or you can add to your program by using other Digital Mars C++ tools. The next section shows how to enhance your application's C++ classes by using ClassExpress.

Building on a Framework with ClassExpress

AppExpress cuts the work involved at the beginning of the application-building process. ClassExpress, on the other hand, enhances productivity throughout the rest of the process. You use this tool to flesh out the skeleton application produced by AppExpress.

Specifically, you can use ClassExpress to:

This chapter describes the first two of these options: writing message maps and creating new classes derived from existing classes.

Message maps, defined in "What Is an Application Framework?" in this chapter, are discussed in greater detail in Chapter 17, "More about AppExpress."

You can use ClassExpress immediately after creating an application framework as well as at later points in development. For example, you probably want to wait until you have created some dialog boxes with ResourceStudio (see Chapter 7, "Adding Look and Feel with Resources" ) before mapping class member variables to user interface objects.

Launching ClassExpress

From the IDDE main menu, launch ClassExpress by choosing ClassExpress from the IDDE's Tools menu.

Launching ClassExpress opens the window shown in Figure 4-7.

[Figure 4-7 ClassExpress window]

Looking at the ClassExpress window

The ClassExpress window contains: To navigate through the selections, click on the name of a selection in the list. Alternatively, use the key combination Control-n, where n is a number between 1 and 6 representing the position in the selections list of the selection to which you want to move.

Writing a message map with ClassExpress

Message maps are tied to particular C++ classes. In ClassExpress, you can add to an existing message map by adding new linkages between messages and class methods. Or you can add a new message map for an entirely new class.

ClassExpress runs from within the IDDE or as a stand-alone application. If run from within the IDDE, ClassExpress will be loaded with the IDDE's open project if there is one; otherwise, it prompts to open an existing project (which also opens the project in the IDDE's project system).

As an example, the following steps demonstrate how to add a message handler to the CAboutDlg class of an SDI application generated by AppExpress:

  1. Select Message Maps from the listbox. (If you just started ClassExpress, this should already be selected.) The ClassExpress window is displayed as shown in Figure 4-7.
  2. Select the class CAboutDlg from the Class drop-down list. The contents of the three other lists in the options pane are updated to reflect the following selection:
  3. Select CAboutDlg from the Control IDs in Class list. The list of Windows messages changes, revealing a long list of messages to which your dialog box could respond.
  4. Double-click on WM_ACTIVATE. Notice that the method OnActivate (in its fully prototyped form) is added to the Function Name list.
Now, whenever your About dialog is activated, the OnActivate method is called in response to the dialog window receiving the message WM_ACTIVATE. With the four above steps, you have created an association between the message WM_ACTIVATE and the method OnActivate, and added it to the message map for the CAboutDlg class.

Adding a new class to your application

Adding new classes to your application is as easy as creating a message map. To add a class:
  1. Select Message Maps from the listbox. (If you just loaded ClassExpress, then this should already be selected.)
  2. Click on the Add Class button. The Add Class dialog box shown in Figure 4-8 opens.

    [Figure 4-8 Add Class dialog box]

  3. Select a class type from the Class Type drop-down list. This type specifies the base class from which your new class will be derived. The list displays names of MFC classes without the initial letter 'C', thereby allowing you to navigate rapidly within the list by typing the first letter of a class type. For example, typing 'V' selects the View class type.
  4. The New Class Name field becomes active, displaying a suggested name for the new class. Edit this name as appropriate.
  5. If you selected CDialog or CFormView, then the field Dialog ID is displayed. Move to this field and choose the resource ID of the dialog that you want to associate with the new class's window.
  6. Check the OLE Automation box if you want your new class to be a programmable OLE object. If you choose this option, any other Windows application that is an automation client can use the OLE interface you define for this object.
  7. If you check the OLE Automation box and you are deriving a new class from the CCmdTarget or CWnd class, the Creatable check box is displayed. Check this box if you want other applications to be able to create the OLE automation object that you are defining.
  8. If you check the OLE Automation check box and you are deriving a new class from the CCmdTarget or CWnd class, you must also type a name in the External Name field. This is the name that is exposed to other applications that may want to use your OLE automation object.
  9. Decide whether to edit the implementation filename of your new class (shown in the last field in the Add Class dialog box). By default, the base part of the filename is the name of your new class without the initial letter 'C', and truncated if necessary.
  10. Click OK to add the new C++ class to your application. If you want, you can create message mappings for your new class by using the steps outlined in the previous section.
This section on ClassExpress showed how easy it is to write a message map and to create a new class. By just clicking on a check box, you can also add OLE automation support to your application.

In addition, ClassExpress can bind your classes to your dialog boxes and generate C++ wrapper classes for Visual Basic custom controls (VBXs). It also provides extensive support for building OLE servers and containers. For more information on these features, refer to Chapter 18, "More about ClassExpress."

5. Defining Classes and Their Hierarchies

Once you have produced an application framework, customize the application by adding your own classes and functions. The two tools designed specifically for object-programming are the Class Editor and the Hierarchy Editor. They simplify the design and maintenance of C++ projects by working directly with the project's class hierarchy and members. The editors themselves take care of many of the mundane details of file-oriented program development, such as opening and closing files and locating source code for particular member functions.

These tools are suited for developing a class hierarchy from scratch, for adding classes to an application framework generated with AppExpress, and for browsing and editing pre-existing class hierarchies. They are especially useful for understanding the architecture of unfamiliar source code.

The Class and Hierarchy Editors can perform the same operations on classes and hierarchies; they differ only in their interface. The Class Editor's interface emphasizes member editing; the Hierarchy Editor's interface, through its graphical display, emphasizes inheritance relationships. Use one or the other, or both simultaneously, according to preference.

This chapter describes basic operations that may be performed with the Class and Hierarchy Editors. For a complete reference on these two tools, see Class Editor Reference, and Hierarchy Editor Reference.

Parsing and Browsing

The Class and Hierarchy Editors are C++ class browsers. These tools let you work with your source code in an object-oriented manner, rather than in the traditional file-oriented manner. The Class and Hierarchy Editors present you with a list of classes in your project, allow you to view the members of each class, and let you edit the member declarations and definitions directly, without performing the overhead of opening and closing files and locating source code for particular members. Changes made to classes or inheritance relationships in the Class or Hierarchy Editors are automatically changed in the underlying source code.

To present you with a list of classes and members, the IDDE must parse the source code. By default, this is done automatically. When the IDDE detects that source code or project settings have changed since the last parse, it reparses the necessary files. If errors are encountered during parsing, messages are displayed in the Output window. You can double-click on the error message to open for editing the appropriate file at the point at which the error was detected.

How the class browsers expand macros

The parser used by the Class and Hierarchy Editors contains a fully functional C preprocessor. One significant difference between this parser and the Digital Mars C compiler is the way the parser expands macros.

The parser treats an entire project as one "database" of code. Consequently, preprocessor macros defined in any header will expand in any subsequently parsed file. This can produce unexpected errors. For example:

// foo1.h ------------------------------------
#define pBar (pIndirect->pBar) 
// . . .

// foo1.cpp ----------------------------------
#include <foo1.h> 


// foo2.cpp ----------------------------------
struct A 
{   int *pBar;    // ERROR! Expands to: int * 
    (pIndirect-> pBar);
}; 
To avoid errors of this type, undefine the macro at the top of the file where the error occurs (foo2.cpp).

Browsing library source code

If browsing source code that is based on MFC or some other large class library, it is convenient to turn off the display of library classes. To do so:
  1. Choose Settings from the IDDE's Project menu.
  2. In the Project Settings dialog box, click the Directories tab.
  3. In the Browser Exclude Directories textbox, type the name of the directory containing the class library headers (for example, c:\dm\mfc\include).
  4. Click OK.
Control the parsing of individual files from the Project window, and enable or disable parsing for the entire project from the Target page of the Project Settings dialog box. For more information, see More about Projects and Workspaces.

Class Editor

The Class Editor provides a list-based view of the class hierarchy. From within the Class Editor add classes, modify inheritance relationships, and view and edit class member declarations and definitions.

To open a Class Editor window, do one of:

  1. Choose Class Editor from the Window menu's Goto View submenu.
  2. Click and drag the Class Editor icon from the Views toolbox to an empty area of the desktop.
The Class Editor window (see Figure 5-1) is divided into three panes:
  1. The Classes pane, which contains a list of classes.
  2. The Members pane, which contains a list of members of the current (highlighted) class.
  3. The Source pane, which displays member source code. You can edit the source code in this pane as in the Source window (see Editing Program Code, for a description of text editing features).
Figure 5-1 <b>Class Editor</b> window
Figure 5-1 Class Editor window

The Class Editor window contains a standard menu bar and toolbar; pop-up menus are available in each pane. You can set options for the grouping, sorting, and display of classes and members in the Classes and Members panes in the Editing/ Browsing Settings dialog box. For a complete reference on Class Editor menus and options, see Class Editor Reference.

You can change the relative sizes of panes in the Class Editor window by first positioning the cursor over the line separating the panes. The cursor changes to a two-headed arrow. Press the left mouse button and drag the separator to the desired location.

To select a class in the Classes pane, click on it. Additional classes may be selected by holding down the Control key and clicking. By default, classes are displayed hierarchically, with derived classes below and indented relative to their bases. Classes with multiple bases are displayed beneath each of the bases. Triangular buttons to the left of base classes can be used to collapse and expand branches of the hierarchy. You can set an option to display classes alphabetically in the Editing/ Browsing Settings dialog box.

By default, class members in the Members pane are grouped into Functions, Data, and Typedefs. The tree structure can be expanded or collapsed by clicking on the triangular buttons to the left of the category names. To select a class member, click on it. Additional members can be selected by clicking while holding down the Control key. You can display a member declaration or definition in the Source pane by double-clicking on the member name.

Creating classes

You can create a class hierarchy consisting of new classes related to other classes by inheritance (derived or sibling classes), or create new top-level classes not related to any other class.

Creating a top-level class

To create a new class hierarchy, first create a top-level class to serve as a base for the hierarchy.

To create a new top-level class:

  1. Choose Add Top from the pop-up menu in the Classes pane. The Add Class dialog box is displayed (Figure 5-2).

    Figure 5-2 Add Class dialog box
    Figure 5-2 Add Class dialog box

  2. Type a name for the new class.
  3. Click OK.
The class declaration is placed in a new header file, and the header file is added to the project. By default, the first eight letters of the class name are used to derive the header filename. You may change the header filename by typing an alternative name in the Header File textbox of the Add Class dialog box.

Creating a derived class

After a base class exists, you may create derived classes- specialized versions of the base class.

To create a new derived class:

  1. Select the base class of the new class.
  2. Choose Add Derived from the pop-up menu in the Classes pane. The Create Derived Class dialog box opens. (This dialog box is similar to the Add Class dialog box.)
  3. Type a name for the new class.
  4. Click OK.

Creating a sibling class

You may also create a new derived class as a "sibling" to an existing class. Siblings have the same base class with the same access specifiers.

To create a new sibling class:

  1. Select the class whose base class will be the base class of the new class.
  2. Choose Add Sibling from the pop-up menu in the Classes pane. The Create Derived Class dialog box is displayed.
  3. Type a name for the new class.
  4. Click OK.

Editing inheritance relationships

As your application evolves, you may want to restructure your class hierarchy. The Class Editor lets you add and delete connections between classes, as well as change the inheritance attributes.

When altering inheritance relationships, the Class and Hierarchy Editors change only the class declarations. In particular, they do not change references to base classes and their members in a derived class's constructors or functions. If such references exist, you must change them manually in the source file.

Connecting to a base class

You can connect a class to a base class to make it a derived class of this base.

To make one existing class derive from another existing class:

  1. Select the class that will be the derived class.
  2. Choose Connect Base from the pop-up menu in the Classes pane. The Add Base dialog box opens (Figure 5-3).

    Figure 5-3 Add Base dialog box
    Figure 5-3 Add Base dialog box

  3. From the listbox, select the class (or classes) to be this class's base class.
  4. Select the desired access specifier. Check Virtual if virtual inheritance is desired.
  5. Click OK.
If the classes are displayed hierarchically, the derived class is displayed below and is indented relative to the base class in the Classes pane.

Deleting a connection

You can also disconnect a derived class from a base class.

To delete an inheritance relationship:

  1. Select a derived class.
  2. Choose Delete Base Connection from the pop-up menu in the Classes pane.
  3. A message box requests confirmation. Click Yes to delete the base connection.
In cases of multiple inheritance, select one inheritance relationship to delete by clicking on the instance of the derived class below the base to be removed. For classes derived from more than one base class, multiselecting the inheritance relationships to be deleted lets you delete all base connections simultaneously. If a class has all of its base connections severed, it remains in the hierarchy at the top level.

Editing inheritance attributes

You can change a derived class's base class access specifier and virtual inheritance flag.

To edit the base class access specifier:

  1. In the Classes pane, select the derived class.

    In cases of multiple inheritance, select the base connection to edit by clicking on the instance of the derived class below the appropriate base.

  2. Choose Edit Base Attributes from the pop-up menu in the Classes pane.

    The Edit Base Attributes dialog box opens (Figure 5-4).

    Figure 5-4 Edit Base Attributes dialog box
    Figure 5-4 Edit Base Attributes dialog box

  3. Select the desired access specifier. Check Virtual if virtual inheritance is desired. Click OK.
If you are editing several inheritance relationships simultaneously and the access specifiers are not identical, a Don't Change option is displayed. This lets you change the Virtual specifier without also affecting the access specifiers. You may, however, select Public, Protected, or Private, and all connections are given that access specifier.

Working with class members

After creating a class, you can implement its functionality through member data and functions. You may add, delete, and edit class members through the Members pane and Source panes.

A list of the members of the currently selected class is shown in the Members pane (Figure 5-5). By default, the member list is sorted into three categories: Data, Functions, and Typedefs. Within each category, items are sorted alphabetically. The colored diamond in front of each member identifies the access as public (green), protected (yellow), or private (red). Names of members defined as macros appear in red.

Note: Members that appear in red are not syntactically verified before source changes are saved back to the file.

The lists following each category header can be collapsed or expanded by clicking on the triangular button to the left of the category name.

Figure 5-5 Members pane of <b>Class Editor</b>
Figure 5-5 Members pane of Class Editor

Adding a class member

The first step in class implementation is to declare the data members and member functions.

To add a class member:

  1. Choose Add from the pop-up menu in the Members pane. The Add Member dialog box opens (Figure 5-6).

    Figure 5-6 Add Member dialog box
    Figure 5-6 Add Member dialog box

  2. Type the member declaration. The member may be a data item (for example, int nCats), a function (for example, int NumCats()), or a typedef (for example, typedef int CATCOUNT). Do not type any storage specifiers into the declaration textbox; these are added by the Class Editor.
  3. Select the desired access and storage specifiers. Check the Inline check box for an inline function.
  4. Click OK.
The new member is added to the appropriate group in the Members pane and to the class declaration in the header file. If the new member is a function, an empty function is added to the appropriate source file. If a new source file is created, it is added to the project.

By default, the first eight letters of the class name are used to derive the source filename for new functions. You may change the file name by entering an alternative name in the Source File textbox of the Add Member dialog box.

Deleting a class member

Unneeded class members are easily removed.

To delete a class member:

  1. Select the class member to be deleted.
  2. Choose Delete from the pop-up menu in the Members pane.
  3. When the message box requests confirmation, click Yes to delete the member.
The declaration is removed from the header file and, if the member was a function, the function definition is removed from the source file.

Changing member attributes

As your class and hierarchy evolve, you may decide to change certain member attributes. For example, you may want to make a function virtual, or data private.

To change a member's access and storage specifiers:

  1. Select the member you want to change.
  2. Choose Edit Attributes from the pop-up menu in the Members pane. The Change Member Attributes dialog box opens (Figure 5-7).

    Figure 5-7 Change Member Attributes dialog box
    Figure 5-7 Change Member Attributes dialog box

  3. Select the desired access and storage specifiers. Check the Inline check box for an inline function. Click OK.
The class declaration in the header file is modified and the Members display is updated to reflect those changes.

If you are editing several members' attributes simultaneously and the access specifiers are not identical, a Don't Change option is displayed in the Access group box. Likewise, if the storage specifiers are not identical, a Don't Change option is displayed in the Storage group box. These options let you change other member attributes without affecting the original access or storage of each member. You may, however, select a particular access or storage specifier, and all members are given that attribute. Also, when you are editing several members' attributes, if the inline attributes are not the same, the Inline check box changes to allow three states (checked, unchecked, and grayed, indicating "Do not change") instead of the normal two-state options.

Viewing and editing member source

After declaring your class members, you can extend your functions by editing the function definitions in the Source pane. You also can change data member types, array dimensions, and so on.

To view and edit member declarations and function definitions:

  1. Double-click on the member in the Members pane.

    The member's declaration (for data items and pure virtual functions) or definition (for other functions) is displayed in the Source pane. If the source code is not available (as with MFC libraries, for example), the definition is displayed.

  2. Click in the Source pane to begin editing. Editing operations here are identical to editing operations in other Source windows.
  3. To save changes, choose Save from the pop-up menu in the Source pane.
Changes made to a function's argument and return types in the definition are updated automatically in the class declaration. The Members pane is updated when the source is saved.

Note: If you close the current project before you save a source file you've modified with the Class Editor, you cannot discard the changes or close the file until you reopen the project.

Viewing and editing source files

At times it is useful to view and edit the entire file containing the class declaration or the class's functions. It is necessary, for example, to add the appropriate #include statements to the source files before compiling.

To view and edit the header file containing the class declaration:

  1. Select the class in the Classes pane.
  2. Choose Show Header from the pop-up menu in the Classes pane. A Source window containing the contents of the class header file is displayed.
  3. Edit the class declaration as desired.

    You may add or delete class members as you would without the Class Editor. However, if you add functions to the declaration, you have to add the function definitions manually to the source file as well.

  4. Save your changes by choosing Save from the Source window's File menu.
  5. To close the Source window, choose Close from the File menu.
  6. Click on the Class Editor window. If you have made changes to the header file, a message box asks whether it is OK to reparse. Click Yes.
  7. Click on the class whose declaration you just edited to see the member changes updated in the Members pane.
Note: For non-inline functions, if you change the function's signature (return type, argument types, and so forth) in its declaration, you must make the corresponding changes to its definition by hand, or the Members pane will display two versions of the function.

To view and edit the source file containing member function definitions:

  1. Select a member function from the Members pane.
  2. Choose Show Source from the pop-up menu from the Members pane. (Show Source is dimmed if the source code is not available.)

    The file containing the member function's source code is opened for editing in a Source window.

  3. Edit the member functions as desired.

    You may edit member functions as you would without the Class Editor. However, if you change function arguments or return types, or add new functions, you must modify or add the function declarations manually in the header file as well.

  4. Save your changes by choosing Save from the Source window's File menu.
  5. To close the Source window, choose Close from the File menu.
  6. Click on the Class Editor window. If you have made changes to the source file, a message box asks whether it is OK to reparse. Click Yes.

Hierarchy Editor

The Hierarchy Editor provides a graphical view of the class hierarchy. From within the Hierarchy Editor, you may add classes, modify inheritance relationships, and view and edit class member declarations and definitions. With its graphical view of class relationships, the Hierarchy Editor is an especially useful tool when examining unfamiliar source code for the first time.

To open a Hierarchy Editor window, do one of the following:

The Hierarchy Editor window opens. By default, only the graphical display of class hierarchies is shown. To provide full functionality, it is necessary to enable the editor's two child windows.

To enable the Hierarchy Editor child windows:

  1. Choose Settings from the Hierarchy Editor's pop-up menu. The Editing/Browsing Settings dialog box opens to the Hierarchy page.
  2. Check the items labeled Members and Source in the Pop-up Windows group box.
  3. Click OK.
The Members and Source child windows open below the Hierarchy Editor window (Figure 5-8).

Figure 5-8 <b>Hierarchy Editor</b> window
Figure 5-8 Hierarchy Editor window

Unlike the Members and Source panes of the Class Editor, Hierarchy Editor windows are independent. They have their own menus and may be positioned, sized, and closed separately. Otherwise, they behave as do the corresponding panes of the Class Editor. For a complete reference on Hierarchy Editor menus and options, see Hierarchy Editor Reference.

Creating classes

A class hierarchy consists of a number of classes connected by inheritance relationships. You can create new classes related to other classes by inheritance (derived or sibling classes) or new top-level classes not related to any other class.

Operations relating to class creation and the establishment of hierarchical relationships are carried out in the Hierarchy Editor's graphical display window.

Creating a top-level class

To create a new class hierarchy, first create a top-level class to serve as a base for the hierarchy.

To create a new top-level class:

  1. Activate the Hierarchy Editor window.
  2. Choose Add Top from the pop-up menu. The Add Class dialog box opens (Figure 5-9).

    Figure 5-9 Add Class dialog box
    Figure 5-9 Add Class dialog box

  3. Type a name for the new class.
  4. Click OK.
The class declaration is placed in a new header file, the header file is added to the project, and the new class is selected in the Hierarchy Editor main pane. By default, the first eight letters of the class name are used to derive the header file name. You may change the header file name by typing an alternative name in the Header File textbox of the Add Class dialog box.

Creating a derived class

After a base class exists, you may add a specialized version of that class to the hierarchy by creating a derived class.

To create a new derived class:

  1. Select the class that will act as the base class of the new class.
  2. Choose Add Derived from the pop-up menu.

    You can also perform this step with the mouse. Hold the left mouse button down and drag the cursor from the selected class to an empty area of the window. A rubber band line appears as you do this (Figure 5-10). Release the mouse button.

    The Create Derived Class dialog box opens (this dialog box is similar to the Add Class dialog box).

    Figure 5-10 Creating a new derived class using the mouse
    Figure 5-10 Creating a new derived class using the mouse

  3. Type a name for the new class.
  4. Click OK.

Creating a sibling class

You may also create a new derived class as a "sibling" to an existing class. Sibling classes have the same base class with the same access specifiers.

To create a new sibling class:

  1. Click on the class whose base class is to be the base class of the new class.
  2. Choose Add Sibling from the pop-up menu. The Create Derived Class dialog box is displayed.
  3. Type a name for the new class.
  4. Click OK.

Editing inheritance relationships

As your application evolves, you may want to restructure your class hierarchy. You can add and delete connections between classes, as well as change the inheritance attributes.

In altering inheritance relationships, Class and Hierarchy Editors change only the class declarations, not references to base classes and their members in a derived class's constructors or functions. If such references exist, you must change them manually.

Connecting to a base class

You can connect a class to a base class, to make the former a derived class of the latter.

To make an existing class a base of another existing class:

  1. Click on the class that is to be the derived class.
  2. Choose Connect Base from the pop-up menu. The Add Base dialog box opens (Figure 5-11).

    Figure 5-11 Add Base dialog box
    Figure 5-11 Add Base dialog box

  3. From the listbox, select the class (or classes) that will be the derived class's base class.
  4. Select the desired access specifier. Check Virtual if virtual inheritance is desired.
  5. Click OK. The display changes to show the new inheritance relationship.
You can also connect to a base by using the mouse in the graphical display. Click on the class that is to be the base class. Holding down the mouse button, drag the rubber-band line to the class that is to be the derived class. (The cursor changes to a universal "No" sign when positioned over a class that cannot become a derived class of this base.) Release the mouse button. The class is publicly derived from the base.

Deleting a connection

Just as you can connect a class to a base class, you also can disconnect a derived class from a base class.

To delete an inheritance relationship:

  1. Click on the line connecting the base and derived classes. The line is highlighted to show that it is selected (Figure 5-12).

    Figure 5-12 Highlighted base-derived connection
    Figure 5-12 Highlighted base-derived connection

  2. Choose Delete Base Connection from the pop-up menu.
  3. When the message box requests confirmation, click Yes to delete the base connection.

Changing base class

You can move a base class connection to change the base of a derived class.

To change a class's base class:

  1. Click on the line connecting the derived class and its current base.

    The line is highlighted to indicate that it has been selected. Note that at the end nearest the base class, there is a small black box (referred to as the line's "handle").

  2. Click on the line's handle. Holding down the left mouse button, drag the handle over the class that is to be the derived class's new base class.
  3. When the message box requests confirmation, click Yes to change the base connection.

Editing inheritance attributes

You can change a derived class's base class access specifier and virtual inheritance flag.

To edit the base class access specifier:

  1. Click on the line connecting the base and derived classes. The line is highlighted to show that it is selected.
  2. Choose Edit Base Attributes from the pop-up menu. The Edit Base Attributes dialog box opens (Figure 5-13).

    Figure 5-13 Edit Base Attributes dialog box
    Figure 5-13 Edit Base Attributes dialog box

  3. Select the desired access specifier. Check Virtual if virtual inheritance is desired. Click OK.
If you are editing several connections simultaneously and the access specifiers are not identical, a Don't Change option becomes available. This lets you change the Virtual specifier without affecting the various access specifiers. You may, however, check Public, Protected, or Private instead, and all connections are given that access specifier.

Working with class members

After creating a class, you can implement its functionality through member data and functions. You may add, delete, and edit class members through the Members and Source child windows.

A list of members of the currently selected class is displayed in the Members child window (Figure 5-14). By default, the member list is sorted into three categories: Data, Functions, and Typedefs. Within each of these categories, items are sorted alphabetically. The colored diamond in front of each member identifies the access as public (green), protected (yellow), or private (red). Lists following each category header can be collapsed or expanded by clicking on the triangular button to the left of the category name.

Figure 5-14 Members child window
Figure 5-14 Members child window

Adding a class member

The first step in class implementation is to declare the data and function members.

To add a class member:

  1. Activate the Members child window.
  2. Choose Add from the Member menu or from the pop-up menu. The Add Member dialog box opens (Figure 5-15).

    Figure 5-15 Add Member dialog box
    Figure 5-15 Add Member dialog box

  3. Type the member declaration. The member may be a data item (for example, int nDogs), a function (for example, int NumDogs()), or a typedef (for example, typedef int DOGCOUNT). Do not type any storage specifiers into the declaration textbox; these are added by the Hierarchy Editor.
  4. Select the desired access and storage specifiers. Check the Inline check box for an inline function.
  5. Click OK.
The new member is added to the appropriate list in the Members child window and to the class declaration in the header file. If the new member is a function, an empty function is added to the appropriate source file. If a new source file is created, that file is added to the project.

By default, the first eight letters of the class name are used to derive the source file name for new functions. You can change the file name by entering an alternative name in the Source File textbox of the Add Member dialog box.

Deleting a class member

Unneeded class members are easily removed.

To delete a class member:

  1. Select the class member to be deleted.
  2. Choose Delete from the Member menu or from the pop-up menu.
  3. When the message box requests confirmation, click Yes to delete the member.
The declaration is removed from the header file; if the member was a function, the function definition also is removed from the source file.

Changing member attributes

As your class and hierarchy evolve, you may need to change certain member attributes. For example, you may want to make a function virtual, or data private.

To change a member's access and storage specifiers:

  1. Select the member to be changed.
  2. Choose Edit Attributes from the Member menu or from the pop-up menu. The Change Member Attributes dialog box opens (Figure 5-16).

    Figure 5-16 Change Member Attributes dialog box
    Figure 5-16 Change Member Attributes dialog box

  3. Select the desired access and storage specifiers. Check Inline for an inline function. Click OK.
If you are editing several members' attributes simultaneously and their access specifiers are not identical, a Don't Change option becomes available in the Access group box. Similarly, if the storage specifiers are not identical, a Don't Change option is displayed in the Storage group box. These options allow you to change other member attributes without affecting the original access or storage of each member, respectively. You may, however, select a particular access or storage specifier, and all members are given that attribute.

The class declaration in the header file is modified and the Members display is updated to reflect the changes.

Viewing and editing member source

After declaring your class members, you can extend your functions by editing the function definition in the Source child window. Also, you can change data member types, array dimensions, and so on.

To view and edit member declarations and function definitions:

  1. Double-click on the member in the Members child window.

    The member's declaration (for data items and pure virtual functions) or definition (for other functions) is shown in the Source child window.

  2. Click in the Source child window to begin editing. Editing operations here are identical to those in other Source windows.
  3. To save changes, choose Save from the pop-up menu.
Changes made to a function's argument and return types are updated automatically in the class declaration. The Members child window is updated when the source is saved.

Viewing and editing source files

At times it is useful to view and edit the entire file containing the class declaration or the class's functions.

To view and edit the header file containing the class declaration:

  1. Click on the class in the Hierarchy Editor window.
  2. Choose Show Header from the pop-up menu.

    A Source window containing the contents of the class header file opens.

  3. Edit the class declaration as desired.

    You may add or delete class members as you would without the Hierarchy Editor. However, if you add function declarations, you must add the function definitions to the source file manually as well.

  4. Save your changes by choosing Save from the Source window's File menu.
  5. To close the Source window, choose Close from the File menu.
  6. Click on the Hierarchy Editor window. If you have made changes to the header file, a message box asks whether it is OK to reparse. Click Yes.
  7. Click on the class whose declaration you just edited to see the member changes updated in the Members window.
To view and edit the source file containing member function definitions:
  1. Select a member function from the Members child window.
  2. Choose Show Source from the Member menu or from the pop-up menu.

    The file containing the member function's source code is opened for editing in a Source window.

  3. Edit the member functions as desired.

    You may edit member functions as you would without the Hierarchy Editor. However, if you change function arguments or return types, or add new functions, you must modify or add the function declarations manually in the header file as well.

  4. Save your changes by choosing Save from the Source window's File menu.
  5. To close the Source window, choose Close from the File menu.
  6. Click on the Hierarchy Editor window. If you have made changes to the source file, a message box asks whether it is OK to reparse. Click Yes.

6. Editing Program Code

Program code is edited in Source windows. The Source window is a full-featured text editor, with many options and features particularly useful when editing C and C++ source code. Subsets of Source window functionality are also available in the Source pane of the Class Editor and in the Source child window of the Hierarchy Editor.

In addition to its role in editing project code, use the Source window for monitoring program execution while debugging. See Chapter 24, Commands Available in Debugging Mode, for more information.

Chapter 21, Text Editor Reference, contains descriptions of all Source window menu commands, toolbar icons, dialog boxes, and options. Refer to it once you've read this chapter and you need more details about specific aspects of the editor.

Refer to the Digital Mars C++ IDDE Help for the key combination used to execute a particular editting command. It contains a reference to all key combinations for every key binding set.

Role of the Text Editor

The purpose of the IDDE text editor is to create, examine, and modify project source files. Because these files are standard text files, any text editor to work with them. However, the IDDE text editor is designed especially to edit C and C++ source files and to work in concert with other IDDE tools.

Anyone familiar with Windows can get started quickly with the IDDE text editor because it uses standard Windows editing commands. In addition, the text editor has some features that make working with C and C++ files easier. For example, the editor can automatically indent or unindent after braces and can check delimiters.

The text editor can display keywords, preprocessor directives, and comments in special font styles and colors. This technique helps track errors in source code while editing. For example, an unmatched comment (/* without a matching */) turns a large part of the code a different color, making it obvious where the problem lies. Keywords and preprocessor directives are easier to spot when they are in a different color or font style. Misspelled keywords can be caught immediately when they remain displayed in the default font.

Source windows are an integral part of the IDDE environment and work together with other IDDE windows to make application development easier. For example, the IDDE automatically saves all files open in Source windows when you rebuild your project. During compilation, error messages are displayed in the Output window; double-clicking on an error message opens a Source window on the corresponding source file, if necessary, and then jumps to the line in the source code that caused the error.

The Source Window

Source window

[Figure 6-1 Source window]

Most work with a Source window is in the editing area. This is where text is displayed and edited, as described later in this chapter. The Source window contains a typical IDDE window menu and toolbar; a pop-up menu is available by right-clicking in the editing area. Complete information about the menus and toolbar is contained in Chapter 21, Text Editor Reference.

The status bar, shown in Figure 6-2, provides information about the current state of the file being edited.

[Figure 6-2 Source window status bar]

Information string
Displays information about the state of the current function. For example, the message Pattern not found is displayed when the Find command is unable to locate the specified pattern.
Modification flag
Displays Mod if the file has been modified since it was last saved.
Insertion mode
Displays Ovr when the typing mode is set to overtype. When the typing mode is set to insert, nothing is displayed in this field. Toggle the insertion mode with the Insert key.
Read-only flag
Displays Rd when the file is set to read-only. When the file is in read/ write mode, nothing is displayed in this field. The read-only attribute is set in the Current Buffer Options dialog box described later in this chapter.
Line number
Displays the line number of the insertion point.
Column number
Displays the column position of the insertion point.

File Manipulation

The IDDE lets you open as many different files as your computer's memory allows. You can open multiple views of one file; changes made in one window will be made in all.

Creating files

To create a new file, choose New from the IDDE's File menu. An empty Source window opens, and you can begin typing. Note that the new file is not actually created on disk until you save it.

Opening files

To open a source file (or any text file), choose Open from the IDDE's File menu, or choose Open from a Source window's File menu. A standard Windows File Open dialog box is displayed. Select the file you want to edit and click OK. The file is opened for editing in a new Source window. There are additional ways to open a file for editing:

Saving files

To save the file in the active window, choose Save from the Source window's File menu. If the file is untitled, the editor displays the File Save As dialog box to let you name it. Otherwise, it saves the file under its current name. This procedure saves only the file in the active Source window.

To save the files in all Source windows, choose Save All from the Source window's File menu. The editor displays the Save As dialog box for any untitled file.

To save an unnamed file or a named file under a new name, choose Save As from the File menu. The text editor displays the File Save As dialog box, as shown in Figure 6-3.

[Figure 6-3 File Save As dialog box]

Enter a name for the file and click OK.

Writing blocks of text to files

By choosing Write Block from the Source window's pop-up menu, you can write the currently selected text block to a new file or append the block to an existing file. This is useful when, for example, you want to remove some functions from a file and place them in a separate file.

Printing files

To print the file in the active window, choose Print from the Source window's File menu. The Text Print dialog box opens, as shown in Figure 6-4.

[Figure 6-4 Text Print dialog box]

The contents of the Text Print dialog box depend on the default printer you specify in the Windows control panel. Make any necessary changes in the dialog box, then click OK to print.

Closing files

To close a file in a Source window, choose Close from the Source window's File menu, or click the close button. If you've edited the file since the last time it was saved, the IDDE displays a dialog box asking if you would like to save the file.

Text Editing

This section describes the text editing features available in the Source window.

Typing mode

Source windows support two typing modes: overtype, which replaces characters as you type; and insert, which adds new characters to the file. You can toggle the typing mode between overtype and insert modes by using the Insert key. (Press Alt+I if you selected the Brief key binding set.) The typing mode is displayed in the status bar. A change in typing mode applies to all open Source windows, not just to the active window.

Word wrap

Because the editor is designed for source files, word wrap is not enabled by default. You must press the Enter key to start a new line. When you type past the right edge of the window, the text scrolls horizontally. You can enable word wrap and set a right margin either locally or globally using the text editor options.

Indentation

By default, the editor automatically indents a new line to the same depth as the previous line. You can set several indentation options, such as autoindent, tab width, and indent/ unindent after braces.

It also is possible to change the indentation of a selected block of text by choosing Indent Block or Unindent Block from the Format Text submenu of the Source window's pop-up menu.

Moving around in a file

You can move the insertion point in a file by using the mouse or keyboard in the standard Windows text-editing manner. In addition, you can jump to specific points in a file using commands from the Source window's Goto menu.

Jumping to a matching delimiter

A common source of problems in C and C++ programming is parentheses (()), brackets ([]), and braces ({}) that don't match. To find the other half of a pair of these delimiters, position the insertion point in front of one of the delimiters and choose Matching Delimiter from the Goto menu. The insertion point then moves to the front of the other half of the pair.

Delimiter checking can also be done automatically using the text editor options described later in this chapter.

Note: The IDDE editor looks for any parenthesis, bracket, or brace, including text in strings and comments.

Jumping to a specific line

To jump to a specific line, choose Line from the Goto menu. The Goto Line dialog box, shown in Figure 6-5, opens.

[Figure 6-5 Goto Line dialog box]

Type the line number in the textbox and click OK. The editor moves the insertion point to the beginning of the specified line.

Jumping to a function

To jump to a specific function, choose Function from the Goto menu. The Goto Function dialog box, shown in Figure 6-6, opens.

[Figure 6-6 Goto Function dialog box]

You can select a function name from the scrolling list or type in a function name. The insertion point then moves to the beginning of the specified function.

Jumping to a bookmark

The IDDE text editor lets you position bookmarks anywhere in your files by choosing Bookmark from the Source window's Goto menu. The Bookmarks dialog box, shown in Figure 6-7, opens.

[Figure 6-7 Bookmarks dialog box]

To use bookmarks, first position the insertion point where you want the bookmark to be located. Then choose Bookmark from the Goto menu, select a bookmark, and click on the Drop button. When you want to return to this location, click on this entry's name in the list of bookmarks, then click on Goto.

Selecting text

Text selection is accomplished using one of two standard techniques: clicking and dragging the mouse or shift-clicking. The IDDE text editor provides additional modes for text selection using the Column and Line commands in the pop-up menu's Select submenu.

Both commands require that you first select a block of text in the standard manner. Column changes the currently selected text block into a column-oriented select block; only the characters in the columns between the start and end of the original text block are selected. This is shown in Figure 6-8.

[Figure 6-8 A column select block]

Line changes the currently selected text block into a line-oriented select block; all the lines from the start to the end of the original text block, including the first and last lines, are selected.

This is shown in Figure 6-9.

[Figure 6-9 A line select block]

Choosing Normal from the Select submenu of the pop-up menu changes a column-or line-oriented text block back to the original selection. Cancel deselects the current selection block; this can also be accomplished by clicking somewhere outside the selected text.

The text editor supplies standard Windows functions for cutting, copying, pasting, and deleting text. These functions can be accessed through either the Edit menu or the pop-up menu. In addition, by clicking and dragging a block of selected text, you can reposition the text anywhere in the buffer. Press the Control key while releasing the block to copy rather than move the block. When you are dragging text blocks around in this way, a small outlined box is drawn next to the cursor to indicate this mode.

Searching and replacing

The IDDE editor has powerful text-based search and replace functions that let you search open files for a string and replace one string with another. In addition, you can search through any set of source files, whether or not they are open or in your project.

Finding a string

To search for a string, choose Find from the Source window's Edit menu. The dialog box shown in Figure 6-10 opens.

[Figure 6-10 Find dialog box]

If you select some text before opening the Find dialog box, the selected text becomes the default search pattern. You can either use this text as it appears, select a previous string from the drop-down list, or type in a new string. Then click on the Next (or Previous) button. The editor locates and selects the next (or previous) occurrence of the string in the active file. You can repeat the search in the same direction by choosing Repeat Find from the Edit menu. If the pattern is not found, the editor returns to the current insertion point and displays Pattern not found in the status line.

By checking Regular Expression in the Find dialog box, you can use the wildcard characters ? and * in your search string. The ? character matches any single character, while the * character matches any string of consecutive characters. Regular expressions permit more powerful text searches.

Replacing a string

To replace an occurrence of a string in your file with another string, choose Replace from the Source window's Edit menu. The Replace dialog box opens, as shown in Figure 6-11.

[Figure 6-11 Replace dialog box]

Type the search string or regular expression in the Pattern textbox, just as you did in the Find dialog box described earlier. Then type the replacement string in the Replacement textbox. Note that wildcards cannot be used in the Replacement textbox. You can also select previous search and replacement strings from the drop-down list. Begin the replacement by clicking OK.

If you check the Confirm Changes option, the editor scrolls the display to each occurrence of the search string, selects it, and asks whether you want to replace it by displaying the Confirm Replacement dialog box in Figure 6-12.

[Figure 6-12 Confirm Replacement dialog box]

Click on Yes to replace the string and continue searching, or click on No to continue searching without replacing. Click on Cancel to stop searching. If you do not check Confirm Changes, the editor replaces all occurrences of the search string without confirmation messages.

You can use the Undo command to undo the entire set of replacements of the search string.

Searching through multiple files

The text editor's global find feature provides a powerful means of locating a string in any set of files. For example, this feature is useful for: To search for a string in multiple files, choose Global Find from the Source window's Edit menu.

The Global Find dialog box opens, as shown in Figure 6-13.

[Figure 6-13 Global Find dialog box]

To perform a global search, first specify the set of source files you want to search. You can choose to search:

Next, specify the string or regular expression to search for. (As with the Find command, you can preselect the search text before choosing Global Find.) When you click OK, the editor opens the Search window. The editor searches through the indicated files and lists the names of files containing a match in the Search window.

By double-clicking on a filename, you can open the file; the first occurrence of the pattern is highlighted. You can continue searching for your string or expression in that file by choosing Repeat Find from the Source window's Edit menu. For more information, see Chapter 21, Text Editor Reference.

Undoing edits

You can undo typing, cutting, pasting, and string-replace operations by choosing Undo from the Edit menu. Undo multiple edits by repeatedly selecting the Undo command. You can set the number of editing operations that can be undone in the text editor options.

Text Editor Options

Global text editor options are set in the Editing/Browsing Settings dialog box, shown in Figure 6-14. To open this dialog box, choose Text Settings from the Edit menu. (You can also choose Editing/Browsing Settings from the Environment menu; in this case you will have access to Class and Hierarchy Editor options as well.)

[Figure 6-14 Editing/ Browsing Settings dialog box]

The Editing/Browsing Settings dialog box is a tabbed dialog that contains numerous options for different aspects of the text editor:

Several text editor options can be set on a buffer-by-buffer basis. To set these local options, choose Current Buffer Settings from the Edit menu. The Current Buffer Options dialog box, shown in Figure 6-15, opens.

[Figure 6-15 Current Buffer Options dialog box]

This dialog lets you override global indentation options, set word wrap, and set the buffer to read-only.

You can find detailed information about text editor options in Chapter 21, Text Editor Reference.

Macros

The text editor has powerful macro facilities. You can record a sequence of keystrokes, save the sequence as a named macro, assign a keyboard shortcut to the macro, place the macro in the Macro menu, edit the macro, and so on. To record a macro, choose Record Macro from the Macro menu; to end the macro, choose Stop Recording. You can play back the stored sequence by choosing Play Macro.

Compiling Files and Checking Errors

The IDDE makes it easy to iteratively edit and check your source code. To save and compile the current buffer, choose Compile from the Source window's File menu. The IDDE compiles the file using the current project build settings. If the compilation is successful, the file is marked as compiled. If the compilation generated errors, you can quickly locate the line in your source code that generated the error by double-clicking on the error in the Output window.

For more information about compiling files and building the project, see Chapter 8, Testing an Application.

7. Adding Look and Feel with Resources

Any application written for the Windows environment needs an interface to the user that gives it the "look and feel" of a Windows application. Various standard mechanisms are available to create this look and feel, and resources are some of the most important of these. Resources such as menus and dialog boxes define the interface to an application.

ResourceStudio contains tools for creating and modifying the resources. This chapter defines the different types of resources and explains how to use ResourceStudio to create three basic resources: menus, dialog boxes, and bitmaps. The final section describes how to work with the identifiers by which resources are referenced in the source code.

For more information about ResourceStudio, see ResourceStudio Resource Editor. For more information on resources and programming with resources, refer to the following texts:

What Are Resources?

Resources are structured data objects that define Windows user interface elements. When you choose a command from a menu or select options from a dialog box, for example, you are interacting with an application's resources. Predefined resource types include bitmaps, cursors, icons, fonts, dialog boxes, menus, accelerators, strings, and version information.

An application's resources typically are defined in a resource script file (.rc). Each resource definition contains information and data relevant to that resource type, as well as the identifier by which the resource is referenced in the source code. Resource script files are created and edited with ResourceStudio.

Resources are compiled by a special resource compiler and are linked to the Windows application separately from the application code. This modular design enables you to modify the appearance of an application without changing, or even accessing, the program source code. Separating resources from code also makes it easier to use the same resource definitions for multiple applications.

Resource Types

Create and edit the following resource types in ResourceStudio:

Bitmaps

Bitmaps are used by an application to display pictures on the screen. Each bit, or group of bits, in a bitmap represents one pixel of the image. Bitmaps may be any size you specify.

Cursors

Cursors are small bitmaps, usually 32 x 32 pixels in size, that represent the mouse pointer. Cursor images may contain areas that are transparent, allowing the screen background to show through unused parts of the cursor image. Cursors also may contain inverted areas in which the screen background color is reversed.

In addition to image information, a cursor resource also specifies the cursor's hot spot, the exact pixel in the image that maps to the mouse pointer's screen location.

Icons

Icons are small bitmaps, usually 32 x 32 or 16 x 32 pixels in size, that represent applications or actions within an application. For example, when you minimize a Windows application, an icon is displayed on the screen to represent the minimized program. Like cursors, icons may contain transparent and inverted areas.

Fonts

A font resource is a collection of up to 256 bitmaps of identical height. A font typically represents a character set, but it also may be used for more efficient management of bitmaps not representing characters.

Dialog boxes

Dialog boxes are windows that communicate information and receive user input. For example, a dialog box may let the user set program options, or alert the user to an error and ask how to proceed. To enter information and make selections in a dialog box, a user manipulates graphical elements called controls. Commonly used controls include buttons, check boxes, listboxes, textboxes, and scroll bars.

A dialog box resource is a complex set of data describing each control in detail, as well as general properties such as the dialog box size and location.

Menus

Menus are hierarchical lists of program commands and options. When a user chooses an item from a menu, either an action is taken or another menu opens to provide additional commands. A menu resource identifies the available commands, specifies their individual styles and attributes, and determines the order in which they appear.

Accelerators

Accelerators are key combinations a user presses to perform a task in an application and are frequently used as shortcuts to menu choices. An accelerator resource contains a collection of key combinations and associated commands.

Strings

Strings are text that an application may use in window titles, menus, dialog boxes, error messages, and so on. A string resource is a table of strings.

Version information

The Version Information resource contains version information for Windows .exe and .dll files, such as version number, file description, company name, and copyrights.

User-defined resources

User-defined resources contain data that you define and use in your program in any manner you choose. For example, you may want to attach a table of data or a block of text to your executable file. ResourceStudio allows you to include these types of data in your application's resources and to edit the data in hexadecimal format.

Using ResourceStudio

ResourceStudio can be used to: This section explains how to start ResourceStudio and use it to create resource files. Detailed steps are provided for creating three basic resources: menus, dialog boxes, and bitmaps. This section also outlines several useful features of ResourceStudio, such as drag and drop.

Starting ResourceStudio

Start ResourceStudio using any one of several commands available in the IDDE's Resource menu:
Edit
opens the current project's resource (.rc) file for editing.
New
opens the current project's resource file. A dialog box then opens, allowing you to create a new resource.
Open
opens a dialog box from which you can select for editing any file that contains resources.
Settings
opens ResourceStudio to the Settings dialog box, but does not load any resource file.
You can also double-click on a resource file in the Project window to open that file for editing with ResourceStudio.

To create a new resource file, choose Open from the Resource menu, and in the File Open dialog box click Cancel. Then, double-click on the ResourceStudio icon on the desktop. The Resource Studio Shell window opens (Figure 7-1).

Figure 7-1 Resource Studio Shell window
Figure 7-1 Resource Studio Shell window

The Shell window is ResourceStudio's main window and contains the main menu and toolbar. From this window, you can create and open resource files and set ResourceStudio preferences.

Another window that will open as you work is the Property Sheet. The Property Sheet does not open immediately, but rather opens when it is first needed. While creating and editing resources, you can use the Property Sheet to view and edit properties of the currently selected object. (In this context, "object" refers to either a resource as a whole or to an element within a resource, such as a dialog box control or a menu item.) Some types of objects have multiple pages of properties; to switch between pages, simply click on the tabs.

Creating a new resource file

Resources are contained in resource files. Use ResourceStudio to create and edit most types of files that store Windows resources. For example, you can edit the resources of executable files even if you do not have the original source code.

To create a new resource file, choose New from the File menu. The New File dialog box opens (Figure 7-2), listing the types of resource files that can be created with ResourceStudio.

Figure 7-2 New File dialog box
Figure 7-2 New File dialog box

Select the type of resource file you want to create (see Table 7-1). Note that resource script (.rc) and binary resource (.res) files usually contain more than one resource. If you are starting to create resources for a new application, .rc is likely to be your choice of file type. Resource scripts can contain any type of resource.

Table 7-1 Resource file types
File Type Extension Contains
Resource script .rc Any type or combination of resources in text format
Binary resource .res Any type or combination of resources in binary format
Icon .ico A single icon resource in binary format
Cursor .cur A single cursor resource in binary format
Bitmap .bmp A single bitmap resource in binary format
Font .fnt A single font resource in binary format

Resources such as icons can be contained either in individual icon resource files (.ico) or with other resources in a resource script file. Some resources, such as dialog boxes and menus, are contained only in .rc or .res files. Thus, these resource options do not appear separately in the New File dialog box.

The Platform option in the New File dialog box lets you create resource files that are compatible with Windows 3.1, Windows NT, or Windows 95. You can also elect to create resources for an MFC application by checking Support MFC.

Warning: If dialog boxes for NT come out with a white background, select Windows 95 as the target platform. This is because the Windows NT target is for NT 3.51, an old version.

After selecting a type of resource file, click OK. The window that opens next depends on the type of file you specified. If you selected one of the file types containing a single resource (icon, cursor, bitmap, or font), that resource type's editor opens in a separate window.

If you selected Resource Script or Binary Resource, the Browser window opens (Figure 7-3).

Figure 7-3 Browser window
Figure 7-3 Browser window

The Browser window has three main areas:

Resource Types:
A listbox containing all the resource types found in the current file.
Resources:
A listbox containing resources of the currently selected type.
Preview/Edit:
A display of the selected resource. Resources also are opened for editing in this area when created, or by choosing Edit Resource from the File menu.
When a new resource file is first opened, the Resource Types and Resources listboxes are both empty.

Note: ResourceStudio has several subprograms, each of which is used to edit a particular resource type. In this chapter, for example, you will use the Menu editor, Dialog box editor, and Bitmap editor. Each individual resource editor can either be opened in a separate window or can use the right pane of the Browser window from which it is launched. The latter is the default behavior in most circumstances.

Editing a resource file

Besides the resource files listed in the previous section, you can edit the resources of executable files, even though you don't have the original source code. By choosing Open from the Shell window's File menu, you can open files of any type listed in Table 7-1, plus files of the following types: Warning: Do not modify or save the resources of a running application. Saving a resource usually changes the locations of the resources within the file.

Creating a new menu resource

The main interface between the user and a Windows application is generally the application's menu. The IDDE's Resource menu is a good example, as shown in Figure 7-4.

Figure 7-4 A typical menu
Figure 7-4 A typical menu

A menu is a hierarchical structure containing pop-up items, menu items, and separators.

To create a new menu resource, choose New Menu from the Resource menu of the Browser window. The Menu editor opens in the right pane of the Browser window (Figure 7-5).

Figure 7-5 Menu editor open in Browser window
Figure 7-5 Menu editor open in Browser window

Note: While a resource editor is open in the Browser window, the Browser window's menu is replaced by that of the particular resource editor. The editor's toolbar is displayed at the top of the right pane, below the Browser window's toolbar.

The new menu resource initially contains a single pop-up item and a menu item. The list of items is indented to show the hierarchy. Pop-up items are labeled POPUP, menu items are labeled MENUITEM, and separators are labeled SEPARATOR. The currently selected item is enclosed in a box; to select any item, click on it. The Property Sheet shows properties of the selected item.

The Test menu window (Figure 7-6) opens at the same time. You can test the menu in progress at any time in this window.

Figure 7-6 Test menu window
Figure 7-6 Test menu window

Adding a pop-up item

Start creating a menu by adding a new pop-up item to the menu bar. To do so, click on Menu at the head of the item list. Then choose New Popup from the Menu menu. The new pop-up item is inserted at the start of the list.

The Property Sheet displays the properties of the new pop-up item (Figure 7-7). At this point, you probably want to change only the menu name, which is contained in the Text field.

Figure 7-7 Properties of a Pop-up menu
Figure 7-7 Properties of a Pop-up menu

When changing the menu name, you can also assign an activation key to the menu. Put an ampersand (&) in front of the corresponding letter in the text.

Adding a menu item

To add one or more menu items to a drop-down menu, first make sure that the pop-up item is selected. Then choose New Item from the Menu menu. The new menu item is inserted into the hierarchy.

The Property Sheet displays the properties of the new menu item (Figure 7-8). You can change the item's text and add an activation key. As with pop-up items, you add an activation key by typing an ampersand (&) in front of the corresponding letter in the text.

Figure 7-8 Properties of a menu Item
Figure 7-8 Properties of a menu Item

The ID field contains the command ID, which is sent to the application when the user chooses this menu item. New command and resource IDs are assigned automatically to new objects when they are created; you can also change ID names and numerical values as desired. For more information on resource IDs, see the section "Managing Resource IDs" later in this chapter.

Adding separators

Separators enhance the readability of menus. To insert a separator after the currently selected item, choose New Separator from the Menu menu.

Editing menus

The normal editing operations (cut, copy, paste, and delete) work with items in a menu. Note that when you perform one of these operations on a pop-up item, all of the items it contains are affected as well.

Rearrange menu items quickly by clicking and dragging. To move an item, drag the item to the location where it should be inserted. If you hold down the Control key while dragging, a copy of the selected item is inserted. The copy is given a new, unique resource ID.

You can also rearrange menus with the arrow keys. To move an item up or down within its present level in the hierarchy, press Ctrl+Up Arrow or Ctrl+Down Arrow. To move an item horizontally, use Ctrl+Right Arrow or the Ctrl+Left Arrow.

Closing the menu editor

After you have arranged your new menu, close the Menu editor by choosing Close Editing from the File menu. The Browser window is updated to show the new resource (Figure 7-9).

Figure 7-9 Browser window after creating menu resource
Figure 7-9 Browser window after creating menu resource

The Resource Types list contains an entry called Menu to show that you have at least one menu resource. The Resources list contains the ID of your menu resource. The Preview/ Edit area shows a preview of the new menu.

The Property Sheet displays the menu resource's ID and memory options (Figure 7-10).

Figure 7-10 Properties of a menu resource
Figure 7-10 Properties of a menu resource

To edit a menu resource, double-click on its ID in the Resource list, or select the resource and choose Edit Resource or Edit in Separate Window from the File menu.

Creating menus with accelerators and item help

As you create menus, you usually want to assign accelerator key combinations and item help strings at the same time. To do so, you must set up the string and accelerator tables before adding menu items, as outlined here:
  1. Create a string table resource by choosing New String Table from the Browser window's Resource menu.
  2. Close the String Table editor by choosing Close Editing from the File menu.
  3. Create a new accelerator table resource by choosing New Accelerator Table from the Browser window's Resource menu.
  4. Close the Accelerator Table editor by choosing Close Editing from the File menu. Note the accelerator table's resource ID.
  5. Create a new menu resource by choosing New Menu from the Browser window's Resource menu.
  6. Make the new menu's resource ID the same as that of the accelerator table resource. In the Property Sheet, select the accelerator table resource's ID from the drop-down list in the ID field. You now can add menu items with accelerators and item help.
To set a menu item's accelerator, click on the Connect tab in the Property Sheet, then click on the Next Key. You are prompted to press the key combination that is used as the accelerator. When you do so, the accelerator is stored in the associated accelerator table. To set a menu item's help string, type the string into the Prompt field in the Property Sheet. The string is automatically placed in the string table.

To show which key combination is associated with each menu item, add the accelerator to the item text. For readability, the accelerator is usually separated from the command name with a tab. For example, if you want Ctrl+F to be the accelerator for a command called Find, enter Find\tCtrl+F into the Text field of the menu item's Property Sheet (Figure 7-11).

Figure 7-11 Menu item text
Figure 7-11 Menu item text

Simple guidelines for creating menus

When creating a menu, keep in mind the following points: Windows users are accustomed to certain menu arrangements. For example, the File menu is usually the first menu in the menu bar and contains commands such as New, Open, and Save. Choose commands from the Menu menu to quickly create standard File, Edit, and Help menus.

Creating a new dialog resource

A dialog box is a window that communicates information and receives user input. It contains graphical elements called "controls." Figure 7-12 shows a typical dialog box.

Figure 7-12 A typical dialog box
Figure 7-12 A typical dialog box

The following types of controls can be included in your dialog boxes:

To create a new dialog box resource, choose New Dialog Box from the Resource menu of the Browser window. The DialogExpress dialog box opens (Figure 7-13).

Figure 7-13 DialogExpress dialog box
Figure 7-13 DialogExpress dialog box

DialogExpress gives you several options for simple dialog boxes that you may use as a starting point for your own dialog box. Select Standard and click OK. The Dialog editor opens in the right pane of the Browser window (Figure 7-14).

Figure 7-14 Dialog editor open in Browser window
Figure 7-14 Dialog editor open in Browser window

At the same time, the Dialog editor toolbox (Figure 7-15) opens. This toolbox provides shortcuts to commands in the Tool menu that let you create the different types of dialog box control.

Figure 7-15 Dialog editor toolbox
Figure 7-15 Dialog editor toolbox

The Property Sheet shows the General, Styles, and Look properties of the dialog box (Figure 7-16). You may want to start by changing the dialog box title.

Type the new title into the Text field of the General properties page.

Figure 7-16 Properties of a dialog resource
Figure 7-16 Properties of a dialog resource

Adding a push button

Initially, a new Standard dialog has no controls. To create a new push button:
  1. Choose Push Button from the Tool menu or click on the corresponding icon in the toolbox.
  2. Click in the dialog box on the point at which you want to position the upper-left corner of the new button. Hold down the left mouse button and drag the cursor. A rubber-band rectangle appears.
  3. Release the left mouse button when the rectangle is the proper size for the new button. A new push button is placed in your dialog box (Figure 7-17).
Figure 7-17 Dialog box resource with new push button
Figure 7-17 Dialog box resource with new push button

The new push button is selected and highlighted. Then move and resize the new push button control with the mouse.

You also may center the selected control in the dialog box. Choose Vertical or Horizontal from the Center submenu of the Controls menu.

The Property Sheet lets you modify push button properties (Figure 7-18). To change the button text, for example, change the Text field to the desired text. As with items in menus, you can set the activation key of a button or other control by typing an ampersand (&) before the corresponding letter in the text.

Figure 7-18 Properties of a push button control
Figure 7-18 Properties of a push button control

Adding static text

To add static text to a dialog box (for example, an informational message), choose Text from the Tool menu or click on the corresponding icon in the toolbox. Then click in your dialog box and drag the rubber-band box to the desired size.

The Property Sheet shows the properties of the static text (Figure 7-19). To change the text, edit the Text field. After entering the text, you can resize the static control to the size of the text by dragging the handles.

Figure 7-19 Properties of a static text control
Figure 7-19 Properties of a static text control

To center the text within the control, select Center from the drop-down list in the Align/ Style property. Center the control within the dialog box by choosing Horizontal from the Center submenu of the Controls menu.

A static text control may contain multiple lines of text. While typing text into the Caption field, press Ctrl+Enter to start a new line. Likewise, insert tab characters by pressing Ctrl+Tab.

Testing the dialog box

Test the dialog box resource without leaving ResourceStudio. To open the new dialog box for testing, choose Test Dialog from the Dialog menu (Figure 7-20).

Figure 7-20 Testing the new dialog box
Figure 7-20 Testing the new dialog box

When you are testing the dialog box, ResourceStudio does not function; you must close the test dialog box by pressing Alt+F4 before continuing.

Aligning controls

Commands are available to align controls, to space them evenly, and to make them the same size. The following steps illustrate the three operations:
  1. Add a few odd-sized buttons to your dialog box, using the procedure described in the section "Adding a push button" earlier in this chapter. Place them in a horizontal row.
  2. Select all the buttons at once by clicking on one, then holding down either the Shift or Control key as you click on the others. You can also choose Select from the Tool menu and drag a rubber-band box around the controls.
  3. Establish one button as the "standard." Hold down Control and click on this button. The standard button is highlighted in blue on your screen. Figure 7-21 shows what your dialog box might look like. In the example, the button labeled "# 2" has been selected as the standard.
Figure 7-21 Multiple selection of controls
Figure 7-21 Multiple selection of controls

Now you can perform any of the following alignment operations from the Controls menu:

You also can move the selected controls as a unit by holding down the left mouse button and dragging them to a new location.

Closing the dialog box editor

After finishing with a dialog box, close the Dialog editor by choosing Close Editing from the File menu. The Browser window is updated to show the new resource (Figure 7-22).

Figure 7-22 Browser window after creating dialog box resource
Figure 7-22 Browser window after creating dialog box resource

After creating a dialog box resource, you can use ClassExpress to create a corresponding dialog box class, set up the class's message map, and implement dynamic data exchange and validation. ClassExpress can be run directly from the Browser window's File menu. For further information, see Chapter 18, More about ClassExpress, as well as Chapter 13, Lesson 4: Add Messages with ClassExpress and Chapter 14, Lesson 5: Add a Dialog Box with ClassExpress.

Creating a new bitmap resource

A bitmap is a picture that may be used for informational or decorative purposes. The Bitmap editor contains the functionality of a typical paint program, allowing you to create pictures of any size in 2, 16, or 256 colors.

To create a new bitmap resource, choose New Bitmap from the Resource menu of the Browser window. The BitmapExpress dialog box opens (Figure 7-23).

Figure 7-23 BitmapExpress dialog box
Figure 7-23 BitmapExpress dialog box

BitmapExpress allows you to set the number of colors and the initial size of the bitmap. If you are creating a bitmap for an MFC toolbar, you also can specify the number of buttons. For now, accept the defaults and click OK. The Bitmap editor opens in the right-most pane of the Browser window (Figure 7-24).

Figure 7-24 Bitmap editor open in Browser window
Figure 7-24 Bitmap editor open in Browser window

The Bitmap editor window is divided into two panes. Draw in either. To change the relative sizes of the panes, click and drag the bar separating the panes.

The Bitmap editor toolbox (Figure 7-25) also opens. This toolbox lets you choose graphics tools (also available in the Tool menu), set foreground and background colors, and select the line width and background pattern.

Figure 7-25 Bitmap editor toolbox
Figure 7-25 Bitmap editor toolbox

The Property Sheet shows the General and Palette properties of the bitmap (Figure 7-26). Page between the two groups of properties by clicking on the tabs. The File field specifies the bitmap file; bitmaps are included in resource scripts by reference. If you want to change the bitmap file's name, type a new name into the File textbox.

Figure 7-26 Properties of a bitmap resource
Figure 7-26 Properties of a bitmap resource

Changing bitmap size

To change the bitmap size, change the width and height in the Property Sheet or resize the bitmap directly by dragging one of the handles along the right and bottom edges of the bitmap.

Selecting colors and patterns

Select drawing color and patterns from the toolbox in the following way:

Drawing tools

These drawing tools are available in the toolbox or in the Tool menu: To select a drawing tool, click on the tool in the toolbox. To use a tool, click or click and drag (as appropriate) with either the left or the right mouse button. Tools make use of the current line type and background pattern whenever possible. Using the right mouse button to click or click and drag reverses the roles of foreground and background colors.

Zoom and grid

Work with an image at normal size or zoom by factors of 2, 4, or 8. To zoom, click in the pane containing the image, then select a Zoom command from the View menu. Set one image at normal size for reference and a second image at a larger size for easier drawing.

To help finish the details of the image, you can display a pixel grid in the image. A pixel grid can be displayed only when the zoom factor is 4 or 8. To show a pixel grid, choose Grid from the View menu.

Closing the bitmap editor

After finishing with the bitmap, close the Bitmap editor by choosing Close Editing from the File menu. The Browser window is updated to show the new resource (Figure 7-27).

Figure 7-27 Browser window
Figure 7-27 Browser window

Useful ResourceStudio features

A number of ResourceStudio features are useful for creating and editing different resources. These include toolbars, the undo and redo functions, and the dragging and dropping of items.

Toolbars and pop-up menus

ResourceStudio makes extensive use of toolbars. Toolbar icons offer quick access to frequently used menu items. For a list of toolbar commands, see the "ResourceStudio Reference."

In many parts of ResourceStudio, clicking with the right mouse button opens a pop-up menu. The contents of the menu depend on the item clicked and on the current mode or tool. Pop-up menus are a convenient way to access commands available from the main menu.

Undo and redo

ResourceStudio can undo any operation or redo any operation that was undone. To undo the previous operation, choose Undo from the Edit menu or click on the Undo icon in the toolbar. Notice that the operation that will be undone is noted within the Undo menu item. To instead redo an action that was just undone, choose Redo from the Edit menu.

Operations that you have performed are saved in lists. To set the number of operations that are saved (and thus that can be undone or redone), choose Preferences from the Shell window's Edit menu. Each Browser window and each resource type's editor keeps its own undo and redo list.

To view a list of stored operations, click the right mouse button on the Undo or Redo toolbar icon. Select one or more operations from the list (see Figure 7-28).

Figure 7-28 List of stored operations in Bitmap editor
Figure 7-28 List of stored operations in Bitmap editor

Clipboard and drag and drop

ResourceStudio supports cut, copy, and paste of resources and of objects within resources, such as dialog box controls and menu items.

ResourceStudio also supports drag and drop of all items that can be cut, copied, and pasted. To move a resource or resource element, click and drag it to the new location. For example, to move resources from one file to another, open a Browser window for each file, then drag the resources from the first file to the second. To copy rather than move the element, hold down the Control key until you have released the item.

Managing Resource IDs

Windows programs identify resources by a resource name, which can be a string or a number. Windows programs also use numbers to identify commands resulting from menu selections and accelerators and to identify dialog box controls. The number of identifiers used in a single application easily can run into the hundreds. One of the major features of ResourceStudio is its ability to automatically create and manage resource IDs.

Resource ID field

Many property pages contain an ID field for the current resource or resource element. There are three types of resource IDs in ResourceStudio:

Textual IDs

Textual IDs are allowed only for certain resource types. To specify a textual ID, enclose the text in the ID field in double quotes. ResourceStudio warns you if you try to assign a textual ID to a resource type for which it is not allowed.

Symbolic IDs

Symbolic IDs are names that correspond to numbers. By using this type of ID, you work with names that are meaningful, leaving ResourceStudio to keep track of the numbers that match the names. Symbols and their corresponding numbers are saved in the resource header file as #define statements. Thus the same symbols can be used to refer to the resources in your application code.

Assign a symbolic ID either by typing the name into the ID field or by selecting a pre-existing ID from the drop-down list. If you enter a new symbol, ResourceStudio automatically assigns a unique numeric value. If you want to specify the numeric value, follow the symbolic name with an equal sign and the value (for example, IDD_ TEST= 451). Reassign the value of an existing symbol in the same way.

Numeric IDs

Numeric IDs should not be used in new resource script (.rc) files; use symbolic IDs instead. If you create a binary resource file (.res), or edit the resources in an existing .exe or .dll file, you see the resource IDs as numbers, because the symbolic information is not saved for these file types. Assign a numeric ID by typing the number into the ID field.

Note: When editing resources in .exe or .dll files, remember that the compiled source code refers to resources and commands by the numeric (or textual) ID; reassigning or changing IDs may result in incorrect behavior.

Automatic creation of resource IDs

ResourceStudio automatically creates a new resource ID every time one is needed. The new ID is unique within its context: for resource elements, the ID is unique within the resource and, for resources, unique within the resource file.

When assigning values to new symbols typed in by the user or created automatically, ResourceStudio uses different ranges for various purposes:

Resource item range (100-1999)
Used for resources within a resource file
User range (2000-2999)
Used for resource IDs created by the user from within the Resource ID Browser dialog box (see below)
Control range (3000-31999)
Used by the Dialog editor for dialog controls
Command range (32000-65535)
Used by menu and accelerator editors for menu commands

Resource ID browsing

To browse and modify resource IDs, choose Edit Resource IDs from the File menu.

The Resource ID Browser dialog box opens (Figure 7-29).

Figure 7-29 Resource ID Browser dialog box
Figure 7-29 Resource ID Browser dialog box

The upper listbox shows all the symbolic resource IDs in the resource file. Symbols can be sorted by name, value, or used/ unused state. Click on an ID to show a list of resources using the ID in the lower listbox. Open a resource shown in the lower listbox by double-clicking on it, or by selecting it and clicking View Usage.

The remaining buttons are:

New
Opens the New Resource ID dialog box. Here you can create a new symbol and assign a value. By default, the value is in the User range (2000-2999).
Delete
Deletes the currently selected symbol. A symbol may only be deleted if it is not in use.
Change
Opens the Change Resource ID dialog box. Here you can change the symbol name or value.
Renumber
Performs a renumbering operation on all symbolic IDs. Each symbol is examined and a new value is assigned based on how it is used. If a symbol is used by items whose values are usually in different ranges, a dialog box asks for the range in which to place the value.

8. Testing an Application

This chapter provides an overview of building, running, and debugging an application in Digital Mars C++. Whenever you finish making any significant addition or change to the source files of an application, it is wise to test the result and verify that you have achieved your goals. To do so, you must first build (or rebuild) the executable so that it incorporates your modifications. Then you must observe its behavior- either by tracing through modified sections, or at least by running the application under the control of the debugger.

This entire phase of the development cycle can be carried out in the IDDE. Because all debugging in Digital Mars C++ takes place within the IDDE, you do not have to leave the IDDE and run a separate debugger. The IDDE itself provides a wealth of tools for examining all facets of your application's structure and behavior.

Two other chapters present detailed information about the debugging capabilities of Digital Mars C++. Controlling and Configuring the Debugger describes the commands you use when debugging, and the options available in the IDDE for configuring the debugging environment. Commands Available in Debugging Mode, describes the commands available in each of the debugging windows.

Debugger Highlights

The integrated debugger:

Choosing an Environment for Debugging

There are three versions of the IDDE included with Digital Mars C++. An icon for each version you install is available in your Digital Mars C++ program group. These different versions of the IDDE are essentially identical, except that they allow you to debug different kinds of executables:

Building a Project

To test an application, you must first build the executable file, which is the file you test. Your project specifies the source and library files needed to build the executable, as well as options that control the build process. Windows executables also incorporate such resources as menus, dialog boxes, icons, and bitmaps; these are defined in resource files. The building process begins by compiling the source files into object files. Object files are then linked with library files to create the executable file.

Selecting the project type

You must specify the type of executable you plan to build. You do so by choosing Settings from the Project menu and clicking on the Target tab to select the Target page, as shown in Figure 8-1.

[Figure 8-1 Target page of the Project Settings dialog box]

On this page, choose the operating system your target executable will run on, and the target type. Not all target types are available with all operating system types.

The Target page also presents the option of building a Debug or Release version of the executable. If you want to debug your executable, select the Debug option.

For more information on the Target page of the Project Settings dialog box refer to More about Projects and Workspaces.

Setting compiler and linker options for debugging

When you indicate that a debugging version should be built, the IDDE sets the appropriate compiler and linker options, and also prevents debugging information already in object files from being discarded.

To verify that the these settings are appropriate, choose Settings from the Project menu, and then click on the Build tab to select the Build page of the Project Settings dialog box. Select the Debug Information subpage by clicking on that label in the left listbox. The Debug Information subpage is shown in Figure 8-2.

[Figure 8-2 Debug Information options]

For more information about project, compiler, and linker options, see More about Projects and Workspaces.

Building executable files

The IDDE provides three ways to build executable files from your project: by performing a standard build, by rebuilding the entire project, or by linking the existing object files.

Performing a standard build

This is the most common of the three build options. To begin, choose Build from the Project menu. The IDDE recompiles only those files that changed since you last compiled them, then links the project. The IDDE displays any errors in the Output window.

The IDDE Make facility is used by default to determine the steps needed to build your project. It is functionally identical to the DOS command-line Make utility SMAKE, included with Digital Mars C++. If you need to use a different, DOS command-line Make utility, such as NMAKE or PolyMake, you can do so; see More about Project Build Settings, for details on how to use an external Make program.

Rebuilding the project

If you want to recompile every file in your project- even those files that are up-to-date- choose Rebuild All from the Project menu. The IDDE recompiles all files in your project, whether they've been edited recently or not, then links the project.

Typical situations in which you use the Rebuild All command include:

Linking the project

If you want to build a program with the existing object files but without recompiling your source files, choose Link from the Project menu. The IDDE links the object files.

Typical situations in which you use the Link command include:

Other project options

The Build page of the Project Settings dialog box offers additional settings that you may find useful for precompiling headers and generating an assembly listing.

Precompiling headers

The Header Files subpage lets you precompile one or all of the header files that are included by source files in your project. Precompiling a header is useful when the header file changes infrequently or not at all between builds, or when a header file is included by most of the source files in a project. Precompiled headers speed up the build process, especially with large header files. For example, windows. h can be beneficially precompiled because it is large and is not likely to change.

Generating an assembly listing

The Assembly Listing (.COD) check box on the Output subpage lets you create a .cod file that contains the assembly language code into which the compiler converts your source code. In this file, C++ source statements are preserved as assembly language comments. Each commented statement precedes the assembly language code to which it corresponds.

Running a Project

You can run the application that your project produces without leaving the IDDE. Commands that run your application ask you to build it if required.

If your program requires no command-line arguments, choose Execute Program from the Project menu. The IDDE launches your application.

If your program requires arguments, first choose Arguments from the Project menu. The IDDE displays the dialog box in Figure 8-3.

[Figure 8-3 Run Arguments dialog box]

Enter your arguments -- not the program name -- in the dialog box. For example, entering:

*.* /s 
launches your program with the arguments *.* and /s.

After specifying the arguments, click OK. Then run your application as described above.

Quick Start: Debugging an Application

This section provides a brief description of how to perform common debugging tasks. You can find a complete presentation of the debugging capabilities of Digital Mars C++ in Controlling and Configuring the Debugger, and in Commands Available in Debugging Mode. In Chapter 23, see especially the sections "Commands on the Debug Menu" and "Debug Toolbox Icons."

After building your project, you can enter debugging mode by choosing Start/Restart Debugging (F4) from the Debug menu. (That is, you may either choose this command from the menu, or type its keyboard shortcut given in parentheses.) Alternatively, you can click on the Restart Debugging icon in the Debug toolbox. Any open Source windows change to debugging mode. Your application executes to the breakpoint set automatically on WinMain (for Windows applications) or main (for DOS applications and 32-bit console applications).

Other debugging windows, such as the Function window and Data/ Object window, can be opened as needed from the Views toolbox or from the Goto View submenu of the IDDE's Window menu.

In debugging mode, the Start/Restart Debugging command on the Debug menu remains available. This command restarts the program. The Stop Debugging command on the Debug menu exits debugging mode, and returns the IDDE to editing mode.

Stepping through code

To step to the next source code statement, choose Step Into (F8) from the Debug menu. Alternatively, you may click on the Step Into icon in the Debug toolbox. If the current line is a function call, and debugging information is available for that function, you will trace into that function. To step over a function call, choose Step Over (F10) from the Debug menu, or click on the Step Over icon in the Debug toolbox.

Note: If you accidentally step into a function call when you meant to step over it, you can move to where you intended to be- the statement following the call- by choosing Return from Call from the Debug menu. This command executes to the current function's return address (unless a breakpoint or watchpoint is encountered before control reaches that point).

Setting and clearing breakpoints

Setting a breakpoint on a source code statement causes your program to stop when execution reaches that statement. The debugger regains control, and you may again perform any debugging mode actions.

To set a breakpoint on a statement, first click on that statement in the Source window to make it the selected line. Then choose Set/Clear Breakpoint (F9) from the Source window pop-up menu (which appears when you click the right mouse button in the Source window), or click on the Toggle Breakpoint icon in the Debug toolbox. These commands act as toggles; repeating them clears the breakpoint.

The Source window pop-up menu, as it appears in debugging mode, is shown in Figure 8-4.

[Figure 8-4 Source window pop-up menu in debugging mode]

A breakpoint symbol in the left margin of the Source window indicates a breakpoint on the adjacent line. You can also clear a breakpoint by dragging the symbol out of the Source window.

Executing up to a statement

To execute up to the currently selected line, choose Go Until Line from the Source window pop-up menu. Double-clicking on any line in the Source window causes your program to run until execution reaches that line.

Viewing a list of functions

The Function window lists the functions in the current module or in all modules. Toggle the display by choosing Current Module or All Modules from the View menu. Double-click on any function to view that function in a Source window.

You can easily set a breakpoint at the beginning of a function from within the Function window by choosing the Set/Clear Breakpoint (F9) command from the Bpt menu.

Examining the values of variables

The Data/Object window lets you view either global data or the variables local to a function. The Show menu of the Function window has commands Global Data and Local Data that select the type of data displayed in the Data/Object window. If you choose Local Data, the Data/Object window shows the local variables for the function currently selected in the Function window, provided that function is in the call chain. (If a function is not in the call chain, it has no local data.) The display can also be toggled by choosing Local/Global Data from the View menu of the Data/Object window.

Examining the call chain

The Call window displays the stack of function calls in your code that have not yet returned. The list is presented in reverse chronological order from most to least recent; thus, WinMain (or main) is at the bottom of the list.

The Call window's Show menu contains commands that let you zoom in on a particular function in the chain. For example:

Setting watchpoints

A watchpoint specifies that execution of your program should stop when a particular variable or memory location is written to or read from. This capability is essential for detecting problems arising from wild pointers, for example, which can manifest themselves in extremely elusive and seemingly random behavior.

Digital Mars C++ debuggers are designed to take advantage of hardware watchpoints provided by 386 and higher microprocessors. The Digital Mars C++ installation program may install the file SCWDEBUG. 386 in the [386Enh] section of system. ini if your system needs it to allow the use of hardware watchpoints. Because watchpoints are implemented with hardware assistance, using this powerful tool imposes no speed penalty on program execution.

Setting a watchpoint on a variable

Using the methods described in the sections above, make sure that the desired variable is displayed in the Data/Object window. Click on the line referencing the variable to select it; the line should be highlighted. Choose Set Watchpoint (Ctrl+ W) from the Watch menu of the Data/Object window. This opens the Set Watchpoint dialog box, shown in Figure 8-5.

[Figure 8-5 Set Watchpoint dialog box]

The debugger maintains information about the type of variables and their location in memory. The selected variable's type determines the size of the watchpoint. The Set Watchpoint dialog box displays the address and size of the watchpoint as noneditable fields, and provides options for breaking on a Read access, Write access, or both. To clear the watchpoint, choose Clear Watchpoint from the Watch menu of the Data/Object window.

Warning Exercise caution when setting a watchpoint on an automatic variable (that is, a local, nonstatic variable). If you attempt to set such a watchpoint, the debugger warns you by displaying a message on the status line. You should clear the watchpoint by the time the function whose local variable you are watching returns. If you don't, Windows itself can use the stack location subsequently, thus triggering the watchpoint and causing Windows to crash.

In addition to setting watchpoints on variables, watchpoints can also be set on locations in memory using the Memory window, whose Watch menu is identical to that of the Data/Object window.

Letting your program run until the next breakpoint

You can make your program run until execution reaches a breakpoint by choosing Go until Breakpoint (F5) from the IDDE's Debug menu, or by clicking on the Go until Breakpoint icon in the Debug toolbox. You can use the Breakpoint window to see at a glance where breakpoints have been set.

Letting your program run until it terminates

You can make your program run until it terminates -- ignoring any breakpoints -- by choosing Go until End from the Debug menu.

Interrupting execution of the debugged application

Use the Ctrl+Alt+SysRq key combination to break execution of the application being debugged and return control to the debugger. It may be necessary to press this key combination a few times before the debugger regains control. (If you use this key combination to break execution when control is within Windows itself, it may be difficult for the debugger to step out of Windows code.)

The technique is most useful when you suspect that your own code is hung. Returning to the debugger lets you examine your program's state, which may be one that you thought impossible. Inspecting the values of variables and the call chain can suggest how to identify and eliminate the source of the error.

Note: Use Ctrl+Alt+F11 to break execution of Win32s applications.

9. Introduction to the Tutorial

Welcome to Digital Mars C++. This section of the manual contains a tutorial designed to introduce you to the important components and features of the Integrated Development and Debugging Environment (IDDE) -- the "shell" within which most of your application development takes place.

The tutorial is designed to complement Part Two, "Creating an Application with Digital Mars C++." The tutorial provides a quick tour of the IDDE that shows you how to perform the most common tasks. Part Two contains more in-depth information, to show you procedures for less common tasks and alternative ways of accomplishing things.

Prerequisite Knowledge

This tutorial assumes that you are familiar with the Windows environment -- that you can start applications from the Program Manager, move and resize windows, operate menus and dialog boxes, and perform simple text editing tasks (such as cut, copy, and paste). The tutorial also assumes some familiarity with C, C++, and Windows programming basics. You need not know anything about the Microsoft Foundation Class (MFC) library; MFC basics are introduced here.

For more information, consult the references listed in Chapter 1, Introducing Digital Mars C++.

The Tutorial Application

The application built in the tutorial lets you read and navigate through hypertext. Two versions are built: a DOS version (in Lesson 1) and a Windows 3.1 version (in Lessons 2-5). Most of the code for the application has been written; the tutorial just shows you certain stages in the development process to familiarize you with IDDE tools.

The hypertext files that the tutorial applications accept as input are text files containing simple commands that control document formatting and show images as well as commands that define links to other such documents. The markup language recognized by the tutorial applications, referred to throughout the tutorials as TML, is a subset of the Hypertext Markup Language (HTML). HTML is a format that has become a standard for information interchange on the World-Wide Web (WWW), a distributed hypermedia system accessible through Internet connections.

Special WWW browser programs enable users worldwide to access and share text, graphics, audio, and other data. The tutorial applications only hint at the richness of full-featured WWW browsers. The DOS TML Reader built in Lesson 1 is called TMLDOS; the Windows version of Lessons 2 through 5 is called TMLRead.

Tutorial Structure

The tutorial comprises five lessons that include instructions for performing various tasks. Following these instructions will teach you basic procedures and familiarize you with IDDE tools. Each lesson builds on concepts and procedures introduced in previous lessons, so it is best to work through the lessons in order.

Tutorial Source Code

The source code for the tutorial is located in samples\tutorial, under the directory in which you installed Digital Mars C++ (by default, this is c:\dm\samples\tutorial). The samples\tutorial directory contains a subdirectory corresponding to each lesson (these subdirectories are named lesson1, lesson2, lesson3, lesson4, and lesson5).

Each lesson's subdirectory (except lesson2) contains three subdirectories, named start, finish, and backup.

The subdirectory for Lesson 2 contains only a finish subdirectory. The start subdirectory is created as part of the lesson.

The source and executable of the final DOS version of the TML Reader is contained in tutorial\tmldos. The source and executable of the final Windows version is located in tutorial\tmlread.

10. Lesson 1: Create the DOS Application

In this chapter you learn basic procedures for using the Integrated Development and Debugging Environment (IDDE) while building a DOS version of the TML Reader. This lesson teaches you to: Most of the code for the application has already been written; during the lesson you will add a few final lines. At the end of the lesson, you will have a DOS executable that can read and display TML files.

Starting the IDDE and Loading a Project

To start the IDDE:

First, start the IDDE. If you haven't yet installed Digital Mars C++, please see the Getting Started Guide for installation instructions.

  1. Double-click on the Digital Mars C++ 16-bit group icon in the Windows Program Manager. (If the Digital Mars C++ 16-bit group is already open, you may omit this step.)
  2. Double-click on the Digital Mars C++ icon. The IDDE main window opens at the top of the screen (see Figure 10-1).

    [Figure 10-1 The IDDE main window and Workspace toolbox]

The IDDE main window contains a title bar and a menu bar. Below the main window is the Workspace toolbox, used to switch between workspaces (described later in this chapter). The Workspace toolbox is currently docked under the IDDE menu bars. Additional IDDE windows open below the main window and Workspace toolbox. You can open other IDDE windows by selecting their names from the Goto View submenu of the Window menu; close any window by clicking the Close button in its upper-left corner.

Next, you must load the DOS TML Reader project. (A project is a collection of source and other support files from which an executable is generated.) To open the project:

  1. Choose Open from the IDDE's Project menu.
  2. Use the Open Project dialog box to find samples\tutorial\lesson1\start\tmldos.prj, located under the directory in which you installed Digital Mars C++.
  3. Click OK.
You can view the project's source file list in the Project window. If the Project window is not already open, choose Project from the Goto View submenu of the Window menu.

In the next section you edit one of the source files.

Editing Source Code

The DOS TML Reader's source code needs a minor addition before compilation. To add the missing lines, you must edit the source code in a Source window.
  1. In the Project window, double-click on display.c. A Source window opens, showing the contents of the source file (see Figure 10-2).

    [Figure 10-2 Source window]

  2. Choose Function from the Source window's Goto menu. The Goto Function dialog box opens.
  3. Select Display from the Function Name listbox, then click OK. The editor moves to the start of Display().
  4. Choose Find from the Edit menu. The Find dialog box opens.
  5. In the Pattern textbox, type LESSON 1.
  6. Click on Next.
  7. You should see the following line in the source code:
    	/* INSERT CODE FOR LESSON 1 HERE! */ 
    	
    Just after this comment, but before the procedure's closing brace, insert the following two lines of code:
    	disp_move(disp_numrows - 1, 0);
    	disp_eeol(); 
    	
  8. Choose Save from the File menu.
The DOS TML Reader is now ready to be compiled. In the next section you learn to build and run the project, and you look at a sample document.

Building and Running the Application

To build and run the DOS TML Reader:
  1. From the IDDE's Project menu, choose Rebuild All.

    The Output window opens automatically. This window informs you of build progress and displays any warning or error messages. If no errors exist, you see the message "Successful build." (You can still work in the IDDE while the build is in progress, because the process of building is multitasked. The Output window can be behind other IDDE windows, even when messages are being written to it.)

  2. From the IDDE's Project menu, choose Arguments. The Run Arguments dialog box opens.
  3. Type sample.tml into the textbox and click OK.
  4. From the Project menu, choose Execute Program.
The TML Reader opens in full-screen mode, showing the formatted contents of sample.tml (see Figure 10-3). You can use Page Up, Page Down, and the arrow keys to scroll through the file. To execute a hyperlink, position the cursor over text shown in reverse video and press Enter. Press Escape to exit the program and return to the IDDE.

[Figure 10-3 The DOS TML Reader]

The DOS TML Reader is believed to be without any significant bugs. However, most applications have bugs during at least some of their development phase. To help you locate and correct incorrect code as quickly as possible, the IDDE has powerful debugging features.

The following sections show you how to set up a workspace for debugging and debug your source code.

Setting Up a Workspace for Debugging

A workspace is an arrangement of windows on the screen. You can set up several useful configurations of IDDE windows, then switch between them by clicking on workspace names in the Workspace toolbox.

The IDDE predefines a workspace named Debugging, which contains a configuration of windows useful for typical debugging sessions. Here, however, we define a new workspace specific to this lesson, to show you how this is done and to avoid disturbing any customizations you may have already made to the Debugging workspace.

To create a workspace for debugging:

  1. Choose New from the Workspace submenu of the IDDE's Environment menu.
  2. When prompted for a workspace name, type Lesson1.
  3. Click OK.
The IDDE creates a new workspace and adds the workspace name to the Workspace toolbox. Initially the new workspace is empty, with the exception of a few toolboxes that are not needed here. To close the toolboxes, click the Close buttons in the upper-left corners.

Next, you need to add windows to the workspace. During debugging, the Source window follows program execution, the Function window views a list of functions in a particular program module, the Data/ Object window views program data, and the Call window displays the program call chain.

  1. To open the Project window, press Ctrl+Shift+P.
  2. In the Project window, double-click on main.c. A Source window opens.
  3. To open the Function window, press Ctrl+Shift+F.
  4. To open the Data/Object window, press Ctrl+Shift+D.
  5. To open the Call window, press Ctrl+Shift+L.
Other debugging windows are available as well; see Chapter 24, Commands Available in Debugging Mode, for more information.

Arrange the windows the way you want them (one example is shown in Figure 10-4), then choose Save Workspace Set from the Workspace submenu of the IDDE's Environment menu.

[Figure 10-4 A possible Lesson 1 workspace]

Now that the workspace is ready, you can begin debugging. The following section shows you how to run the application in debugging mode and how to set a breakpoint on a function, how to view program data, and how to step through code.

Running in Debugging Mode

To execute the application in debugging mode, click in the Source window, then choose Start/Restart Debugging from the IDDE's Debug menu. Several things happen:
  1. The IDDE opens a window (the Digital Mars Application Window), in which the application runs. This window may be behind other windows.
  2. The application is executed to the start of main.
  3. The Source window changes to debugging mode (see Figure 10-5). Arrows indicating execution points within functions, and flags indicating breakpoints are shown in the left margin. You cannot edit the code while in debugging mode.

    [Figure 10-5 Source window in debugging mode]

  4. The Project window changes to debugging mode (see Figure 10-6). The icons next to the source module names change to indicate their status:
  5. The Function window is updated to show a list of functions in the program (see Figure 10-6). An arrow next to main indicates that it is in the call chain; a diamond indicates that a breakpoint is set.

    [Figure 10-7 Function window]

  6. The Call window is updated to show the call chain and execution status (see Figure 10-8).

    [Figure 10-8 Call window]

You can now perform the following simple debugging tasks.

Setting and running to breakpoints

To set a breakpoint on a function and execute to it:
  1. Click and drag display.c from the Project window to the Source window.
  2. Choose Set/Clear Breakpoint from the Bpt menu. A breakpoint is set at the start of ShowScreen.
  3. Choose Go Until Breakpoint from the IDDE's Debug menu. The program is executed to the start of ShowScreen.
The Source window shows the line at which execution stopped. The Call window shows functions in the call chain (see Figure 10-9).

[Figure 10-9 Call chain to function ShowScreen]

Viewing data

You can view program data using the following commands:
  1. Choose Data from the Show submenu of the Source window's pop-up menu. The Data/Object window is updated to show the local data in ShowScreen (see Figure 10-10).

    [Figure 10-10 Data/Object window showing local data]

  2. In the Call window, click on main, then choose Data from the Show menu. The Data/Object window is updated to show the local data in main.
  3. Choose Local/Global Data from the Data/Object window's View menu. The Data/Object window is updated to display global data accessible in the current module. Choose Local/Global Data again to resume display of local data.

Stepping through code

To step through the source code line-by-line:
  1. Choose Step Into from the IDDE's Debug menu (or press F8) seven times. The IDDE executes seven lines of code. The seventh step takes execution into ShowLine; at that point the Call window adds ShowLine to the call chain, and the Data/Object window is updated to display the function's local data.
  2. Choose Return from Call from the IDDE's Debug menu to execute the rest of ShowLine and return to the calling function.
  3. Choose Step Over from the IDDE's Debug menu (or press F10) several times. The IDDE executes some lines of code in the function, but it does not step into subroutines. ShowScreen is in a loop that writes lines to the screen one-by-one. The results appear in the Digital Mars Application Window.

Running to the end

To execute the rest of the program, ignoring breakpoints, choose Go Until End from the IDDE's Debug menu. Bring the Digital Mars Application Window to the front and test the program as usual. You can press Alt+Ctrl+SysRq to break to the debugger, or let the program terminate before resuming your debugging session. (In the DOS TML Reader, you must press Escape to end the program.)

Ending the debugging session

To exit debugging mode, choose Stop Debugging from the IDDE's Debug menu. You can do this at any time during debugging; you don't have to choose Go Until End first.

In this chapter you have learned how to start the IDDE, load a project, edit source code, build and run the application, and run in debugging mode. These are the fundamental tasks you perform repeatedly as you develop your own applications, whether you are developing in C or C++, for DOS or for Windows. In the following lessons, you learn about the IDDE's more advanced features, many of which are designed specifically for Windows application development in C++.

11. Lesson 2: Generate an Application Framework

In this chapter you begin the process of building a Windows version of the TML Reader. This version is built around a Microsoft Foundation Class (MFC) version 2.5 Single Document Interface (SDI) framework. In this lesson you: At the end of the lesson you will have a working application framework with menus, a toolbar, and a status bar. The framework itself will respond to certain commands, but the functionality needed to read and display TML files is not yet included. In subsequent chapters you modify the user interface for the TML Reader and add the necessary file input and display routines.

There are many ways to create an application framework. This lesson provides the most straightforward way.

Generating the Framework

In this lesson you use AppExpress to generate a new project containing an application framework. To start AppExpress:
  1. Start the IDDE and close any open project by choosing Close from the Project menu.
  2. Start AppExpress by choosing AppExpress from the Tools menu.
The AppExpress window opens (shown in Figure 11-1).

[Figure 11-1 Setting up an SDI application with AppExpress]

AppExpress contains six pages of options that together define the project to be generated. You define these options in six steps, listed in the upper-left portion of the window. For this project, you need to change options on only four of the six pages. Set up the project options as follows:

  1. On the Application Type page (shown when AppExpress is started), select SDI.
  2. Deselect Include Help to suppress generation of Windows Help support.
  3. Click on Next to switch to the Select Directory page. Change to the samples\tutorial\lesson2 directory under the directory in which you installed Digital Mars C++, then click on Create New Directory.
  4. Type start in the textbox and click Create.

    Note: To avoid filename conflicts, it is a good idea to keep each project you create in a separate directory.

  5. Click on Next to switch to the Miscellaneous page. Type your company name and suffix (or your own name) in the appropriate textboxes. This information is displayed in the automatically generated About dialog box, and in comments at the beginning of each source file.
  6. In the Project Name textbox, type TMLRead.
  7. Click on Next to switch to the Names page. You can customize the names of automatically generated classes here. From the Name drop-down list, select CTMLReadApp. In the Edit textbox, type CTMLReadApp.
  8. Click Finish.
AppExpress generates a new project in the directory you created. The directory contains: After generating the project, AppExpress closes and control returns to the IDDE. The new project is loaded automatically. The IDDE parses the new project's source files for browsing with the Class and Hierarchy Editors; parsing progress is displayed in the Output window.

Building and Running the New Project

Next you build the project and learn what the default application framework can do.
  1. From the IDDE's Project menu, choose Rebuild All.
  2. From the Project menu, choose Execute Program.
The IDDE minimizes itself and the TMLRead application opens (shown in Figure 11-2).

[Figure 11-2 New application framework generated by AppExpress]

At present, default functionality for several menu commands is provided by the MFC base classes. For example, if you choose Open from the File menu, a standard Windows File Open dialog box opens. You can select a file in this dialog box, but the code needed to read data from the file is not yet installed.

To close TMLRead and return to the IDDE, choose Exit from the File menu.

The project can take a considerable amount of time to compile. Next you learn how to decrease compilation time by using precompiled headers.

Using Precompiled Headers

In the last section, over 70,000 lines of code were read during compilation. Many of these lines are in Windows and MFC header files that are changed infrequently (if ever), but still must be included by almost every source file. To speed compilation, you can precompile header files; thereafter, the symbols generated by the compiler can be loaded directly.

To precompile the Windows and MFC header files:

  1. Choose Settings from the Project menu. The Project Settings dialog box opens.
  2. Click on the Build tab.
  3. In the left listbox, click on Header Files.
  4. In the Precompile section of the right pane, select Specific Header.
  5. In the textbox below the Specific Header selection, type stdafx.h.

    Note: You can specify multiple specific headers to precompile by entering in this textbox a list of their names separated by semicolons or spaces.

    [Figure 11-3 Using precompiled headers]

  6. Click OK.
  7. An Editor/Browser message box is opens, noting that project settings have changed and asking if you want to reparse all files. Click No, because you are about to build in the next step, which will stop any parse in progress.
  8. From the IDDE Project menu, choose Rebuild All.
During the rebuild, the header file stdafx.h is precompiled, then the source files are compiled using the precompiled symbol table. You should notice a significant reduction in the number of lines compiled, as well as a corresponding increase in compile speed.

Now that you have created, compiled, and executed the application framework, the rest of the chapter helps you to understand the framework's structure. The following three sections are optional.

Adding TRACE Calls with Class Editor

In the remainder of this chapter, you investigate calls to member functions of the MFC-derived classes created by AppExpress to understand the structure of the application framework and the relationships between the classes. To do this, you use the Class Editor to insert calls to the MFC global TRACE macro into the member functions, then watch the output in the Trace Messages window.

To add a TRACE call to the application class's constructor:

  1. Choose Class Editor from the Goto View submenu of the IDDE Window menu. The Class Editor window opens (see Figure 11-4).
  2. Under Classes, click on CTMLReadApp. The application class's members appear in the Members list.
  3. Under Members, double-click on CTMLReadApp. The application class constructor's source code is shown in the source pane.
  4. Add the following line to the constructor:
    	TRACE("CTMLReadApp::CTMLReadApp()\n"); 
    	
    The constructor should now appear as follows:
    	//////////////////////////////////////////////////////////////////
    	// CTMLReadApp construction 
    
    	CTMLReadApp:: CTMLReadApp()
    	{   
    	    TRACE("CTMLReadApp::CTMLReadApp()\n");
    	    // TODO: add construction code here, 
    	    // Place all significant initialization in InitInstance
    	} 
    	
  5. Press Ctrl+S to save the modified constructor.

[Figure 11-4 Adding TRACE calls with Class Editor]

You can add similar TRACE calls to these other member functions:

When you have finished, choose Build from the IDDE Project menu to recompile the source files you have changed.

In the next section you execute the application and watch the TRACE output in the Trace Messages window.

Watching TRACE Output in the Trace Messages Window

To watch TRACE output, first you must set up the Trace Messages window to receive and display TRACE messages.
  1. Choose Trace Messages from the Goto View submenu of the IDDE's Window menu. The Trace Messages window opens.
  2. Choose Output to Window from the Options menu of the Trace Messages window.
  3. Choose MFC Debug Messages from the Options menu. The MFC Trace Debug Options dialog box opens.
  4. Check Enable Tracing and uncheck any other options that are checked. Click OK.
You are now prepared to run the application and view the output of the TRACE macro calls.
  1. Choose Execute Program from the IDDE's Project menu.
  2. The IDDE is minimized and the application window opens. Double-click on the IDDE icon to reopen the IDDE windows. Position the windows so you can watch the Trace Messages window while the program executes.
The Trace Messages window has already received several messages from the application's class constructors and initialization code (Figure 11-5). You see more messages if you choose Open or New from TMLRead's File menu, or when the window needs to be repainted.

When you close TMLRead, the Trace Messages window receives messages from the application's class destructors.

[Figure 11-5 TRACE output in the Trace Messages window]

The next section gives an overview of the classes in the application framework and explains the messages you see in the Trace Messages window.

The Application Framework and MFC Classes

In this chapter, you have used AppExpress to build an application framework, a skeleton on which you can build a Windows application, consisting of C++ classes contained in and derived from classes in the Microsoft Foundation Class (MFC) library.

The MFC library is a C++ class library that supports programming for Windows. It encapsulates most of the Windows Application Programming Interface (API), and provides additional C++ programming support such as container and string classes. The MFC library makes it easy to work with Windows elements in an object-oriented manner. For example, MFC library classes exist to represent objects such as windows, dialog boxes, controls, device contexts, Graphic Device Interface (GDI) objects, and so on. Windows API functions are implemented as member functions of the classes with which they are logically associated.

TMLRead is built on a Single Document Interface (SDI) framework. The SDI framework contains five fundamental objects:

Document:
The document contains data, reads the data from disk, and provides access to the data. In TMLRead, the document is an object of type CTMLReadDoc, derived from the MFC library class CDocument.
View:
The view displays the data contained by the document. In TMLRead, the view is an object of type CTMLReadView, derived from the MFC library class CView (which is, in turn, derived from CWnd, the base class for all types of windows).
Document Template:
The document template defines the association between document and view classes. In an SDI application, this is an object of type CSingleDocTemplate.
Frame Window:
The frame window object is the application's main window. In TMLRead it contains a toolbar, a status bar, and the view. The frame window is an object of type CMainFrame, derived from the MFC library class CFrameWnd.
Application:
The application object creates and controls the other objects, and takes care of general program initialization and cleanup. In TMLRead the application is an object of type CTMLReadApp, derived from the MFC library class CApplication.
The framework itself provides standard user-interface implementations for some commands (for example, file open and save); you must add support for certain framework functions (such as file input and output), as well as add other command and message-handling capability specific to your application.

The TRACE output from the previous section lets you see the creation, use, and destruction of objects in the application. For example, when you start the application, you see the following messages:

	[00001] NOTIFY(StartTask)
	[00002] CTMLReadApp::CTMLReadApp() 
	[00003] CTMLReadApp::InitInstance()
	[00004] CTMLReadDoc::CTMLReadDoc() 
	[00005] CMainFrame::CMainFrame()
	[00006] CMainFrame::OnCreate() 
	[00007] CTMLReadView::CTMLReadView()
	[00008] CTMLReadDoc::OnNewDocument() 
	[00009] CTMLReadView::OnDraw() 
The application object is created first. Using a document template, the application object creates the document, frame window, and view objects. It then calls the document object to set up a new document. Finally, when the window is shown, the framework calls the view's OnDraw() function to repaint the window.

If you choose New from TMLRead's File menu, you see the following messages:

	[00010] CTMLReadDoc::OnNewDocument()
	[00011] CTMLReadView::OnDraw() 
Or, if you choose Open from the File menu, then select a file, you see:
	[00012] CTMLReadDoc::Serialize()
	[00013] CTMLReadView::OnDraw() 
The document object is called either to create a new document or to read a document from a file, depending on the menu item that was chosen. Note that neither the document object nor the view object is destroyed; in an SDI application, they are reused continually.

When you choose Exit from TMLRead's File menu, the application's objects are destroyed in reverse order in which they were created. You see these messages in the Trace Messages window:

	[00014] CTMLReadView::~CTMLReadView()
	[00015] CMainFrame::~CMainFrame() 
	[00016] CTMLReadDoc::~CTMLReadDoc()
	[00017] NOTIFY(ExitTask) 
	[00018] NOTIFY(DelModule) 
There is no message from the application object's destructor, because it is not defined explicitly in the framework.

You may find it useful to continue to add TRACE calls to the application as it is built. It is often difficult to follow the workings of a message-driven system; the Trace Messages window, however, acts as a kind of passive debugger that keeps you informed of the internal workings of your application.

In the next chapter, you begin to shape the application framework to the specific needs of the application. The first step in this process is to customize the user interface with the Resource Editor.

12. Lesson 3: Customize the Interface

After an application framework has been generated with AppExpress, it is usually necessary to customize the user interface. This typically is an ongoing process; as your application evolves, you can add and remove interface elements. In this lesson you perform the initial stage of customization. You will: AppExpress generates an SDI application framework with a full set of resources. TMLRead needs only a subset of the standard user interface, so most of the work in this lesson involves trimming down the interface. At the end of the lesson you will have a modified version of TMLRead, supporting only the commands that are needed.

Before starting this lesson, start the IDDE and open the project tmlread.prj found in directory samples\tutorial\lesson3\start.

Launching ResourceStudio

An application's resources are contained in a resource script file, which includes descriptions of menus, dialog boxes, and other user interface elements. The resource script file is edited with ResourceStudio. To launch ResourceStudio:
  1. Open the Project window by pressing Ctrl+Shift+P.
  2. In the Project window, double-click on tmlread.rc.
  3. When asked if you want to use ResourceStudio to edit this file, click Yes. ResourceStudio starts, with its Shell window minimized. (The Shell window is a control center from which you can create and open resource files. You will use it later in this lesson.)
The Browser window of ResourceStudio opens (Figure 12-1). The window controls editing of the resources within an individual resource file. On startup, its upper-left pane contains a list of resource types found in tmlread.rc.

[Figure 12-1 The Browser window of ResourceStudio]

The TML Reader is only able to read and display TML files; it cannot edit or write them. Thus, you can remove menu items related to editing and saving.

Customizing the Menu

In this section you customize TMLRead's menu.

Within ResourceStudio are several individual editors, each capable of editing a single type of resource. For example, the Dialog editor is used to edit dialog box resources, and the Menu editor to edit menu resources. By default, the editors use the right pane of the Browser window.

To start the Menu editor:

  1. Click on Menu in the Browser window's upper-left pane.
  2. Double-click on IDR_MAINFRAME in the lower-left pane.
The Menu editor opens in the Browser window (Figure 12-2). Its menu replaces the Browser window's menu, and its toolbar appears at the top of the right pane.

[Figure 12-2 The Menu editor in the Browser window]

As the Menu editor opens, the Property Sheet also opens (Figure 12-2). This window is used to edit resource and resource element properties and options.

[Figure 12-3 The Property Sheet]

The Test Menu pop-up window also opens simultaneously with the Menu editor (Figure 12-2). It is a top-level window whose menu is identical to the one you are editing. This window does nothing when you choose menu items that are not top-level menu items or submenus.

Because changes you make to the menu in the Browser window are immediately reflected in the menu of the Test Menu window, you can verify your changes as you make them.

[Figure 12-4 The Test Menu window]

Now you can remove unnecessary menus and menu items.

  1. Click on "MENUITEM New" to select this menu item.
  2. Press Delete.
  3. Repeat the above steps to delete:
If you make a mistake, you can correct it by choosing Undo from the Edit menu.

To close the Menu editor, choose Close Editing from the File menu, or press Escape. The Browser window menu and toolbar return. The right pane shows a preview of the menu.

Although we have removed menu items for commands that will not be supported, at present it would still be possible to access some of those commands through their accelerators. In the next section we remove those commands from the accelerator table.

Customizing the Accelerator Table

To start the Accelerator Table editor:
  1. Click on Accelerator in the Browser window's upper-left pane.
  2. Double-click on IDR_MAINFRAME in the lower-left pane.
The Accelerator Table editor opens in the Browser window (shown in Figure 12-5). As with the Menu editor, the Accelerator Table editor's menu replaces the Browser window's menu, and its toolbar appears at the top of the right pane.

[Figure 12-5 The Accelerator Table editor in the Browser window]

Removing accelerators is quite similar to removing menu items. To remove the unnecessary accelerators:

  1. Click on ID_FILE_NEW.
  2. Press Delete.
  3. Repeat the above steps for all the accelerators, leaving only ID_FILE_OPEN and ID_FILE_PRINT.
As in the Menu editor and elsewhere in ResourceStudio, if you make a mistake, you can correct it by choosing Undo from the Edit menu.

To close the Accelerator Table editor, press Escape.

Commands may be sent to TMLRead in one other way: by clicking on buttons in the toolbar. In the next section we replace the toolbar bitmap with one containing only commands that are supported by TMLRead.

Importing a New Toolbar Bitmap

Before importing a new toolbar bitmap, delete the current toolbar bitmap:
  1. Click on Bitmap in the Browser window's upper-left pane.
  2. Click on IDR_MAINFRAME in the lower left-pane.
  3. Press Shift+ Delete.
You must now copy a bitmap from another resource script file. To do this, you open a second Browser window to view the contents of a resource script file containing the new toolbar bitmap. Then you copy the bitmap to the clipboard and paste it into tmlread.rc.
  1. Double-click the ResourceStudio icon to restore the Shell window.
  2. In the Shell window, choose Open from the File menu.
  3. Select the file newbar.rc and click OK.
  4. In the upper-left pane of the new Browser window, click on Bitmap.
  5. In the lower-left pane, click on IDB_NEWBAR. A preview of the bitmap appears in the right pane (Figure 12-6).

    [Figure 12-6 New toolbar bitmap]

  6. Choose Copy from the Edit menu. The bitmap is copied to the clipboard.
  7. Choose Close from the File menu. The second Browser window closes. Activate the Browser window containing tmlread.rc by clicking on it.
  8. Choose Paste from the Edit menu. The bitmap is added to your application's resources.
The new toolbar does not presently have the correct resource ID. For the application framework to use it correctly, this toolbar's resource ID must be identical to that of the application's menu and accelerator table resources. To set the new bitmap's resource ID:
  1. Click on the Property Sheet to bring it to the front. The Property Sheet shows the resource ID and memory options for the bitmap resource.
  2. From the ID drop-down list, select IDR_MAINFRAME.
The initial resource customization is now complete. Next you exit ResourceStudio and make a minor adjustment to update the source code that loads the toolbar.

Exiting ResourceStudio

To save your work and exit Resource Studio:
  1. Choose Save from the Browser window's File menu.
  2. Choose Close from the File menu. The Browser window closes, but the Shell window and Property Sheet remain open.
  3. Choose Exit from the Shell window's File menu.

Setting Up the New Toolbar

The MFC framework uses a single bitmap to represent a set of toolbar buttons. The correspondence between the button images in the bitmap and the commands they represent is established in an array in the source code. Because you have replaced the original toolbar bitmap, you also must update this array.
  1. In the Project window, double-click on mainfrm.cpp. A Source window opens, displaying the frame window class's source code.
  2. Scroll downward a few lines until you find the following code:
    	// toolbar buttons -IDs are command buttons
    	static UINT BASED_CODE buttons[] = { 
    		// same order as in the bitmap 'toolbar. bmp'
    		ID_FILE_NEW, 
    		ID_FILE_OPEN,
    		ID_FILE_SAVE, 
    		ID_SEPARATOR,
    		ID_EDIT_CUT, 
    		ID_EDIT_COPY,
    		ID_EDIT_PASTE, 
    		ID_SEPARATOR,
    		ID_FILE_PRINT, 
    		ID_APP_ABOUT,
    		ID_CONTEXT_HELP, 
    	}; 
    	
  3. Remove and rearrange lines until the array looks like this:
    	// toolbar buttons -IDs are command buttons
    	static UINT BASED_CODE buttons[] = { 
    		// same order as in the new toolbar bitmap
    		ID_FILE_OPEN, 
    		ID_SEPARATOR,
    		ID_FILE_PRINT, 
    		ID_SEPARATOR,
    		ID_APP_ABOUT, 
    	};
    	
  4. Save the code by choosing Save from the Source window's File menu.
The buttons[] array now contains the command IDs of the three toolbar buttons. The ID_SEPARATOR entries indicate where spaces should be placed between the button images when drawing the toolbar.

In the last section you build the application and view the results of your labor.

Building and Running the Application

To build and run the application, choose Execute Program from the IDDE Project menu. Because no executable has yet been built, the IDDE automatically builds TMLRead and then runs it. (When you try to run an existing executable that needs to be rebuilt, the IDDE asks if you want to rebuild the program before running it.)

The source files are recompiled, the resource script is compiled by the resource compiler, and all the object files and resources are linked together to create the final application. Then the IDDE minimizes itself and executes the application (Figure 12-7).

You can verify that the changes you made to the menu and toolbar are correct. To close the application, choose Exit from the File menu.

[Figure 12-7 TMLRead with customized menu and toolbar]

You now have completed initial customization of TMLRead's resources. You deleted excess menu items and accelerators and installed a new toolbar bitmap. More changes to the application's resources can be made as the need arises; in Lesson 5, for example, you will return to ResourceStudio to add support for a Preferences dialog box. In the next lesson, though, you will use ClassExpress to install functions to handle Windows messages, such as those generated by key presses and button clicks.

13. Lesson 4: Add Messages with ClassExpress

In Lessons 2 and 3, you learned how to generate an application framework and customize its user interface. However, the behavior of the resulting application is still generic, because it is supplied entirely by methods of MFC base classes. The inherited methods that handle Windows messages, in particular, often do nothing more than call DefWindowProc.

In this lesson, you use ClassExpress to expand the functionality of the TML Reader and add member functions that handle Windows messages announcing user actions. Member functions that handle Windows messages are called message handlers, or just handlers. You can think of them as callbacks, which are called by MFC when the message they are intended to process is received. A message handler is called in response to only one message.

The Windows message stream is the lifeblood of a Windows application, regardless of whether the application is constructed in an object-oriented or a procedural way. A well-behaved Windows application can interact with the user only if it taps into the message stream and responds to messages in nondefault ways. Using ClassExpress to add MFC message handlers demonstrates how easy it is to enhance the behavior of your MFC application.

In this lesson, you:

At the conclusion of this lesson, you will have: The next section provides a brief introduction to Windows message handling in MFC to help you understand how messages are handled in TML Reader.

Windows Message Handling in MFC

Regardless of how it is written, a Windows application receives messages that inform it of user actions and their consequences, changes in the state of other applications, or changes in the state of Windows itself. MFC transforms this message-driven model into the object-oriented model defined by its class hierarchy, thereby introducing several improvements to the design of applications. To discuss this transformation and its benefits, it is necessary first to review how messages are handled in a traditional Windows program, and to identify the shortcomings of that approach.

Message handling in a traditional Windows application

In a traditional Windows program written in C, you handle a Windows message by adding code directly to the window procedure to which that message is dispatched by your application's message loop. The window procedure usually consists of a large switch statement whose cases are different messages.

For example, to handle the WM_SIZE message, you must add a case WM_SIZE to the switch. The statements following that case statement must have to unpack and coerce the window procedure's parameters, wParam and lParam, into constituent parts in a way that is specific to the WM_SIZE message. The result would look much like the following:

	LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
	{
	    // local and static variables... 
	    switch (msg)
	    {   
		// ... 
		case WM_SIZE:
		{   
		    UINT nType = (UINT) wParam;
		    int cx = LOWORD(lParam); 
		    int cy = HIWORD(lParam);
		    // Now do what you really want to do 
		    // ...
		} 
		break; 
		// ... 
		default:
		    break; 
	    } 
	    return DefWindowProc(hwnd, msg, wParam, lParam); 
	} 
The switch statement usually sprawls across several pages, and the bodies of case statements often spill over the right margin of the page. Data that must be preserved across messages or shared between cases is usually stored in automatic or static variables visible to every case. The result enjoys none of the benefits of encapsulation or data hiding afforded by C++, and it is difficult to read, comprehend, and maintain.

MFC's design

In MFC, window procedures are part of MFC itself; you do not edit them. Instead, the window procedures route each message to a handler- a member function of some class- whose purpose is to process that message. MFC provides default handlers, which collectively define the default behavior of an MFC application. You supply handlers only for those messages you want to process. Each handler you supply is a member function of one of your derived classes and overrides the inherited handler in the base class.

However, you will sometimes find that your handler can call the inherited handler to perform the bulk of its work.

For example, to handle the WM_SIZE message, use ClassExpress to add a handler for this message to your View class. (By convention, the handler for the WM_SIZE message is named OnSize.) Whenever a WM_SIZE message is received by a window represented by an object of your View class, your handler is called. The prototype of this handler is as follows:

	void OnSize(UINT nType, int cx, int cy); 
Notice that the parameters of OnSize contain the same information that the WM_SIZE message bears in the wParam and lParam window procedure arguments, but in an immediately usable form. No unpacking or typecasting is required. In general, the signature of each handler- its return type, the number of its arguments and their types- is specific and appropriate to the message it processes. MFC parses the messages before calling the handler.

To route Windows messages to handlers, MFC consults tables, called message maps, that pair Windows messages with the member functions that handle them. You never have to edit message maps manually because AppExpress and ClassExpress create and maintain them for you. AppExpress creates message maps when you generate an application framework. Their definitions are placed in the implementation (.cpp) files of your derived classes. When you use ClassExpress to add a handler to a class, the message map is updated automatically with a new entry associating the chosen message with your handler. Furthermore, ClassExpress adds a prototype for the new handler to the class's header file and inserts a stub for the member function into the implementation file. All you need to do is to add code to the body of the handler.

Note: This introduction to MFC message handling has necessarily been brief and has glossed over several topics you will want to learn more about. For a definitive discussion of how MFC works, see the expository chapters of the Microsoft Foundation Class Library Reference.

Because you used AppExpress in Lesson 2 to generate an application framework for the TML Reader, message maps have already been created for your derived classes. During the course of this lesson, ClassExpress updates them. ClassExpress can be run either separately- from a Program Manager icon- or from within the IDDE. Because you will be using the Source window to edit the code that ClassExpress generates, you will launch ClassExpress from within the IDDE.

Launching ClassExpress

To launch ClassExpress from the IDDE:
  1. If you are not already in the IDDE, launch it.
  2. Open the project tmlread.prj in directory samples\tutorial\lesson4\start.
  3. Choose ClassExpress from the Tools menu. This launches ClassExpress and automatically loads the project tmlread.prj.
The ClassExpress window features a multipage interface. Its left column presents a list of the six different pages that can be displayed in the area to the right. You will work on the Message Maps page, which is selected automatically when you launch ClassExpress. The ClassExpress window is displayed, as in Figure 13-1.

[Figure 13-1 ClassExpress, displaying the Message Maps page]

The lists on the Message Maps page

The drop-down combobox at the top of the page labeled Class contains a list of all derived classes in the TML Reader application. The class selected here directly determines the contents of two lists beneath it- those labeled Control IDs in Class and Function Name.

The list labeled Control IDs in Class contains an entry for the class itself, as well as the names of any commands and controls that the selected class could potentially handle.

The list labeled Function Name contains a list of message handlers already generated for the selected class by AppExpress. These methods are referenced in the class's message map.

The contents of the list labeled Windows Messages depends on what you select in the Control IDs in Class list. If you select the class name in the Control IDs list, then the Windows Messages list contains a list of Windows messages. However, if you select a control ID, the Windows messages list contains notification messages appropriate to that type of control. If you select a command ID (usually corresponding to a menu item), the rightmost list contains names of potential message map entries for commands.

Because the TML Reader handles messages that signal user input, the handlers must be added to the class corresponding to the window that receives those messages. Thus, you will add the handlers to the View class, CTMLReadView.

Adding Message Handlers

The requirements of the TML Reader dictate the messages you will add handlers for.
WM_SIZE
Detect when the window is resized, so it can recompute word-wrapping
WM_VSCROLL
Permit scrolling through a document using the vertical scrollbar
WM_KEYDOWN
Permit scrolling through a document using the keyboard
WM_SETCURSOR
Change the cursor when it is positioned over a hyperlink
WM_LBUTTONDOWN
Detect clicks on hyperlink jumps so it can change its display
WM_ERASEBKGND
Repaint the window background

Adding a handler for WM_SIZE

To add a handler for WM_SIZE to your View class:
  1. From the drop-down list labeled Class, select the name of the View class, CTMLReadView.
  2. Use the scrollbar to move through the Windows messages list until the message WM_SIZE is visible.
  3. Double-click on WM_SIZE.
Notice that a new entry appears in the Function Name list:
	afx_msg void OnSize(UINT nType, int cx, int cy); 
This is the prototype of a handler for the WM_SIZE message, as it would appear within a class declaration.

Also notice that a solid square appears to the left of the message name, WM_SIZE, indicating that a handler now exists for that message.

The ClassExpress window is displayed, as in Figure 13-2.

[Figure 13-2 ClassExpress after adding a WM_SIZE handler]

Adding other message handlers

Follow the procedure described in Steps 2 and 3 in the previous section to add a handler for each of the messages WM_VSCROLL, WM_KEYDOWN, WM_SETCURSOR, WM_LBUTTONDOWN and WM_ERASEBKGND: use the scrollbar of the Windows messages list to scroll to the message, then double-click on the message. Again, notice that for each message you double-click on, a new prototype is added to the Function name list, and a solid square appears to the left of the message name.

What you have just done

When you add a handler for a message WM_messagename, ClassExpress generates code in three places. For example, when you add a handler for WM_SIZE, ClassExpress generates the following: Now, whenever a CTMLReadView window receives a WM_SIZE message, the member function OnSize is called to handle it.

Saving Your Work

To save your work and return to the IDDE, click Close at the bottom of the ClassExpress window.

Clicking Close updates your project files and returns you to the IDDE. To observe the handlers in action and confirm that they are indeed called when you expect them to be, you can add code that notifies you when they are called.

Adding Code to Handlers

To add code to the OnLButtonDown and OnSize handlers, follow these steps:
  1. Open the file tmlrdvw.cpp in a Source window.
  2. Find the function CTMLReadView::OnLButtonDown.
  3. Add the following line to the top of the function:
    	AfxMessageBox("Left button clicked!"); 
    	
  4. Now find the function CTMLReadView::OnSize.
  5. Add the following line to the top of the function:
    	::MessageBeep(-1); 
    	
  6. Type Ctrl+S to save your changes.
After the project is rebuilt, you'll want to confirm that the appropriate statement executes whenever you click in the client area or resize the window.

Building and Running the Project

To see the effect of what you've done, perform these steps:
  1. Choose Build from the Project menu to update the executable.
  2. Choose Execute Program from the Project menu to run the program.
  3. With the mouse cursor in the client area of the program's window, press the left mouse button. A box containing the message "Left button clicked!" is displayed (Figure 13-3). This message is displayed each time you press the left mouse button in the client area. It is not displayed when you release the left mouse button, move the mouse, or click with the right mouse button. To remove the message box, click OK.

    [Figure 13-3 TML Reader running, with message box displayed]

  4. Now resize the window by dragging a corner of the window's border to a different position. You hear a beep when you release the mouse button.

    Note: You will already have heard beeps during the initial sequence of messages received by the View window. This is normal: the window receives multiple WM_SIZE messages early in its life-cycle.

  5. After you have confirmed to your satisfaction that the handlers are called when, and only when, they ought to be called, quit the program by choosing Exit from TMLRead's File menu.

Summary

In this lesson, you have learned: In the next lesson, you implement a Preferences dialog box. You learn how MFC and ClassExpress make it easy to create a dialog box, validate its data, and exchange data between the dialog box and your application. In TML Reader's present state, the only preference one could have would be for the application to actually do something. Toward that end, we have added code to the result of this lesson so that your starting point in the next lesson is a functioning TML Reader.

14. Lesson 5: Add a Dialog Box with ClassExpress

In Lesson 4, you learned how to use ClassExpress to add handlers for Windows messages. The application from that lesson is still skeletal. Its interface is complete, and it receives the Windows messages it needs to act upon, but every user action ultimately results in a call to a stub function. After completing Lesson 4, the next step is writing code that supplies functionality.

This lesson shows you how to use some additional, powerful features of Digital Mars C++. To accomplish this, a body of code that supplies some substantial functionality has been added to the application you built in Lesson 4. In between the end of Lesson 4 and the start of this lesson, only the Source window has been used to create or change C++ files in the project. That is, none of the new code has been automatically generated; it has all been manually entered.

Start this lesson with the project samples\tutorial\lesson5\start\tmlread.prj, located in the directory where you installed Digital Mars C++. The first task you will perform is to build that project. Once you have done so, you will have a fully functional TML Reader.

In the remainder of the lesson, you will implement a Preferences dialog box. In addition to supplying C++ code for the start of this lesson, we have also already used ResourceStudio to create a dialog resource that defines the Preferences dialog box. However, this dialog box is not yet connected to the application. It lies dormant within tmlread.rc. You will perform all the tasks necessary to animate it and make it fully functional.

Specifically, you'll use ResourceStudio to:

Within ClassExpress, you'll: Finally, within the IDDE, you will: After completing this lesson, you will have: The next section walks you through building and running the TML Reader. It also discusses how the Reader displays files and how to create a Preferences dialog box which lets the user configure how the files are displayed.

Building and Exploring the TML Reader

This section acquaints you with the major features of the TML Reader. After building the Reader, you will use it to read sample files that contain TML formatting strings.

Before building the Reader, you must first copy the file viewhdrs.h from the tutorial\tmlread directory to the tutorial\lesson5\backup directories. Various TMLRead modules include this header file, and cannot be compiled without it.

Building the Reader

Follow the first four steps to build the TML Reader.
  1. If you are not already in the IDDE, launch it.
  2. Open the project tmlread.prj in the directory samples\tutorial\lesson5\start located beneath the directory where you installed Digital Mars C++.
  3. Choose Build from the Project menu.
  4. Choose Execute Program from the Project menu to run the program. The IDDE minimizes, and TMLRead is launched. No file is yet displayed.

Exploring the capabilities of the Reader

Now use the Reader to browse two sample files that illustrate the kinds of formatting that the Reader can display.
  1. Choose Open from TMLRead's File menu.
  2. In the File Open dialog box, select the file sample.tml in the samples\tutorial\lesson5\start directory, then click OK. TMLRead reads, parses, and displays the file.
  3. Scroll within the document using the arrow keys and the Page Up and Page Down keys. Code within CTMLReadView::OnKeyDown causes the scrolling to occur.
  4. Now scroll by using the vertical scroll bar. In this case, code within CTMLReadView::OnVScroll is responsible for the scrolling.
  5. Drag either the left or right border of the window to resize it. Notice that the ends of lines are automatically adjusted so that paragraphs wrap properly, filling almost all of the window's width. The handler CTMLReadView::OnSize causes rewrapping to occur.
  6. If you are not now displaying the beginning of the file, press the Home key. The heading "Contents" announces the table of contents of this document, presented as a hierarchical bulleted list of the major sections of sample.tml. Each line in the table of contents is underlined and displayed in green. These properties of the text indicate that it is a hyperlink. Place the cursor over any hyperlink; the cursor changes to a hand with an extended index finger, a visual cue that you can meaningfully click on the text. Move the cursor so that it is not over a hyperlink; the cursor reverts to the default cursor. This behavior is provided by CTMLReadView::OnSetCursor after a necessary initialization by CTMLReadView::PreCreateWindow.
  7. Click on the last hyperlink in the Contents section, named "Hyperlinks," with the left mouse button. This displays the last section of the file. The method CTMLReadView::OnLButtonDown handles the mouse click by determining whether or not it occurred on a hyperlink; if a hyperlink is clicked, the jump occurs.
  8. At the end of the last paragraph, there is the following hyperlink phrase: "here is a link to another sample document." Click on this phrase. The file complex.tml is read and displayed. Again, CTMLReadView::OnLButtonDown causes the jump to occur.
  9. Choose Previous File from TMLRead's File menu to return to sample.tml.
  10. Examine each section of sample.tml by clicking each hyperlink in the document's contents at the top of the file. This will give you a good sense of the features of TML, the subset of HTML (HyperText Markup Language) recognized by the Reader.
  11. Choose Print Preview from TMLRead's File menu to see a WYSIWYG display of how sample.tml would look if it were printed on the current default printer. The presence and functionality of the buttons at the top of the Print Preview window has been supplied almost entirely by MFC. When you finish looking at the Print Preview display, click Close to return to the main view of the Reader.
  12. Choose Exit from TMLRead's File menu. This closes the Reader and returns you to the IDDE.

Turning aspects of the Reader's display into preferences

A few numerical quantities that help determine how TMLRead displays documents are at present hard-coded. These numbers are stored as int data members of CTMLReadView and are described in the following table:
nParVSpace
Vertical space between paragraphs
nMargin
Amount of horizontal space between the document and the edges of the window
nIndent
Amount by which items in a list are offset from the left margin
The CTMLReadView constructor calls CTMLReadView::SetDefaultPrefs to initialize these data members with default values provided by the following enum constants (defined in the class declaration):
	eDftParVSpace = 12
	eDftMargin = 10 
	eDftIndent = 40 
The Preferences dialog box lets the user alter these values, as shown in Figure 14-1.

[Figure 14-1 The Preferences dialog box]

Of course, the user should be allowed to configure many other aspects of the Reader's display, such as colors and fonts. However, implementing this simple Preferences dialog box gives you the fundamental skills needed to realize more ambitious designs using the Digital Mars C++ tools.

Before you connect the Reader's data with the controls of the Preferences dialog box, you need to first outfit the user interface with a way to call the dialog box. In the next section, therefore, you'll use ResourceStudio to add a menu item to TMLRead.

Using ResourceStudio to Add a Menu Item

To add a Preferences item to the View menu of TMLRead, launch ResourceStudio from within the IDDE so that it loads tmlread.rc. To do this, follow these steps:
  1. Open the Project window if it is not already open.
  2. Double-click on tmlread.rc in the Project window. When asked if you want to use ResourceStudio to edit this file, click Yes.

    The Browser window of ResourceStudio opens, as shown in Figure 14-2.

    [Figure 14-2 The Browser window of ResourceStudio]

  3. Select the item named Menu in the upper-left pane. The lower-left pane now displays the ID of the TMLRead menu, IDR_MAINFRAME.
  4. Double-click on IDR_MAINFRAME in the lower-left pane. The pane on the right now contains a representation of the TMLRead menu, shown in Figure 14-3.

    The Property Sheet and the Test menu window also open; they are described in Chapter 12, "Lesson 3: Customize the Interface."

    [Figure 14-3 ResourceStudio displaying the TMLRead menu]

  5. In the right pane, click on the item MENUITEM Status Bar to select it. This item is the last one belonging to the POPUP View item. When a new menu item is added, it will appear beneath this one.
  6. Choose New Item from the Menu menu in the Browser window. This inserts a new item whose text is Item, and creates a new ID for it. The Property Sheet, shown in Figure 14-4, shows these settings.

    [Figure 14-4 The Property Sheet after adding a new item]

  7. Click on the Property Sheet to make it active.
  8. Click on the General tab near the top of the window to ensure that the General page is displayed.
  9. In the ID textbox, type ID_VIEW_PREFS to change the ID name.
  10. In the text textbox, type &Preferences....
  11. Click on the Connect tab.
  12. On this page, type the string Customize the appearance of the view. This prompt will appear in the status bar whenever the Preferences item is selected.
  13. Save your work by choosing Save from the Browser window's File menu.
  14. Close the Browser window, close the ResourceStudio Shell window (and with it, the Property Sheet), and return to the IDDE.
You have now created the desired menu item. However, TMLRead does not yet contain a command handler for ID_VIEW_PREFS. In the next section, you will add one using ClassExpress, in which the bulk of the remaining work will take place.

Two command handlers must be added- one for ID_VIEW_PREFS, the other for the Default button of the Preferences dialog box. Thus, a class must be created that represents the Preferences dialog box in the same way that CAboutDlg represents the About dialog box. The handler for the Default button will be a method for this new class. In the next section, you use ClassExpress to add the CPrefDialog class.

Using ClassExpress to Create a New Dialog Class

Follow these steps to create a class that corresponds to the Preferences dialog box:
  1. Launch ClassExpress by choosing ClassExpress from the IDDE's Tools menu.
  2. Click the Add Class button. The Add Class dialog box opens, as shown in Figure 14-5. ClassExpress detects that a new dialog box has been added to the project, and assumes that you want to create a corresponding class.

    It initializes the selections in the Class Type and Dialog ID drop-down lists to reflect this assumption: Class Type is set to Dialog, and Dialog ID to IDD_PREFDIALOG.

    [Figure 14-5 The Add Class dialog box]

    The focus is in the New Class Name editbox. ClassExpress has suggested the name CTestDialog and has selected the substring Test so that you can change it just by typing. It has also suggested TestDial.cpp as the name of the implementation file.

  3. Type Pref to change the name of the dialog class to CPrefDialog. Notice that ClassExpress accordingly changes the suggested name of the implementation file to PrefDial.cpp.
  4. Click OK in the Add Class dialog box to accept the settings. ClassExpress confirms the operation with a message box.
  5. Click OK to close this message box. This returns you to the ClassExpress window, which displays the Message Maps page, as shown in Figure 14-6.

    [Figure 14-6 ClassExpress displaying the Message Maps page]

Using ClassExpress to Add Methods

In this section, you'll add two methods that respond to user actions. One opens the Preferences dialog box when the Preferences menu item is chosen, and updates the Reader's display if the OK button is clicked in the dialog box. The other method handles the clicking of the Default button in the Preferences dialog box. You will see later why it is unnecessary to add handlers for the OK and Cancel buttons.

First you'll add a method that handles the command generated when Preferences is chosen from the View menu. This method also is responsible for updating the application to reflect any changed preferences. Then, you'll add a method that responds to a click on the Default button of the Preferences dialog box.

The procedure in each case is similar to the one that you used in Lesson 4. The results of your actions also will be similar: ClassExpress adds these methods to class declarations, add entries to Message Maps, and create stub functions for the methods. When you return to the IDDE, you will only need to write the code for these two methods.

Creating a handler for the Preferences command

You will use ClassExpress to bind the ID_VIEW_PREFS command ID to a new method that creates and initializes an object of class CPrefDialog, and then uses this object to display the dialog box. When the user closes the dialog box, this method determines whether the user clicked OK or Cancel. If OK was clicked, application data must be updated, and the view must be redrawn.

This method needs access to data members of CTMLReadView in order to initialize the dialog box and to update those data members if the user clicks OK. Because of these requirements, the method is added to the class CTMLReadView.

  1. Select the class CTMLReadView in the Class combobox on the Message Maps page.
  2. In the Control IDs in the Class listbox, select ID_VIEW_PREFS, the ID of the command issued when the Preferences item in the View menu is chosen. The listbox on the right, Windows Messages, now contains the two items, COMMAND and UPDATE_COMMAND_UI.
  3. Double-click on COMMAND in the Windows Messages listbox. The Method Name dialog box opens, asking you for a name for the method that is called when Preferences is chosen. ClassExpress suggests the name OnViewPrefs for this method.
  4. Click OK in the Method Name dialog to accept the name OnViewPrefs.
ClassExpress adds this method to the declaration of class CTMLReadView in the header file for the class. It also updates the class implementation file by adding an entry to the class's Message Map, and by adding a stub function CTMLReadView::OnViewPrefs.

Creating a handler for the Default button of the Preferences dialog box

You will now add a method to CPrefDialog for handling clicks on the Default button in the Preferences dialog box. This method must update the values displayed in the controls of the dialog box with the same default values used to initialize the CTMLReadView data members nParVSpace, nMargin, and nIndent. Because the default values are public enum constants, this method requires no access privileges to CTMLReadView.

Follow these steps to add this method:

  1. Select the class CPrefDialog in the Class combobox on the Message Maps page.
  2. In the Control IDs in Class listbox, select ID_PREFS_DEFAULT, the ID of the Default button. The listbox on the right, Windows Messages, now contains the two items BN_CLICKED and BN_DOUBLECLICKED.

    Note: These so-called messages are actually notifications that the button sends to its parent, the Preferences dialog box, via WM_COMMAND messages. BN_xxx stands for Button Notification. The BN_xxx identifiers are defined in windows.h.

  3. In the Windows Messages listbox, double-click on BN_CLICKED, the notification sent when the Default button is clicked. The Method Name dialog box opens, suggesting OnClickedPrefsDefault for the method name.
  4. Change this name to OnDefault.
  5. Click OK in the Method Name dialog box to return to the ClassExpress main window.
As it did when you added CTMLReadView::OnViewPrefs, ClassExpress adds a prototype for OnDefault to the declaration of the class CPrefDialog in the class's header file. It also updates the class implementation file by adding an entry to the class's Message Map. It also adds a stub function CPrefDialog::OnDefault.

Once you are back in the IDDE, you must write code to implement these two handlers. To have the handlers to perform their intended tasks, you must first make it possible to transfer data into and out of the controls of the Preferences dialog box. MFC and ClassExpress make it surprisingly easy not only to transfer data to and from a dialog box, but also to validate data that the user has entered into a dialog's controls. Adding these capabilities is addressed in the next section, the last one in which you use ClassExpress.

Adding Dialog Data Exchange and Validation

Windows programs written in C traditionally exchange data with dialog boxes by fetching data from each control in a manner particular to the control type (edit control, radio button, check box, and so on) and particular to the intended type of the data (string, integer, long integer, and so on). Then, the extracted data is usually stored in static storage. Also, there are rarely any general-purpose facilities from Windows API for validating data that the user enters in a dialog box- placing another burden on the programmer.

MFC and ClassExpress add order, simplicity and elegance to this situation. To use the MFC model of dialog box data exchange and validation, you must first add data members to the dialog class. (This replaces the ad hoc collection of static data favored by the traditional approach.) You use ClassExpress to associate data members with controls in the dialog box. MFC then automates the transfer of data between the dialog's controls and the dialog class data members. When adding a data member with ClassExpress, you also specify its type and the validation criteria in the associated control. MFC uses this information to perform its automatic data validation.

In the next step, you'll add data members to the CPrefDialog class using the Data Transfer page of ClassExpress. After you complete this task, there is a review of the changes that ClassExpress has made to the CPrefDialog source files, and an explanation of how MFC accomplishes data exchange and validation.

Throughout this section, you'll work with the CPrefDialog class on the Data Transfer page of ClassExpress. Perform the following steps to set up ClassExpress for this part of the lesson:

  1. In the upper-left listbox, select the second item, Data Transfer. ClassExpress opens the Data Transfer page in the larger pane on the right, as shown in Figure 14-7.

    [Figure 14-7 ClassExpress displaying the Data Transfer page]

  2. Be sure that CPrefDialog is selected in the Class Name combobox at the top of the Data Transfer page.

Adding data members to CPrefDialog

To add data members, to CPref Dialog, carry out the following steps:
  1. Click on the Add Variable button. The Add Member Variable dialog box opens, as shown in Figure 14-8.

    [Figure 14-8 The Add Member Variable dialog box]

  2. Select IDC_PARVSPACE from the Control ID combobox.
  3. Change the Member Variable Name to nParVSpace. (For simplicity, you can name the member variables of CPrefDialog the same as the members of CTMLReadView to which they correspond.)
  4. For the DDX Type option, select Value.

    In fact, the Control Name combobox does not contain symbolic indentifiers for the three edit controls in the Preferences dialog box. Rather, you see only the integer resource ids of these controls. Select 3001, the resource id of the Paragraph Spacing edit control.

  5. In the Variable Type combobox, select int. Two new textboxes, Minimum Value and Maximum Value, appear at the bottom of the dialog box, as shown in Figure 14-9.

    [Figure 14-9 Add Member Variable with Variable Type set to int]

  6. Type 0 in the Minimum Value field.
  7. Type 100 in the Maximum Value field.
  8. Click OK in the Add Member Variable dialog box. The Data Transfer page now reflects this additional data member and its validation criteria in the Control ID and Variables list, as shown in Figure 14-10.

    [Figure 14-10 The Data Transfer page after adding nParVSpace]

  9. Follow the procedure described in steps 3 through 10 of the previous task to add an int variable named nMargin associated with the control IDC_MARGIN. Set its minimum and maximum values to 0 and 50, respectively.

    In fact, the Control Name combobox does not contain symbolic identifiers for the three edit controls in the Preferences dialog box. Rather, you see only the integer resource ids of these controls. Therefore, add a data member corresponding to the control 3004, the resource id of the Margin edit control.

  10. Then, follow steps 3 through 10 to add a final int variable, nIndent, associated with the control IDC_INDENT. Sets its minimum and maximum values to 0 and 120, respectively.

    In fact, the Control Name combobox does not contain symbolic identifiers for the three edit controls in the Preferences dialog box. Rather, you see only the integer resource ids of these controls. Therefore, add a data member corresponding to the control 3005, the resource id of the Indent edit control.

To return to the IDDE, click the Close button. The IDDE's Project window now lists the source file prefdial.cpp.

Seeing the changes in the CPrefDialog source files

As a result of adding data members to CPrefDialog, ClassExpress makes various changes to the header and implementation files of the class CPrefDialog including:

Changes to the class definition

ClassExpress added the following lines to the declaration of CPrefDialog in prefdial.h:
	// Dialog Data
	    //{{ AFX_DATA(CPrefDialog) 
	    enum { IDD = IDD_PREFDIALOG };
	    int nParVSpace; 
	    int nMargin;
	    int nIndent; 
	    //}} AFX_DATA 

	// Implementation
	protected: 
	    virtual void DoDataExchange(CDataExchange* pDX); // DDX/ DDV support 
The comments help ClassExpress find where subsequently added data members should be declared. (The variables that ClassExpress adds are public.) The enum constant IDD is used by the CPrefDialog constructor as an argument to the constructor of its base class, CDialog.

Changes to the constructor

ClassExpress changes the CPrefDialog constructor so that it appears as follows:
	CPrefDialog::CPrefDialog(CWnd* pParent /*= NULL*/)
	   : CDialog(CPrefDialog::IDD, pParent) 
	{
	    //{{ AFX_DATA_INIT(CPrefDialog)
	    nParVSpace = 0; 
	    nMargin = 0;
	    nIndent = 0; 
	    //}} AFX_DATA_INIT
	} 
The AFX_DATA_INIT comments are used by ClassExpress to delimit the location within the constructor where data members participating in data exchange and validation should be initialized. All the data members that you added are set to 0. Therefore, before it displays the Preferences dialog box, the handler CTMLReadView::OnViewPrefs first sets these CPrefDialog data members to the values of the CTMLReadView data members to which they correspond.

Changes to the DoDataExchange function

The protected member function DoDataExchange is the workhorse that transfers data between the added data members and the controls of the Preferences dialog box. It also validates the values entered into the controls when the user clicks OK. (The acronym DDX stands for Dialog Data eXchange; DDV stands for Dialog Data Validation.) ClassExpress also writes the DoDataExchange function, using the information you gave it when you added each variable. The implementation of the function, in PrefDial.cpp, looks like this:
	void CPrefDialog::DoDataExchange(CDataExchange* pDX) 
	{
	    CDialog::DoDataExchange(pDX); 
	    //{{ AFX_DATA_MAP(CPrefDialog)
	    DDX_Text(pDX, IDC_PARVSPACE, nParVSpace); 
	    DDV_MinMaxInt(pDX, nParVSpace, 0, 100);
	    DDX_Text(pDX, IDC_MARGIN, nMargin); 
	    DDV_MinMaxInt(pDX, nMargin, 0, 50);
	    DDX_Text(pDX, IDC_INDENT, nIndent); 
	    DDV_MinMaxInt(pDX, nIndent, 0, 120);
	    //}} AFX_DATA_MAP 
	} 
Again, the AFX_DATA_MAP comments serve only as delimiters used by ClassExpress when adding data members.

The overloaded DDX_xxx and DDV_xxx functions are declared in the MFC include file afxdd_.h. These functions all take a pointer, pDX, to a CDataExchange object. This object contains two public data members that enable the functions.

The CDataExchange data member m_bSaveAndValidate informs the functions of the direction of the transfer. If m_bSaveAndValidate is TRUE, then the transfer is from the controls to the data members; if this data member is FALSE, the transfer is from the data members to the controls. The DDX_xxx functions perform the appropriate transfer in each case. If m_bSaveAndValidate is TRUE, each DDV_xxx validation function checks whether the data meets the validation criteria it implements. If the data fails to meet the criteria, the validation function opens a message box informing the user, and sets the focus to the control containing the invalid value. If m_bSaveAndValidate is FALSE, the validation functions do nothing.

The CDataExchange data member m_pDlgWnd is a pointer to the CWnd whose data is being transferred and validated. The presence of this data member saves DoDataExchange from having to pass the this pointer to every DDX_xxx and DDV_xxx function.

Note: Because DoDataExchange is a CWnd member function and m_pDlgWnd is a CWnd*, DDX and DDV can be used with any window, and not just with those derived from CDialog.

DoDataExchange is called by the UpdateData function whenever data exchange must take place. You never call it directly. In particular, DoDataExchange is called when a window or dialog box is first opened to initialize its controls. It is also called by the CDialog member function OnOK when a user clicks on a button in the dialog box with an ID of IDOK. Thus in the Preferences dialog box, the inherited handler for the OK button already performs data transfer and validation, so you do not need to supply an override. Similarly, the CDialog member function OnCancel simply terminates a dialog box- behavior completely suitable for the Preferences dialog box.

With these concepts in mind, you can clearly see the purpose and effect of the handlers that you supply in the next task.

Writing Code for the New Handlers

Now, the only task left is to provide implementations of the handlers CTMLReadView::OnViewPrefs and CPrefDialog::OnDefault. Both handlers are straightforward.

Implementing CTMLReadView::OnViewPrefs

Carry out these steps to create the handler:
  1. In the Project window, double-click on tmlrdvw.cpp. This opens a Source window in which you can edit the file tmlrdvw.cpp.
  2. Find the group of #include statements toward the top of the file. Add this line after the last #include statement:
    	#include "prefdial.h" 
    
  3. Find the function CTMLReadView::OnViewPrefs. (It is at the bottom of the file.)
  4. Edit the function by entering the following code. (You may omit the lengthy comments.)
    	void CTMLReadView::OnViewPrefs()
    	{   
    	    CPrefDialog dlgPref; 
    
    	    // Initialize dlgPref data members with
    	    // current values from CTMLReadView 
    	    //
    	    dlgPref.nParVSpace = nParVSpace; 
    	    dlgPref.nMargin = nMargin;
    	    dlgPref. nIndent = nIndent; 
    
    	    // Display the dialog modally.
    	    // If user clicks OK, DoDataExchange 
    	    // will be called to validate data in
    	    // the controls. If the controls hold valid 
    	    // values, their contents will be
    	    // transferred to the CPrefDialog data 
    	    // members. In that case, we must transfer
    	    // the values to the corresponding 
    	    // CTMLReadView data members.
    	    // 
    	    if (dlgPref. DoModal() == IDOK)
    	    {   
    		// Transfer the data to our view class
    		// 
    		nParVSpace = dlgPref.nParVSpace;
    		nMargin = dlgPref.nMargin; 
    		nIndent = dlgPref.nIndent; 
    
    		// Make sure that the view is redrawn
    		// to reflect the new preferences 
    		//
    		bWordsWrapped = FALSE; 
    		OnUpdate(NULL, 0L, NULL);
    	    } 
    	}
    
  5. Save your work by choosing Save from the File menu of the Source window.
  6. Close the Source window by clicking on the close box in the upper-left corner of the window (on the caption bar).

Implementing CPrefDialog::OnDefault

This handler is even simpler. To create it, perform these steps:
  1. In the Project window, double click on prefdial.cpp. This opens a Source window in which you can edit the file prefdial.cpp.
  2. Find the group of #include statements, toward the top of the file. Add this statement to the end of the group:
    	#include "viewhdrs.h" 
    
  3. Find the function CPrefDialog::OnDefault. (It is at the bottom of the file.)
  4. Edit the function by entering the following code. (You may omit the lengthy comments.)
    	void CPrefDialog::OnDefault()
    	{   
    	    // Set data members to default values
    	    // 
    	    nParVSpace = CTMLReadView::eDftParVSpace;
    	    nMargin = CTMLReadView::eDftMargin; 
    	    nIndent = CTMLReadView::eDftIndent; 
    
    	    // Transfer these values to the controls. 
    	    // UpdateData calls DoDataExchange to effect 
    	    // the transfer. The argument determines the 
    	    // direction of the transfer: 
    	    // TRUE causes values to move from the 
    	    // controls to the data members; 
    	    // FALSE, used here, transfers the values of 
    	    // the data members to the controls. 
    	    // UpdateData uses its argument to set the 
    	    // m_bSaveAndValidate data member of the 
    	    // CDataExchange object whose address 
    	    // it passes to DoDataExchange. 
    	    // 
    	    UpdateData(FALSE); 
    	}
    
  5. Save your work by choosing Save from the File menu of the Source window.
You have now completed all the tasks necessary for the Preferences dialog box to be fully functional. To conclude this lesson, you will rebuild TMLRead and test the dialog box.

Rebuild and Test TMLRead

To verify that your work has achieved the desired goal, rebuild and run the Reader, making it a point to use the new features. To do this, follow these steps:
  1. Choose Build from the Project menu to incorporate the changes you have made into the executable file tmlread.exe.
  2. Choose Execute Program from the Project menu to run the Reader.
  3. Choose Open from the File menu of TMLRead. Again, load the file sample.tml.
  4. Choose Preferences from the View menu of TMLRead.
  5. Enter 25 into all three edit controls.
  6. Click on the Default button to verify that the CPrefDialog data members are set to default values by CPrefDialog::OnDefault.
  7. Click Cancel. You should see no change in the display of sample.tml.
  8. Again, choose Preferences from the View menu of TMLRead.
  9. Change the values to 150, 40, and 10, respectively.
  10. Click OK. Observe the message box informing you of invalid data.
  11. Click OK to close the message box. The focus returns to the editbox containing 150.
  12. Continue experimenting with the Preferences dialog box, eventually clicking OK when valid data is entered in the controls. After you have confirmed that the dialog box is performing as you want, exit the program by choosing Exit from the Reader's File menu. This returns you to the IDDE.

Summary

In this lesson, you learned: This concludes the tutorial section. These lessons have been an instructive introduction to the capabilities of Digital Mars C++. By this point, you will have acquired the techniques and knowledge you need to apply the features of Digital Mars C++ to your own projects.

15. More about Projects and Workspaces

This chapter continues the discussion of projects and workspaces that began in Chapter 3, "Starting a Project and Defining Workspaces." Here you find a detailed description of all commands and options associated with workspaces and projects. The first part of the chapter discusses the Environment menu and workspace options; the remainder of the chapter covers project files, the Project menu, project options, and the Project window.

Environment Menu Commands

The IDDE's Environment menu (Figure 15-1) contains commands with which you can modify the IDDE work environment.

[Figure 15-1 Environment menu commands

A list of available workspaces is added to the end of the Environment menu. The current workspace is checked. Choosing a name in this list is equivalent to clicking on the workspace tab in the Workspace toolbox.

Workspace
The Workspace submenu (Figure 15-2) contains commands for creating and editing workspaces.

[Figure 15-2 Workspace submenu]

New
Opens the Workspace Name dialog box.

[Figure 15-3 Workspace Name dialog box]

To create a new empty workspace, type a name for the workspace and click OK. The Build and Views toolboxes open automatically.

The New command is disabled if you already have five workspaces.

Clone
Opens the Workspace Name dialog box. To create a copy of the current workspace, type a name for the new workspace and click OK.

The Clone command is disabled if you already have five workspaces.

Delete
Deletes the current workspace from the workspace set. The last remaining workspace cannot be deleted.
Rename
Opens the Workspace Name dialog box. Type a new name for the current workspace and click OK.
Reset
Resets the current workspace to the configuration it had when you started the session or when you last saved it during the current session with Save Workspace Set.
Save Workspace Set
Saves the current workspace configurations. These configurations can be restored with the Reset command.
Environment Settings
This command opens the Environment Settings dialog box with which you specify various environment options. Two pages of options are available: Workspace and Color.

Workspace

This page (Figure 15-4) provides options for controlling workspaces.

[Figure 15-4 Workspace page of the Environment Settings dialog box

Save workspace set on exit

Saves the workspace set when the IDDE is closed.

Open last project on launch

When the IDDE is launched, automatically opens the project that was open when the IDDE was last closed.

Color

This page (Figure 15-5) provides options with which to customize the IDDE windows' colors.

[Figure 15-5 Color page of the Environment Settings dialog box

To change an item's color, first click on the item name. A dashed box appears around the item name. Then click on Change Color. You may then choose a new color from a Windows Color dialog box.

Editing/Browsing Settings
Opens the Editing/Browsing Settings dialog box, with which you can view and change the IDDE's editing and browsing options. For more information, see Chapter 19, "Class Editor Reference," Chapter 20, "Hierarchy Editor Reference," and Chapter 21, "Text Editor Reference."

More about Projects

This section continues the discussion of projects that began in Chapter 3, "Starting a Project and Defining Workspaces."

What a project contains

The project file contains a list of all the files in your project. It also contains information on how these files depend on one another. When the project manager creates a makefile (a file that builds your program), it uses a file's extension to decide what kind of file it is. The files you can put in a project are described here, along with how the IDDE uses them to build a program.

C and C++ files

The IDDE compiles C and C++ source files to produce object files and links the object files to produce the target.

C source files have the .c extension; C++ source files have either the .cpp or the. cxx extension. When compiled, they all generate object (.obj) files.

Header files

You do not need to add header files to a project; they are added automatically by the project system. See the section "Dependency tracking" later in this chapter.

If you do add a header file explicitly, it is flagged automatically for precompilation. See the description of the Header Files page of the Project Settings dialog box in Chapter 16, "More about Project Build Settings."

The header files that are included by C/C++ source files to provide common interface definitions are identified by the file extensions .hpp, .hxx, and .h.

In some situations, a C/C++ source file may be included by another source file. In this case, you probably do not want a separate object file created from that included source file. Do not add the file to the project. When you compile the target, the project system adds the included file but tracks it as an included object that should not be compiled or linked independently.

Assembly files

Your project may contain assembly source and header files. Assembly language source files are identified by the file extension .asm. Assembly language header files are identified by the file extension .inc.

Note: For assembly files to be built as part of a project, MASM must be in a directory specified by the PATH environment variable. For a NetBuild project, MASM must be in a directory specified by the PATH environment variable of every buildserver, and the buildclient.

Object files

Your project can include pre-existing object files- files for which you do not have the source or that were compiled outside the IDDE. Such object files are identified by the file extension .obj. These objects are linked into your executable.

Resource and dialog script files

Your project can include resource script files, dialog script files, and other binary resource files. The IDDE compiles these script files to produce a resource file. After the IDDE links the object files, it binds the resources from the resource files into the executable. The resource file types are:
.rc
Source scripts of resource files that are compiled by the Digital Mars C++ resource compiler
.ico, .cur, .bmp
Binary resources
.res
Compiled binary resources

Libraries

Your project can include libraries. The IDDE links the libraries with the project's object files to produce the executable file. If your program uses a dynamic link library (DLL), don't add the DLL to the project file. Instead, add the DLL's import library (.lib).

Libraries or library interfaces to a DLL that you want to link into your executable are identified by the file extensions .lib.

Linker definition files

Your project can include a linker definition (sometimes called module definition) file. Use a linker definition file to indicate to the linker how to build a library or executable. These files are identified by the file extension .def.

If you have your own .def file, you can include it in the project. The IDDE automatically modifies the .def file to change a linker option if necessary. If you do not specify a .def file, one is generated and maintained automatically for you.

Project files

The IDDE automatically generates and maintains project files. Project files can be nested to form a hierarchical project structure. Project files are identified by the file extension .prj.

Option set

You can include your own option set. Option sets that you create are identified by the file extension .opn.

Batch and makefiles

You can include a batch or makefile. Batch files are identified by a .bat file extension, and makefiles by a .mak file extension.

When you add a batch file or a makefile to a project, the Build Order dialog box (accessible via the Build Order button on the Make page under the Build tab of the Project Settings dialog box) becomes available to specify when to execute your batch files and makefiles.

Project-generated files

The project system generates and maintains files with these extensions:
.prj
The project file that contains information on the base directory of the project, the option set, the Version Control System (VCS) configuration location, and each of the files and its attributes.
.mak
The makefile generated from the project options and files. You don't have to write and maintain a makefile- the project system does it for you.
.def
The linker definition (module definition) file. You can specify your own .def file or let the project system generate and maintain one for you.
.dep
The file that keeps the dependency listing.
.opn
The file in which project options are stored.
.lnk
A resource file that directs the linker to build your target. It is generated and maintained by the project system.

Hierarchical project structure

You can include projects within projects (to any depth) to create a hierarchical project structure. Hierarchical projects have many uses.

You can use hierarchical projects if you need to build more than one target as part of a system. For example, if your system includes an executable and a DLL, you can create a separate project for the DLL and include this new subproject in the master project. The library is built automatically when (and if) necessary. (Note that, since Windows relies on the module name to determine the uniqueness of modules, you need to give your targets different names. For example, do not name the executable generated by a project mymod.exe and name a DLL created by a subproject mymod.dll; an error results.)

In other cases, some files may need different compiler settings. You have two options. You can put those files in a separate subproject, setting compile options for the project as necessary. Or, you can override compile options on a file-by-file basis. To do this, right-click on the file in the Project window, and choose Settings from the pop-up menu. You can then set compile options for that file.

If you have a special preprocessing or translation step in your build process, you can create a subproject (a project within another project) for that make step. To accomplish the preprocessing, use the Make page under the Build tab in the Project Settings dialog box (see Chapter 16, "More about Project Build Settings") to call your own makefile or batch file.

Use hierarchical projects to handle different releases or versions of a project. To build all the variants in one simple step, create a master project that contains only projects. When you build the master, each of the variants is built.

These examples show that the hierarchical project system can be used in a variety of ways to customize the build process. Note that dependency tracking still works for subprojects- they are built as needed, before the master project is built.

Note: When you build a project that has a hierarchical structure, all subprojects are rebuilt with either the Debug or Release setting, whichever is applied to the master project. To ensure that each subproject is linked with the correct libraries (Debug or Release), you need to rebuild each subproject's .lnk file.

Dependency tracking

The project system automatically tracks dependencies among the components of a project. Dependency information is updated with each successive compilation. As you add or remove include files, for example, the corresponding dependencies are updated. You have the option of turning this tracking off.

The IDDE also tracks changes made to build options and determines how much of the project needs to be rebuilt based on those changes. For example, if you change a compiler setting, all the sources are rebuilt. If you change a resource compiler option, only the resource compiler and link steps are executed. If you change a link option or library directory, only the linker is run. By tracking these changes, the project system supports efficient and accurate builds.

In the Windows 3.1 version of the IDDE, the project system can track files in the project with respect to version control. For more information on project and source code control, see Chapter 22, "Using Version Control."

Project menu commands

The IDDE's Project menu (see Figure 15-6) contains commands to create, open, edit, and close projects; to build projects, to run the application; and to set project options. At the end of the menu, the IDDE adds the names of the most recently opened projects so that you can switch between projects as you work.

[Figure 15-6 Project menu commands]

New
Opens the ProjectExpress dialog box, as described in Chapter 3, "Starting a Project and Defining Workspaces."
Open
Opens the Open Project dialog box, as described in Chapter 3, "Starting a Project and Defining Workspaces."
Edit
Opens the Edit Project dialog box, as described in Chapter 3, "Starting a Project and Defining Workspaces."
Close
Closes the current project.
Build
Builds your project. The IDDE examines all files in the project to determine whether they are up-to-date and recompiles only the necessary files.
Stop Build
Stops a build in progress. You can also stop a build by choosing Stop! from the Output window's menu bar.
Rebuild All
Rebuilds all files in your project, regardless of whether they are up-to-date.
Link
Links all object files and libraries. Use Link instead of Build when adding .lib or .obj files to a project or subtracting them from a project. You can also use this command if you know all files are up-to- date. There is no dependency checking with Link, so linking is faster than building. Also, you would use Link rather than Build if you changed source code but you wanted to generate an .exe with existing .obj files.
Execute Program
Executes your application. Command-line arguments may be set with the Arguments command.
Arguments
Opens the Run Arguments dialog box (Figure 15-7).

[Figure 15-7 Run Arguments dialog box

Type the command-line arguments that you want passed to an application when you choose Execute Program.

Settings
Opens the Project Settings dialog box. This dialog box lets you set project options that specify how the IDDE builds a project. The following pages are available by clicking on the tabs at the top of the dialog box: Target, Build, Option Sets, VCS, and Directories.

Target settings

The options on the Target page (Figure 15-8) specify the target and platform for your project.

[Figure 15-8 Target page of the Project Settings dialog box

Operating system

This set of options determines the target system for your project. Depending on the selection of the target system, different Target Type options become available. The target system can be one of the following: All the systems are self-explanatory except DOSX. This option selects the DOSX 32-bit DOS Extender (which comes with Digital Mars C++) as the target operating system.

Target type

This set of options determines what your project will actually be: an executable, a library, a Windows DLL, or a simple console. The target type can be one of the following:
Executable
Builds an executable program (.exe). Dynamic Link Library: Builds a Windows DLL. This option is not available when Operating System is set to DOS or DOSX.
Static library
Builds a static library (.lib) -- that is, a library a program links to at compile time- as opposed to DLL, which links at run-time.
COM
Builds a DOS executable .com file. This option is only available when Operating System is set to DOS.
Console
Builds a Windows console program. In Windows 3.1 (and Win32s) this creates an SDI application in which the standard input and output functions are carried out through the SDI window. In Windows 95 and Windows NT, this creates an executable that runs as a console application, simulating an old-style teletype.

Uses

These options let you select the extension libraries that are linked to the executable.
MFC (Microsoft Foundation Class Library)
Links the libraries needed for an application that uses classes from the MFC. Two methods of linking are available: static library (.lib) or dynamic link library (DLL).
OLE (Object Linking and Embedding)
Links the libraries needed for creating an application that uses OLE.
VBX (Visual BASIC Control)
Links the libraries needed to create a Visual Basic control.
OCX (OLE Control)
Links the libraries for building an OLE control.
ODBC (Open Database Connectivity)
Links the libraries needed to access an ODBC data source.

Project settings

Two options determine whether debugging information is included in the executable.
Debug
The executable contains debugging information and can be debugged by the IDDE debugger.
Release
The executable contains no debugging information. It cannot be debugged.

Allow project to be built

If this option is selected, the application can be built. Deselect this option if a project should not be built (for example, if you don't want a subproject rebuilt when you choose Rebuild All in the parent project).

Parse for browsing

If this option is selected, the project is automatically parsed. Deselect if you don't want the Browser to parse the source code. See Chapter 5, "Defining Classes and Their Hierarchies," for more information.

Build settings

The options on the Build page control how your project is compiled and linked. See Chapter 15, "More about Projects and Workspaces."

Option sets

The Option Sets page (Figure 15-9) lets you save and retrieve project options. This feature makes it easy to define options once for a particular kind of target and apply them later to another project.

[Figure 15-9 Option Sets page of the Project Settings dialog box

When you exit the IDDE or close a project, current options are saved in the project option file (. opn). This file has the same name as the project. For example, if the project name is test. prj, the option set associated with that project is named test. opn.

The list of option sets includes sets you define and several predefined option sets. Click on an option set name to select the option set; double-click on an option set name or click on Load to load the option set.

The predefined option sets are useful starting points for defining your own custom options. When you load one of these option sets, save any changes to another option set so the defaults are intact for later use. These option sets are named according to the target type and whether debugging information is placed in the executable.

The four buttons on the dialog box have the following functions:

Load
Loads the selected option set.
Save
Saves the current option set.
Create
Creates a new option set. You are prompted for the new set's name.
Browse
Opens the Option Set Name dialog box, from which you can select an option set file to load.

VCS options

The options on the VCS page control the version control system. These options are only available in the 16-bit IDDE. For information about version control see Chapter 22, "Using Version Control."

Directories

The options on the Directories page (Figure 15-10) specify various directories used by the compiler, linker, and browser.

[Figure 15-10 Directories page of the Project Settings dialog box

Include directories

Specifies directories to be searched for included files. You may specify multiple directories by separating each pathname with a semicolon. These directories are searched after those specified by the INCLUDE environment variable.

Library directories

Specifies which directories to search for libraries. You may specify multiple directories by separating each pathname with a semicolon. These directories are searched after those specified by the LIB environment variable.

Compiler output directory

Specifies the directory in which object files (.obj) are placed.

Target output directory

Specifies the directory in which the linked target is placed.

Browser exclude directories

Specifies the directories that are excluded from parsing by the browser. Use this option, for example, to exclude the MFC header file directory, and thus prevent the display of MFC classes in the Class and Hierarchy editors.

Source search path

Specifies which directories to search for source files while debugging.

The Project Window

This section describes all the menu commands available from the Project window.

Parse menu commands

The Parse menu (Figure 15-11) contains commands to control the parsing of source files. Parse information (information about the project's C++ classes and class members) is stored in a global pool that is accessible to and used by the Class and Hierarchy Editors.

[Figure 15-11 Parse menu commands

Update All
Parses all unparsed files in the project.
Parse All
Parses all files in the project.
Parse File
Parses the selected file, adding information about classes and members in the file to the global parse information.
Unparse File
Unparses the selected file. It removes classes and members in the file from the global parse information.
Stop Parse
This command cancels a parse operation in progress. You can also stop a parse by choosing Stop! from the Output window's menu bar.

View menu commands

In debugging mode, commands in the View menu update other IDDE windows to show information pertaining to the selected file. For more information on this menu refer to Chapter 24, "Commands Available in Debugging Mode."

Trace menu commands

The Trace menu controls whether the debugger can step into, set breakpoints in, or watch data in a particular source file in debugging mode. See Chapter 24, "Commands Available in Debugging Mode," for more information.

VCS

The VCS menu controls the Version Control System operation. Version control options are only available in the 16-bit IDDE. The VCS menu commands and their functions are described in Chapter 22, "Using Version Control."

Project window left pane pop-up menu commands

This menu (Figure 15-12) contains commands that operate on the current project.

[Figure 15-12 Left pane pop-up menu commands

New Subproject
Opens the New Sub-Project dialog box, in which you select a project to be a subproject of the currently selected project.
Link
Links the project. This is the same as choosing Link from the IDDE's Project menu.
Build
Builds the project. This is the same as choosing Build from the IDDE's Project menu.
Rebuild All
Rebuilds the entire project. This is the same as choosing Rebuild All from the IDDE's Project menu.
Parse
Parses all files. This is the same as choosing Parse All from the Parse menu.
Edit Project
Opens the Edit Project dialog box, as described in Chapter 3, "Starting a Project and Defining Workspaces." This is the same as choosing Edit from the IDDE's Project menu.
Settings
Opens the Project Settings dialog box. This is the same as choosing Settings from the IDDE's Project menu.

Project window right pane pop-up menu commands

This menu (Figure 15-13) contains commands that operate on the selected file.

[Figure 15-13 Right pane pop-up menu commands

Compile
Compiles the selected file.
Parse
Parses the selected file. This is the same as choosing Parse File from the Parse menu.
Other
Opens the Other submenu, which contains the Preprocess, Disassemble, and Precompile commands.
Preprocess
Preprocesses the selected file.
Diassemble
Disassembles the selected file.
Precompile
Precompiles the selected file.
Get
Is the same as choosing Get from the VCS menu.
Put
Is the same as choosing Put from the VCS menu.
Remove
Removes the selected file from the project. You can also remove a selected file from the project by pressing Delete.
Attributes
Sets read/write attributes for the selected file. They are mutually exclusive, so only one can be selected. A checkmark is displayed next to the selected item.
Read Only
Sets the attribute to read only.
Read/Write
Sets the attribute to read/ write.
Don't Show
Filters the display of the project's files.
Modules
Does not list modules added by the debugger.
Parsed
Does not list files added by the parser.
Dependencies
Does not list files included through dependency relationships.
Settings
Lets you set certain compiler options for an individual source file, overriding those specified for the project as a whole. Choosing this command opens the Project Settings dialog box with only the Build tab available (see Chapter 16, "More about Project Build Settings"). Only the compiler-related subpages (Compiler, Code Generation, Header Files, Code Optimizations, Output, Warning, and Debug Information) are available. The Inherit from Project button resets this source file's individual options to those of the project.

"..." pop-up menu commands

This menu (Figure 15-14) is opened by clicking on the "..." box above the vertical scroll bar in the right pane of the Project window.

[Figure 15-14 "..." pop-up menu commands

Use this menu to set up the display of project file information in the right pane. Information that can be displayed includes:

Name
Displays the filename.
Ext
Displays the file extension.
Path
Displays the file path.
Date
Displays the modification date.
Time
Displays the modification time.
Parsed
Displays whether or not the file has been parsed.
EXE/DLL
Displays to which EXE or DLL the module belongs (in debugging mode).
Virtual
Displays whether the module is virtual (in debugging mode).
For more information about the EXE/DLL and Virtual columns, see "The Project Window," in Chapter 24, "Commands Available in Debugging Mode."

Columns of information are removed from the display by dragging the column heading out of the column heading area. (The item then becomes available on the "..." pop-up menu.) The order of the columns can be changed by dragging the column headings to a new position.

Project window mouse functions

Use the mouse to open projects, select project files, open source windows, drag project files to other windows, open pop-up menus, and change the relative sizes of the right and left panes.

To resize the panes, first position the cursor on the dividing line between panes. The cursor changes to a two-headed arrow. Then click the left mouse button and drag the separator to the desired location.

The right mouse button opens the pop-up menus (see the sections "Project window left pane pop-up menu commands" and "Project window right pane pop-up menu commands" earlier in this chapter).

Click on a project or subproject in the left pane to open that project. Double-click on the current project in the left pane to toggle (expand or collapse) the display of its subprojects.

Click on a project file in the right pane to select it. Double-click on a file in the right pane, or drag it to an empty part of the workspace, to open the Source window to view and edit the file. (Double-clicking on a subproject in the right pane opens that subproject.)

You can drag files from the right pane to Source windows, Function windows, Data/ Object windows, and Assembly windows.

Finally, to eliminate a column of information from the right pane, click on the title at the top of the column and drag it outside the column heading area. Columns of information are restored from the "..." pop-up menu, to the right of the column titles. To rearrange columns of information, drag the title at the top of the column to a new position. You can make columns wider or narrower by dragging the column title's right edge to the right or left. Clicking on a column title re-sorts the list of project files according to that column.

16. More about Project Build Settings

This chapter details the options for controlling how a project is built continuing from Chapter 15, More about Projects and Workspaces. It lists and explains the options on the Build page of the Project Settings dialog box. Access these options by selecting Settings from the Project menu, then clicking on the Build tab.

The Build page of the Project Settings dialog box is composed of 18 subpages. The subpages are displayed in a listbox on the left of the window. To access a particular subpage, click on its name. The options displayed on the right change with each subpage. Subpages are organized hierarchically, as shown in the listbox.

This chapter covers all the subpages on the Build page of the Project Options dialog box. The first section introduces the build settings and the Project Settings dialog box, and the later sections describe the subpages in the order in which they are listed on the Build page.

For more detailed information on how each of these options affects the compilation of code, refer to the Compiler and Tools Guide. Appendix B, IDDE Settings and Command-Line Options, details how each of these options map to the corresponding DMC, Optlink, Make, or Librarian command line options.

Introducing Build Settings

Choose the Settings command from the IDDE's Project menu to open the Project Settings multipage dialog box. Using the tabs at the top of the dialog box, select different pages, each of which presents a set of options.

Click on the Build tab in the dialog box to open the Build page. The Build page is composed of subpages of options. Select a subpage by clicking on its name in the listbox on the left of the Build page. The following subpages are available:


Compiler

The Compiler subpage (Figure 16-1) contains a variety of parameters controlling compilation.

Figure 16-1 Compiler subpage

[Figure 16-1 Compiler subpage]

Enforce ANSI compatibility

Establishes the necessary parameters so the compiler accepts only C/C++ code that conforms to ANSI standards. Refer to the Compiler and Tools Guide for information on the restrictions that take effect.

Treat source as C++

With this option selected, the compiler treats C source files as C++ files. The option is useful for: This option also works on C++ header files with the .h extension.

Relax type checking

Causes the compiler to use relaxed (non-ANSI) type checking. The following data types are then treated as equivalent: In addition, for 16-bit compilations: And for 32-bit compilations: The option is useful for quickly porting code from compilers that do not obey the full set of ANSI type-checking rules.

Suppress predefined macros

Suppresses the definition of the non-ANSI predefined macros.

Exception handling

Enables implementation of exception handling.

Run-time type information

Enables implementation of run-time type information.

Enable new[], delete[] overloading

Enables overloading of operator new[] and operator delete[]. It also sets the predefined macro _ENABLE_ARRAYNEW to 1.

Compiling with Enforce ANSI compatibility automatically enables this option.

char behavior

This option controls the way the compiler treats a char type. By default, the compiler treats char types as signed. Set this option to unsigned to quickly port code that depends on unsigned char types. Note that the behavior of the run-time library routines is not affected by this option unless they are also recompiled.
signed:
Makes char types behave as signed char types.
unsigned:
Makes char types behave as unsigned char types.
char == unsigned char:
Changes the type of char to be unsigned.

Prototyping

This option specifies how the compiler handles function prototypes. New code should always be fully prototyped, due to the requirements of type-safe linkage and the support for alternative linkage conventions.

There are three prototyping possibilities: Standard, Autoprototype, and Strict.

Standard:
Turns off autoprototyping and strict prototyping.
Autoprototype:
Enables the compiler to generate a prototype according to the way the function is used, even if one is not specified for a function. Subsequent uses are checked against the generated prototype. This is especially useful when compiling old C code that is not completely prototyped.
Strict:
Requires that all functions be declared (prototyped) before being used. This declaration provides the compiler with the function name, return type, and storage class of a function, as well as the number and type of arguments that may be passed to it. Once the compiler encounters a function prototype, it can check each function call in the source file against that prototype and flag an error for the calls that do not match it.

International characters

This option specifies how the compiler interprets 2-byte Asian language character codes within character constants and strings. That is, if a character code represents the first byte of a 2-byte sequence, the second byte is not checked to see whether it is a backslash or a closed quote. The second byte cannot be a NULL (0), a carriage return (0x0D), or an end-of-file (0x1A).
None:
Allows no 2-byte sequences.
Japanese:
Signals the 2-byte sequence with a value in the range 0x81 ... 0x9F and 0xE0 ... 0xFC
Taiwanese/Chinese:
Signals the 2-byte sequence with a value in the range 0x81 ... 0xFC
Korean:
Signals the 2-byte sequence with a value in the range 0x81 ... 0xFD

Other options

The options below direct the compiler to define a macro, include a header file, or instantiate a template.

Defines

Specify macro definitions on the compiler command line. Separate multiple Defines with a semicolon (;).

Include filename

Directs the compiler to include a header file for all modules in the project.

Instantiate template

Creates an instance of a template in the program.

Code Generation

The Code Generation subpage, shown in Figure 16-2, contains parameters that control how the compiler generates code.

[Figure 16-2 Code Generation subpage

Pointer validation

Makes the resulting program validate each pointer as it is dereferenced; if the pointer is invalid, a run-time error occurs. This slows and slightly increases the size of the resulting code.

Generate stack frame

Generates a stack frame for each function. The stack frame is generally for the use of the debugger.

Check stack overflow

Inserts stack overflow checking at the beginning of each function. The resulting program aborts with an error message if it detects a stack overflow.

Fast floating point

Directs the compiler to produce the fastest possible floating-point code. No compatibility checking is performed.

Generate inline 8087 code

Causes the compiler to generate inline 80x87 instructions. It significantly speeds up floating-point code, reduces its size, and improves its accuracy.

Generate virtual function tables in far data

Affects Compact and Large memory models only. It causes the virtual function tables to be placed in far data segments rather than in the code segment.

Use Pascal calling convention

Makes Pascal, instead of cdecl, the default linkage for all functions and global data. Because all C library routines have cdecl linkage, they must be prototyped as such before being called. Therefore, include the appropriate header files. The main() function must also be declared cdecl for the linker to find it.

Using Pascal as the default linkage type results in a roughly 3% code size reduction and a corresponding speed up in generated code.

Use Stdcall calling convention

Makes stdcall the default linkage for all functions and global data, instead of cdecl.

Note: Under Windows 95 and Windows NT, Digital Mars's name mangling scheme now appends the string "@nn" to the names of all stdcall functions (where nn is the number of bytes in parameters to the function). Previous versions of Digital Mars C++ did not append this string to mangled names.

Enable function-level link

Directs the compiler to encapsulate functions in initialized common blocks (COMDAT records). This allows the linker to perform function-level linking, which results in a smaller executable.

No default library

Prevents the compiler from embedding the default library record in the object file. This option can result in a significant decrease in program size when generating a large library.

Set data threshold

Places large arrays in far data segments. The threshold size is set in the adjacent textbox.

Code segment

These options govern the ways in which code segments are handled.

Generate new segment for each function

Causes the compiler to start a new code segment each time it encounters a global far function. The name of the segment is the name of the function with _TEXT appended.

Override default code segment name

Overrides the default code segment name. Type the new name in the Name textbox.

Put switch tables in code segment

Places switch tables in the code segment rather than in the data segment. It is useful when data segment space is critical. Do not use this option when the code segment in a Small or Compact model program is close to overflowing.

Put expression strings in code segment

Puts expression string literals into the code segment rather than wasting space in a group.

Struct alignment

Sets the boundaries for structure alignment. The default is to align members within a structure on word boundaries for 16-bit programs. This maximizes speed on computers with a 16-bit bus (such as a PC-AT). The default in 32-bit DOS programs is to align on double-word boundaries to maximize performance.
Byte:
Aligns structures on byte boundaries.
Word:
Aligns structures on word boundaries.
Double Word:
Aligns structures on double-word boundaries. This is the default for 32-bit DOS applications.
Quad Word:
Aligns structures on boundaries that are multiples of four words. This is the default for Win32 applications.

Target CPU

Generates code tailored for the instruction set of a specific CPU.
88:
Generates 16-bit code using the 8088 instruction set.
286:
Generates 16-bit code using the 80286 instruction set. Programs compiled with this option will not run on an 8088 or 8086 processor.
386:
Generates code optimized for machines with an 80386 CPU. Programs compiled with this option require an 80386, 80486, or Pentium processor.
486:
Generates code optimized for machines with an 80486 CPU. Programs compiled with this option require a 32-bit DOS extender or 32-bit operating system, and an 80386, 80486, or Pentium CPU.
Pentium:
Generates code for the Pentium instruction set.

Header Files

The Header Files subpage (Figure 16-3) specifies compiler header file options.

[Figure 16-3 Header Files subpage

Precompile options

If using a large header file or numerous small headers, the compiler spends considerable time compiling the same source code over and over again. To reduce compile time, use precompiled header files; the compiler can load a precompiled header faster than it can a text header file. It is especially useful to precompile large header files that seldom change, such as windows.h.

No headers

Disables generation and use of precompiled headers.

All headers

In most cases, using precompiled headers is convenient and fast. The All Headers option automatically precompiles all header files defined in the project source files into the file scph. sym. The file scph. sym is always in the current directory or in the directory specified as the compiler output directory.

Setting the All Headers option causes the compiler to generate the file scph.sym when it does not exist. If the scph.sym file does exist, the compiler assumes it is a precompiled header. The compiler will then test the header file to see whether all the headers it contains are older than the header file itself. If any are newer, or if the compiler flags have changed, a new scph.sym file is created; otherwise, the old file is loaded as a precompiled header. Setting the All Headers option also causes all files being compiled to use scph.sym as their precompiled header.

The compiler writes out the precompiled header when the first line in the top-level source file is encountered, and when that line is not a comment or an #include statement. To avoid problems with precompiled headers:

To maximize compile speed, set the directory to a RAM disk.

There are two circumstances in which using precompiled headers is not recommended:

Specific header

Selects a header file to precompile individually. Type the header file name into the textbox.

Use precompiled headers from directory

Tells the compiler to use precompiled headers from a specific directory. In the textbox, type the name of the directory in which the precompiled headers reside. If this directory is empty, no additional directories, other than the current or path directories, are searched.

Include headers once

Tells the compiler to include each header file only once, even if it is named in more than one source file. Otherwise, header files are included whenever they are named in a source file. This option can be used with or without precompiled headers.

Memory Models

The Memory Models subpage (Figure 16-4) specifies the memory model to be used.

[Figure 16-4 Memory Models subpage

Memory model

Controls the memory model the compiler uses by specifying its size:
Tiny:
Tells the compiler to create a .com file active only for DOS compilations.
Small:
Generates code with near pointers for the code segment and the data segment.
Medium:
Generates code with far pointers for the code segment and near pointers for the data segment.
Compact:
Generates code with near pointers for the code segment and far pointers for the data segment.
Large:
Generates code with far pointers for both the code and data segments.
Flat:
Generates code for a Win32 compilation; that is active only for Win32s and DOSX compilations.

Data segment

These options control the way the compiler treats the data segment register.

Assume SS==DS

Causes the compiler to generate code that assumes SS equals DS.

Always reload DS

Causes the compiler to generate code that reloads DS at the beginning of each function call.

Code Optimizations

Options on the Code Optimizations subpage (Figure 16-5) control how the compiler optimizes code.

[Figure 16-5 Code Optimizations subpage

Optimization for

These radio buttons control the type of optimization. Optimize for speed or space, select a custom set of optimizations, or disable optimization.
Speed:
Optimizes code for speed at the expense of program size. The code uses all optimizations.
Space:
Optimizes code for space at the expense of execution speed. The code uses all optimizations.
Custom:
Allows selection of optimizations using the Optimization check boxes.
None:
Turns off all Optimization check boxes. No optimization is performed.

Optimizations

The Optimization check boxes control the individual optimizations. These options relate only to the Custom radio button.

For more information on how Digital Mars C++ optimizes code, see the Compiler and Tools Guide.

C++ inlining

Controls inline function expansion in C++. When debugging C++ files, the presence of inline code can present considerable problems to most symbolic debuggers. This option suppresses the production of inline code.

Windows Prolog/Epilog

The Windows Prolog/Epilog subpage (Figure 16-6) specifies the type of Windows prolog and epilog code that the compiler attaches to each far function in a compilation.

[Figure 16-6 Windows Prolog/Epilog subpage

The first group of radio buttons selects from predefined sets of prolog/epilog options.

Set EXE defaults

Sets options to generate prologs and epilogs for a protected-mode Windows application, with callback functions all marked as _export.

Set DLL defaults

Sets options to generate prologs and epilogs for a protected-mode Windows DLL, with callback and exported functions all marked as _export.

Real mode full prolog/epilog

Sets options to generate prologs and epilogs for a real or protected-mode Windows application or DLL.

Real mode reduced

Sets options to generate prologs and epilogs for a real or protected-mode Windows application or DLL with exported and callback functions (marked with _export).

Real mode smart callbacks

Sets options to generate prologs and epilogs for a real or protected-mode Windows application with smart callbacks. In smart callbacks, the compiler compiles far functions with a smart prolog and epilog that loads the data segment from the stack segment. Use smart callbacks only with applications in which the data segment is the same as the stack segment (DS== SS). Do not use it with DLL files.

Custom

Specifies a nonstandard set of prolog/epilog options.

The remaining options on the Windows prolog/epilog subpage are discussed in the Compiler and Tools Guide.


Output

The Output subpage (Figure 16-7) controls the output generated by the compiler.

[Figure 16-7 Output subpage

Source listing files

With this option on, the compiler creates a source listing file; its name is that of the source file with the extension .lst. The compiler inserts error messages and line numbers in the listing file.

Verbose

Displays source and header file names, classes, function prototypes, and time of execution during compilation.

Macro expansions

Tells the compiler to create macro expansions in error listings.

Assembly listing (.cod)

Causes the compiler to generate a .cod file containing an assembly language representation of the program.

Warnings

The options on this subpage, shown in Figure 16-8, control how the compiler produces warnings and enables the compiler to generate only specific warnings.

[Figure 16-8 Warnings subpage]

Warnings

Determines the warning messages that are produced:
All:
All warnings are produced. Turns on all warnings in the Selected Warnings group.
Selected:
Only warnings that have been checked in the Selected Warnings area are produced.
None:
No warnings are produced. Turns off all warnings in the Selected Warnings group.

Treat warnings as errors

Causes the compiler to promote warnings to errors. Setting this option allows using the error window to find warnings in the source file.

Turn off error maximum

Makes the compiler continue rather than stop when its error limit is reached. The compiler processes the entire source file and displays all errors it has detected.

Selected warnings

Determines the warning messages that are produced. For more information on the specific warnings, refer to the Compiler and Tools Guide.

Debug Information

The Debug Information subpage (Figure 16-9) controls the information the compiler places into the code for debugging. These options specify the level of debugging, debug information, and other conditions.

[Figure 16-9 Debug Information subpage

Debug information

These radio buttons select from predefined sets of debug information options.
Full:
Turns on all debug information. Use this set when the application uses a class library or DLL.
Reduced:
Turns on the most frequently needed debug information. Use this set for most other programs.
Custom:
Select the debug information to be included.
None:
Turns off all debug information.

Trace prolog/epilog

Adds the user-defined function calls __trace_pro_f and __trace_epi_f to the prolog and epilog, respectively, for each function. The prolog function is called after the stack frame is set up; the epilog function is called just before the stack frame is destroyed.

Line numbers

Places line numbers corresponding to the source into the code. Line number information significantly increases the size of the object file.

Symbolic debug information

Includes symbol information for all public symbols. Symbols significantly increase the size of the object file.

Three additional options become available when Symbolic Debug Information is checked:

Unreferenced types:
Generates symbols for unreferenced types (for example, typedefs).
All referenced classes:
Forces symbols for all classes that are referenced in DLL files and class libraries to be generated.
Dynamic C++ types:
Adds dynamic C++ class type information to classes with virtual functions. To force the production of typing information for a class with no virtual functions, add a dummy function such as virtual void dummy(){} to the class definition.

Make static functions global

Makes all static functions global. The linker then can enter the names of these functions into the map file and place global debugging information in the executable.

Linker

The Linker subpage (Figure 16-10) governs the overall behavior of the linker.

[Figure 16-10 Linker subpage

Debug information

Places debugging information in the executable file. This is the normal option for linking an executable for debugging using the IDDE.

No default library

Causes the linker to ignore libraries specified in object files.

Case sensitive

Causes the linker to be case sensitive.

Far call translation

Causes the linker to convert intrasegment far calls to near calls.

Reorder segments

Places like segments in contiguous locations.

Export by ordinal

For 32-bit output, causes the linker to export symbols by ordinal. For 16-bit output, when this option is on, the name text for every exported symbol is moved from the resident name table to the nonresident name table.

Don't export names

Eliminates storage of name text for symbols exported by ordinal.

Export, case sensitive

Makes the linker treat the import and export symbols as case sensitive.

Export, uppercase

Forces the linker to convert import and export symbols to uppercase.

DOSSEG ordering

Causes the linker to perform the special segment ordering used by Microsoft high-level languages.

No null DOSSEG

Causes the linker not to offset the first segment by 10.

Warn if dups

Causes the linker to warn if there are duplicate symbols in the code.

Delete EXE/DLL on error

Deletes target executable if a link error occurs.

Create ImpDef

Forces the linker to generate a .din file, which combines export information from source, definition file, and options.

Fix DS

Turning this option on has the same effect as putting a FIXDS directive in the .def file.

Keep segments in .def order

Causes the linker to keep segments in the order in which they appear in the .def file (Windows only).

Requires Windows 3.0

Causes the linker to tag the executable as requiring Windows 3.0 or later to run.

Requires Windows 3.1

Causes the linker to tag the executable as requiring Windows 3.1 or later to run.

Generate import library

Directs the linker to build an import library (.lib) describing the exported symbols available to be imported from a DLL.

Import lib page size

Sets the page size for the Generate Import Library option.

Alignment

In conventional MS-DOS executables, causes the header to be rounded up to the specified size. In segmented .exe files, this option governs the page size.

Base

Sets the base address of the executable.

Entry point

Specifies the program entry point for Win32 applications.

Packing & Map File

The Packing & Map File subpage (Figure 16-11) controls the linker's output of cross-reference and map files.

[Figure 16-11 Packing & Map File subpage

Packing

This group of options controls target packing.

Win pack

Packs Windows programs.

EXE pack

Compresses the executable file.

Smart linking

Enables smart linking of object files containing COMDAT records; only referenced COMDAT records are retained.

Pack code

Causes the linker to combine code segments. The size textbox specifies the maximum code segment size.

Pack data

Causes the linker to combine data segments. The size textbox specifies the maximum data segment size.

Map file

These options generate a file containing a list of segments, in the order of their appearance in the module. This group of options controls map file generation.
No map:
No map file generated.
Segment map:
Generates a list of segments, in the order of their appearance in the module.
Detailed segment map:
Includes more detail about segment type, the modules that were added, the number of bytes per segment, and where each module begins.

Map file options

These options control the contents of the map file.

Cross reference

Causes the linker to generate a cross-reference list in the map file.

Line numbers

Controls whether line-number information is contained in the map file.

Group information

Enables output of group information.

Definitions

The Definitions subpage (Figure 16-12) contains the parameters necessary to create the .def file for an application.

[Figure 16-12 Definitions subpage

Name

Defines the name of the application, which is used by Windows to identify the application. A name is required for all Windows applications.

Description

Contains a description of the application. This optional string is placed in a Windows executable. It can be used for version control or to otherwise help identify the application.

Heap size

Specifies the size of the application's local heap. The default is 4096. If the application frequently uses the local heap, specify a larger heap size.

For Windows 3.1, heap size is a single text field. For Win32s, the field has two parts: Reserve and Commit, where Reserve is optional. Reserve tells Win32s how much heap space to try to get for this application. Commit specifies the amount of heap space the application actually needs. The two fields are separated by a comma (,). For example, 100000, 4096 would specify 100000 for Reserve and 4096 for Commit.

Stack size

Defines the size, in bytes, of the executable's stack. The default is 4096 bytes. The stack is used for storing function arguments. It's common to need to increase the stack size, especially for applications containing heavily recursive functions.

For Windows 3.1, stack size is a single text field. For Win32s, the field has two parts: Reserve and Commit, where Reserve is optional. Reserve tells Win32s how much stack space to try to get for this application. Commit specifies the stack size the application actually needs.

Stub

Specifies an optional file that defines the executable stub to be placed at the beginning of the executable. When a user tries to run the application from DOS, the stub is executed instead. Many applications use the winstub.exe file supplied with the Windows SDK. Any DOS or DOSX executable can be used.

Version

Contains optional version information that becomes part of the executable file.

Initialize once

The DLL's initialization routine is called only when the module is initially loaded into memory.

Private lib

Creates a private DLL that is called.

Initialize process

The DLL's entry point is called when a process attaches.

Terminate process

The DLL's entry point is called when a process terminates.

Initialize thread

The DLL's entry point is called when a thread attaches.

Terminate thread

The DLL's entry point is called when a thread terminates.

Segments

This subpage, shown in Figure 16-13, provides segment information for the .def file.

[Figure 16-13 Segments subpage

Segment Type

This option toggles between two option sets: one for code segment, and one for data segment.
Code Segment:
Shows options for the code segment.
Data Segment:
Shows options for the data segment.

Attributes

These options define the attributes for the application.

Conforming

Turns on the conforming bits for the segment. This attribute can be set for code segments only.

Discardable

Lets the system flush the segment from memory. This attribute can be set for code segments only.

Shared

Lets multiple applications use this segment simultaneously (DLLs only). This attribute can be set for both code and data segments.

Preload

Loads the segment when the executable file or library is loaded. This attribute can be set for both code and data segments.

I/O privilege

Turns on the I/O privilege bit for the segment. This attribute can be set for code segments only.

Moveable

Lets the segment be moved when memory is compacted. This attribute can be set for both code and data segments.

Access Rights

Select access privileges for a segment.

Execute Read

Lets an executable read from or execute a segment, but not write to a segment.

Execute Only

Lets an executable execute, but not read or write, the segment. This attribute can be set for code segments only.

Read Write

Lets an executable read from a segment, or write to a segment, but not execute a segment.

Read Only

Lets an executable read from a segment, but not write to or execute the segment. This attribute can be set for data segments only.

Instance

Select the type of data segment generated.

Multiple data segments

Forces the generation of multiple data segments.

Single data segment

Forces the generation of a single data segment.

Mode

Select the type of executable file generated.

Protected mode

Causes the application to run in protected mode.

Real mode

Causes the application to run in real mode.

Imports/Exports

The Imports/Exports subpage (Figure 16-14) defines the names of routines in DLLs that the executable can use. It also defines the names of routines that the target (which must be a library) exports to other programs. The IMPORTS and EXPORTS statements are placed in the .def file.

[Figure 16-14 Imports/Exports subpage

Imports

This section defines the names of routines in DLLs that the application can use.

Internal name

Contains the name by which the imported routine is called internally. If omitted, the internal name is the same as the external name.

External file

Contains the name of the DLL from which the routine is imported.

External name

Contains the name of the DLL routine to be imported.

Ordinal

Specifies the ordinal number in the DLL of the routine to be imported. Specify the ordinal or the external name, but not both.

Add, Replace, Remove

Clicking on the Add button adds the routine to the list of imported routines. Clicking on the Replace button uses the routine to replace the currently selected routine in the list. Clicking on the Remove button removes the currently selected routine from the list.

Exports

This section defines the names of routines that can be exported from the DLL.

External name

Contains the name by which the DLL routine will be known to other applications.

Internal name

Contains the name of the DLL routine to be exported.

Ordinal

Specifies the ordinal number by which the DLL can be referenced in other applications. This is optional unless No name is set.

Parameters

Specifies the total number of words occupied by the function's parameters. This option applies only to protected-mode functions with I/O privilege.

No data

Specifies that this function does not reference any data. This option applies only to real-mode Windows functions with I/O privilege.

No name

Specifies that the function can only be referenced by ordinal number.

Memory resident name

Makes the function name memory resident, even though an ordinal number is specified.

Private

Causes PRIVATE to be added to the names in the module definition file; this directs the IMPLIB utility to ignore the EXPORTS statements.

Add, Replace, Remove

Clicking on the Add button adds the routine to the list of exported routines. Clicking on the Replace button uses the routine to replace the currently selected routine in the list. Clicking on the Remove button removes the currently selected routine from the list.

Resource Compiler

The Resource Compiler subpage (Figure 16-15) contains options to control the resource compiler.

[Figure 16-15 Resource Compiler subpage

Error maximum

Makes the resource compiler stop when its error limit is reached. If this option is off, the resource compiler processes the entire source file and displays all errors that have been detected.

Use predefined macros

Directs the resource compiler to use all predefined macros for the resource file.

Generate warnings

Shows warning messages.

Verbose

Shows greater detail when compiling resources.

32-bit resources

Specifies creation of 32-bit resource files.

Define macros

Specifies macros that should be defined for the resource compilers.

Source file listing

Specifies the name of the output listing file to create from the .res script.

Default hex language

Specifies the default hexadecimal language for 32-bit resources.

Code page

Specifies the code page used to convert strings in 32-bit resources to Unicode (currently unused).

International characters

This option specifies how the resource compiler interprets 2-byte Asian language character codes within character constants and strings. That is, if a character code represents the first byte of a 2-byte sequence, the second byte is not checked to see whether it is a backslash or a closed quote. The second byte cannot be a NULL (0), a carriage return (0x0D), or an end-of-file (0x1A).
None:
Allows no 2-byte sequences.
Japanese:
Signals the 2-byte sequence with a value in the range 0x81 ... 0x9F and 0xE0 ... 0xFC.
Taiwanese/Chinese:
Signals the 2-byte sequence with a value in the range 0x81 ... 0xFC.
Korean:
Signals the 2-byte sequence with a value in the range 0x81 ... 0xFD.

Make

The Make subpage (Figure 16-16) sets Make options for the IDDE built-in Make.

[Figure 16-16 Make subpage

The radio buttons at the top of the dialog box control the Make program that will be run when the IDDE builds the project.

Use IDDE make:
Use the built-in IDDE make tool.
Use external make file:
Use an external Make program.

IDDE make options

This group of options governs the IDDE Make.

Build order

Opens the Build Order dialog box (see Figure 16-17).

Link order

Opens the Link Order dialog box (see Figure 16-18).

Track dependencies

Specifies whether or not to track dependencies (enabled by default). More time is required to track dependencies for large projects with many include files. The most effective way to use this option to establish the correct dependencies is to turn it on when first building a project. Then turn it off, except when changing the dependency structure (by changing #include statements, for example).

If dependencies are tracked, the dependent files are shown in the Project window.

Track system includes

Specifies whether to track dependencies in system include files (disabled by default).

On error continue unrelated

Causes the IDDE Make to continue to build modules that are not dependent on the module in which the error occurred.

Ignore errors in build

Directs the IDDE Make to ignore errors and continue to build the target.

Multitasking

Affects the responsiveness of the system to a command to execute another task within Windows while the project is being built.
Frequent:
Causes the IDDE to frequently give up time slices so other applications can execute faster.
Moderate:
Causes the IDDE to give up some of the time to other applications.
None:
Turns off multitasking. Other applications are suspended while the IDDE is building a project.

Netbuild

The IDDE allows the build process to be distributed among one or more remote servers. For more information, see Appendix C, "Using NetBuild."

Use NetBuild

Enables distributed builds.

Use remote headers

Allows the remote server to use the header files provided with Digital Mars C++ on the build server. When this option is off, the build server takes the files from the local machine.

Working directory

Specifies the working directory on the remote server.

Remote password

Specifies the password for logging on to the remote server.

Build order

The Build Order button is only enabled when .prj, .bat, or .mak files are in the project. Clicking on this button opens the Build Order dialog box, shown in Figure 16-17.

Figure 16-17 Build Order dialog box

[Figure 16-17 Build Order dialog box]

The Build Order dialog box specifies the stage of the build in which the .prj, .bat, or .mak files are executed. Do this by selecting a file from the Build File Pool list, clicking on one of the build steps on the right, then clicking on Add. The selectable steps are:

Step 1:
Happens before any compilation takes place.
Step 3:
Happens after the files have been compiled into object files, but before they have been linked to make the target.
Step 5:
Happens after the final executable has been linked. Return any of the files to the Build File Pool list by selecting the filename in one of the steps and clicking on Remove.
When done with the build order, click OK to return to the Make subpage.

Link order

The Link Order button opens the Link Order dialog box, shown in Figure 16-18.

Figure 16-18 Link Order dialog box

[Figure 16-18 Link Order dialog box]

The Link Order dialog box specifies the order in which libraries and object files added explicitly to the project are linked. Do this by iteratively selecting files from the LIBs in Project or the OBJs in Project listbox, then clicking Add to move the files to the Link Order listbox.

Return a file to the LIBs in Project or the OBJs in Project listbox by selecting the filename and clicking on Remove.

The libraries added explicitly to the project are linked before other libraries. The object files added explicitly to the project are by default linked after the object files generated by compiling source files in the project. To specify object files to be linked before any other object files use the Prepended linker input files textbox.

When done with the link order, click OK to return to the Make subpage.


External Make

The options on this subpage govern the use of a make utility other than IDDE Make. Figure 16-19 shows the External Make subpage.

Figure 16-19 External Make subpage

[Figure 16-19 External Make subpage]

Using external make

To use a separate external Make program:
  1. Select Use External Make File.
  2. Specify the .exe name of the Make program in the Make Command Line textbox, followed by any arguments. The IDDE expects the program's directory to be in the PATH environment variable.
  3. To set the Make's default directory, enter the change in the Initial Directory box. By default, this is the directory that contains Make.
  4. Use a Windows PIF file to further customize the way Make behaves.
The next time the Build or Rebuild All command is selected, the IDDE runs the external Make program from a DOS command-line window, which closes when Make is done.

The radio buttons at the top of the dialog box control the Make program that will be run when the IDDE builds the project:

Use IDDE make:
Use the built-in IDDE make tool.
Use external make file:
Use an external Make program.

Make command line

The Make Command Line textbox holds the .exe name of the external Make program followed by any arguments.

Initial directory

Use this textbox to specify the directory from which the Make utility will run.

Librarian

The Librarian subpage (Figure 16-20) specifies options for building a library.

Figure 16-20 Librarian subpage

[Figure 16-20 Librarian subpage]

Ignore case

Directs the librarian utility to ignore case in symbols.

Do not create backup

Keeps the librarian utility from backing up the original library. When this option is turned off, the original library is saved in a backup file.

Page size

Specifies the library page-swapping size.

17. More about AppExpress

Chapter 4, "Generating an Application Framework," defines an application framework and outlines the steps for generating a skeleton application using AppExpress. This companion reference chapter provides further detail concerning application types, program detail, program architecture, message maps, as well as generating and examining source files.

Selecting an Application Type

Select Application Type from the list of steps at the upper left of the AppExpress window. The options pane at the right contains three groups of controls, labeled Applications, OLE Options, and Project Options.

[Figure 17-1 AppExpress application type options

Applications

The group of Applications radio buttons contains six categories of applications. Of these, only Quick Console does not use the MFC library. These categories are: The application types vary in the amount of functionality that AppExpress generates as part of the skeleton program. For example, SDI applications contain only one window, while MDI applications contain a main window and a variable number of child windows.

OLE Options group

The OLE Options group is enabled only if you select the SDI or MDI application type. The group contains four radio buttons:

Project options group

The Project Options group contains two check boxes, Include Help and 32-Bit Project.

Checking Include Help tells AppExpress to generate the files necessary to build a Windows Help file for the specified application type. AppExpress creates a Help subdirectory named hlp beneath the project directory, which contains those files. It also creates the file makehelp.bat, which you run to compile a Windows Help file from the files AppExpress provides.

For all application types other than Quick Console, checking the 32- Bit Project box causes the MFC 3.0 to be used instead of the 16-bit MFC 2.5.

For Quick Console, leaving the box unchecked results in a skeleton WINIO program being generated. WINIO is a library that allows you to write simple Windows programs that perform input/output using standard C library functions (in other words, those functions prototyped in stdio.h.). If the 32-Bit Project box is checked, a Win32 console application is generated. Win32 console applications can only be run under Windows NT and Windows 95 (and not under Win32s).

If you check the 32-Bit Project box, your application can call the Win32 API.

Providing Miscellaneous Information

Selecting Miscellaneous in the steps list opens the Miscellaneous options page. This page lets you provide copyright information as well as a name for the project. Note: The module name is recorded in the module definition file generated by AppExpress. It can be changed by using the Project Settings dialog box, opened from within the IDDE by choosing Settings from the Project menu.

The Document/View Architecture

The MFC library provides a number of C++ classes that, when used together, create the object-oriented structure for your application. These are the document, view, frame window, and document template classes. The Form or Database, SDI, and MDI application types all use document/view architecture. This section introduces the MFC classes that implement this program structure.

Frame window

The frame window contains views on the data used by the application. In an SDI application, there is only one frame window, which is derived from the MFC class CFrameWnd. In an MDI application, there is a main frame window derived from CMDIFrameWnd, as well as document frame windows derived from CMDIChildWnd.

In addition to containing child view windows, the frame window handles all window management- for example, minimizing, maximizing, and closing the window. A standard toolbar and status bar also are displayed in this window.

View

Each frame window can contain a view on the data used by the application. A view is a C++ class derived from the class CView. Your application interacts with the user through this view class.

In the SDI frame window, AppExpress generates a child view window that takes up the client area of the frame window. (The client area refers to the part of the window in which the program's data is displayed. It excludes the window border, caption, and menu.) In an SDI application, this view window is given the default class name CSDIAPPView. All display and printing of the application's data is done using this view window and its class. The user's manipulation of the data is also done through the view.

Document

A document is a C++ class, derived from CDocument, that represents the data in your application. For example, a standard Windows application has a File menu that is a variant of the one shown in Figure 17-2.

[Figure 17-2 Standard Windows file menu] When you choose Open from this menu, you are telling the program to open a document.

Note: The word document refers to whatever type of data is used by the application. It does not necessarily mean a text-based word processing document.

As the developer of the application, you write code in a CDocument-derived class to handle the operations on the File menu. An example of a skeleton CDocument-derived class follows.

	class CSDIAPPDoc : public CDocument
	{   
	protected: // create from serialization only
	    CSDIAPPDoc(); 
	    DECLARE_DYNCREATE(CSDIAPPDoc)
	// Attributes 
	public:
	// Operations 
	public:
	// Implementation 
	public:
	    virtual ~CSDIAPPDoc(); 
	    virtual void Serialize(CArchive& ar);
	#ifdef _DEBUG 
	    virtual void AssertValid() const;
	    virtual void Dump( CDumpContext& dc) const; 
	#endif
	}; 
Notice that no member variables are included with this class. It is up to you as the developer to add whatever data you need for your application.

In the example above, a Serialize method is included in the Implementation section of the class definition. This method, inherited from the base class, CDocument, performs object storage and retrieval to and from a disk file. In fact, the framework generated by AppExpress already handles the File Open, File Save, and File Save As operations by automatically calling the Serialize method in your CDocument-derived class. You can use the Serialize method to implement object persistence- the ability to preserve the complete state of objects across multiple executions of the program.

When you add your own member variables to this class, you should also override the Serialize method to read and write the added variables.

Pulling it all together: the document template

Creating and managing an application's frame window, views, and documents is the job of another C++ class, derived from the CDocTemplate class. In an SDI application, the CSingleDocTemplate class is used; in an MDI application, the CMultiDocTemplate class is used.

For more information, refer to the Microsoft Foundation Class Library Reference.

More about Message Maps

This section outlines the purpose of message maps and identifies the different parts of a message.

The rationale for maps

Using message maps saves you development time. The reason for this productivity improvement lies in the event-driven nature of Windows applications.

As a user of a Windows application clicks on buttons, selects menus, drags the mouse to highlight text, or performs any other mouse or keyboard action, the application is notified of this action through a Windows message. This message contains pertinent contextual information such as the screen coordinates at which the mouse was clicked, or an identifier indicating the button that was clicked.

The application developer decides which messages the application should respond to and how. If the developer decides not to write code to handle a particular message, the message can still be passed back to Windows to perform default processing.

If you write a Windows application using the Windows SDK, these decisions are most likely implemented as a switch statement in the main window procedure (usually referred to as a WndProc). For example, your window procedure might look like this:

	LRESULT CALLBACK WndProc(HWND hwnd,
		UINT message, WPARAM wParam, LPARAM lParam) 
	{
	    switch (message)
	    {
		case WM_PAINT:
		    PAINTSTRUCT ps; 
		    BeginPaint(hwnd, &ps);
		    MyPaintProc(hwnd, ps. hdc); 
		    EndPaint(hwnd, &ps);
		    return(0); 
		case WM_CREATE:
		    hmenu = GetSystemMenu(hwnd, FALSE); 
		    AppendMenu(hmenu, MF_SEPARATOR, 0, (LPSTR) NULL); 
		    AppendMenu(hmenu, MF_STRING, IDM_ABOUT, "About..."); 
		    break;
		case WM_DESTROY: 
		    PostQuitMessage(0);
		    return(0); 
	    }
	    return DefWindowProc(hwnd, message, wParam, lParam);
	} 
If your application must respond to many types of messages, the window procedure can get quite large and become difficult to maintain. One of the advantages of the MFC library is the use of message maps, which drastically reduce the amount of code required to process messages.

Components of the message map

A message map is composed of the three components described in this section.

BEGIN_MESSAGE_MAP, END_MESSAGE_MAP macros

All message maps must begin and end with these macros. At run-time, the expanded macro sets up the message mapping between events and the code to handle the events.

ClassExpress-specific comment sections

AppExpress and ClassExpress add special-purpose comments to the message map so that ClassExpress knows where to add or remove mapping macros. Because ClassExpress provides an easy-to-use interface to your C++ class mappings, you should not manually edit the comments or code in a message map.

Message-mapping macros

If a C++ class has a method (that is, a class member function) to respond to a message, ClassExpress writes a message-mapping macro for that message in the class's message map. This macro begins with the prefix ON_, usually followed by the macro name for the Windows message. The mapping macro takes two parameters:

Generating and Examining the Source Files

Generating the source files of the application framework is as easy as clicking on a button. After the files are generated, you may want to examine the header and implementation files. AppExpress typically generates one header and one implementation file for each class. (An exception is the CAboutDlg class, which shares files with the application class.) Examining a few generated files in the IDDE, setting breakpoints on methods, and tracing through their code will help you understand the internal workings of the frameworks that AppExpress generates. At that point you will then be ready to edit the code in order to enhance it as needed.

To generate and examine sample source files:

  1. Launch AppExpress from the IDDE Tools menu, and make all the selections necessary to create an SDI application. When you click on Finish, AppExpress generates all the source files for this skeleton program. When it is done, AppExpress gives control to the IDDE (with the new project open), and then closes.
  2. Open the Project window in the IDDE by clicking the Project View icon and dragging it onto the desktop, or by pressing Ctrl+ Shift+ P.
  3. Double-click on the filename mainfrm.h. A Source window opens containing the header file mainfrm.h. (For more information on Source windows, see Chapter 2, "Introducing the IDDE.")
This file, which AppExpress generated, contains the definition of the class CMainFrame. It is reproduced in its entirety below.
	// mainfrm.h : interface of the CMainFrame class 
	// 
	// Copyright (c) XYZ Corporation, 1994. All Rights Reserved. 
	// 
	// 
	class CMainFrame : public CFrameWnd 
	{   
	protected: // create from serialization only 
	    CMainFrame(); 
	    DECLARE_DYNCREATE(CMainFrame) 
	// Attributes 
	public: 
	// Operations 
	public: 
	// Implementation 
	public: 
	    virtual ~CMainFrame(); 
	#ifdef _DEBUG 
	    virtual void AssertValid() const; 
	    virtual void Dump(CDumpContext& dc) const; 
	#endif 
	protected: // control bar embedded members 
	    CStatusBar m_wndStatusBar; 
	    CToolBar m_wndToolBar; 
	// Generated message map functions 
	protected: 
	    //{{ AFX_MSG(CMainFrame) 
	    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 
		// ClassExpress will add and remove member functions here. 
		// DO NOT EDIT these blocks of generated code ! 
	    //}} AFX_MSG DECLARE_MESSAGE_MAP() 
	}; 
The file contains: In the class declaration, notice that the status bar and toolbar are represented by class member variables, each of which is an instance of yet another C++ class. When writing code to manipulate the toolbar and status bar, reference these member variables.

In the protected section of the class declaration is a prototype for a function that is called as part of the class's message map. As indicated, do not edit the code in this section because it is reserved for ClassExpress.

AppExpress also generates a .cpp, or implementation, file for the CMainFrame class. This file has the same base name, mainfrm, as the class header file, but has the .cpp extension. To examine mainfrm.cpp, open this file in an IDDE Source window. This implementation file contains the following components:

The next chapter covers ClassExpress, one of the tools (along with the Resource Studio) used to enhance an application generated by AppExpress.

18. More about ClassExpress

Chapter 4 defined the concept of an application framework and outlined the steps for building on your skeleton application using ClassExpress. This companion reference chapter provides more detail about using ClassExpress, including:

Deriving a Class to Handle User Interface Events

With ClassExpress, you can derive a new class designed to handle user interface events such as menu selections and button clicks directly from a Microsoft Foundation Class (MFC) library class. Suppose, for example, that you want to add a new dialog box to your application. To derive a class from the CDialog class using ClassExpress, follow these steps:
  1. Create an application framework for a standard SDI program using AppExpress (for details, see Chapter 4, "Generating an Application Framework").
  2. Use ResourceStudio to create a new dialog box resource (see Chapter 7, "Adding Look and Feel with Resources").
  3. Launch ClassExpress from ResourceStudio or from the IDDE's Tools menu.
  4. Add a new class to your program by clicking on the Add Class button. (Follow the instructions in Chapter 4, "Generating an Application Framework.") Be sure to derive the new class from the Dialog class type.

    In ClassExpress, all of the base classes from which you derive new classes are themselves derived from the MFC class CCmdTarget. The MFC Library Reference defines CCmdTarget as the base class for the message map architecture. Any class derived from CCmdTarget inherits the ability to respond to user interface events such as menu and toolbar selections and dialog box actions.

  5. In the ClassExpress main window, verify that your class has been created by browsing through the Class drop-down list.
  6. Select the new class name from the Class list. Note that the list of Control IDs and Windows messages for your derived dialog box class is different from the list for non-dialog classes.
Note: ClassExpress filters out the Control IDs and Windows messages that do not apply for the selected class name. For example, dialog box classes can handle the WM_INITDIALOG message, but this message is not handled by any class derived from CFrameWnd.

The ability to add new classes that derive specialized message-handling functionality from the base MFC classes is one of the benefits of using ClassExpress. The following material summarizes the type of functionality that a new class inherits if it is derived from CCmdTarget. For more information on any of these base classes, refer to the Microsoft Foundation Class Library Reference.

CmdTarget:
The base class for all MFC classes that offer support for Windows message handling. You probably will not derive a new class directly from CmdTarget; instead, use the other base classes in this list.
Dialog:
This class implements dialog boxes, either modal or modeless. It usually is associated with a dialog box resource template created in ResourceStudio. Member variables of this class typically are mapped to fields or controls in the dialog box. For details on how this mapping is established, see the next section, "Working with Data Transfer: DDX and DDV."
Document:
The application's data is represented by the document class. The data can be anything the programmer chooses. All file input and output should be handled within the document class.
FormView:
A class of views that has built-in support for scrolling and for child controls. FormViews typically are combined with a dialog box resource template. One way in which the FormView class differs from the Dialog class is its added support for scrolling.
FrameWnd:
The main window class for single document interface (SDI) applications.
MDIChildWnd:
The child document window class for multiple document interface (MDI) applications.
ScrollView:
A class of view window that supports scrolling.
View:
The base class that provides the connection between the document class representing the program data and the user interface to that data.
Wnd:
The base class for any window, including dialog boxes, frame windows, views, and dialog box controls. Because this class is used to derive many of the other classes listed here, choose Wnd as a base for a new class if other choices do not satisfy your programming requirements.
Splitter:
This special type of window can contain multiple panes. A pane is usually a window that is associated with a View-derived class in the application.

Working with Data Transfer: DDX and DDV

The previous section discussed the architecture classes that you use to build an object-oriented Windows program with the MFC library. The application, document, view, template, and frame window objects are the key components of a standard Windows, MFC-based application.

This section describes MFC library support for data transfer between dialog boxes or other windows and your C++ objects that store that data. This is referred to as Dialog Data Exchange (DDX) and Dialog Data Validation (DDV). You use the Data Transfer options of ClassExpress to bind class member variables to dialog box or window controls.

Note: Data transfer using DDX/DDV can be applied to any window that is derived from the MFC base class, CWnd. It is not restricted to dialog boxes derived from CDialog.

Dialog Data Exchange with Windows 95 Common Controls is also supported.

Implementing Dialog Data Exchange (DDX) using ClassExpress

To implement DDX using ClassExpress, use the following steps. Before performing these steps, generate a dialog box application with AppExpress, then:
  1. Add a few edit controls to your skeleton dialog box using ResourceStudio.
  2. Launch ClassExpress from ResourceStudio or from the IDDE's Tools menu. ClassExpress loads the project and displays the Message Maps options.
  3. In the upper-left listbox, click on Data Transfer. From the Class drop-down list, select the CMainDialog class.

    The ClassExpress window should look similar to that shown in Figure 18-1.

    [Figure 18-1 Data Transfer page in ClassExpress

  4. Click on the Add Variable button. The Add Member Variable dialog box shown in Figure 18-2 opens.

    [Figure 18-2 Add Member Variable dialog box

  5. From the Control ID drop-down list, select a dialog box control that you want to map to a class member variable.
  6. Edit the Member Variable Name to specify the name of a variable to be mapped to the selected Control ID. The variable does not have to exist in the class. (ClassExpress adds it automatically to the class for you.)

    Note: Nonstatic class member variable names are usually prefixed with m_for easy identification; however, you are not required to follow this convention.

  7. For DDX Type, select Control to map the control ID and variable name to a control class (such as CButton or CEdit). Select Value to map to a CString or to a numeric type.
  8. Select a Variable Type for this member variable from the Variable Type drop-down box. The available types depend on the type of control being mapped and the DDX Type option.
  9. If you selected Value from the Type radio buttons, one or two additional fields are displayed along the bottom of the dialog box. If the added member variable is of a numerical variable type, two fields are displayed, which allow you to set the minimum and maximum ranges for the variable's value. If the variable type is CString, then only one field is displayed, in which you specify the maximum number of characters that the CString can contain. (You cannot specify a minimum number of characters.)

    Figure 18-3 shows an example using a CString variable type.

    [Figure 18-3 Adding a CString member variable

  10. Click OK. You are now back in the ClassExpress window, and the member variable you just added is displayed in the spreadsheet. If you added minimum or maximum values for your member variable, a dialog data validation function name is displayed in the DDV type field.

Understanding data transfer at the source code level

The procedure in the preceding section instructs ClassExpress to establish a link between your CMainDialog class and a control within a dialog box. In the implementation file maindlg.cpp are calls to virtual functions that CMainDialog inherits from other MFC classes. These functions perform the dialog data exchange and validation (DDX/DDV) for your program.

This section explores the source code generated by ClassExpress and explains the implementation of data transfer- the first step in how DDX functions bind member variables to dialog box objects to transfer data between the variables and the controls. Next, the validation of values entered into dialog box controls is explained. The third section describes how data transfer functions are invoked by the UpdateData function.

Dialog Data Exchange (DDX)

To implement DDX, follow these steps:
  1. Select Open from the IDDE's Project menu to open the dialog box project you created earlier.
  2. Open the maindlg.cpp file in a Source window. Either double-click on maindlg.cpp in the Project window or open an empty Source window, then open the source file using the Open command in the File menu.
  3. From the Edit menu, choose Find and search for DoDataExchange. Look at the definition for the method CMainDialog::DoDataExchange. ClassExpress has overridden the CWnd method DoDataExchange in your CMainDialog class. A sample implementation of DoDataExchange follows.
	void CMainDialog::DoDataExchange(CDataExchange* pDX) 
	{   
	    CDialog::DoDataExchange(pDX); 
	    //{{ AFX_DATA_MAP(CMainDialog) 
	    DDX_Control(pDX, IDABOUT, m_About); 
	    DDX_Control(pDX, IDOK, m_OKButn); 
	    DDX_Control(pDX, IDCANCEL, m_CancelButn); 
	    DDX_Control(pDX, IDHELP, m_Help); 
	    //}} AFX_DATA_MAP 
	} 
DDX lets you copy data easily from class member variables to dialog box controls, then from the controls back to the member variables. This is accomplished by implementing an override for the CWnd::DoDataExchange method in your dialog box class. For each control that is mapped to a member variable, ClassExpress generates a call to a DDX function. There are four DDX function calls in the code sample shown above.

DDX functions take the form:

	DDX_xxx(pDX, nIDC, Data); 
where: Note: DDX functions that exchange data with Visual Basic custom controls (VBXs) take an additional parameter, nPropIndex- the property index being exchanged. This parameter is shown before the Data parameter.

The preceding sections cover how ClassExpress prompts you for new member variables, then generates code that performs automatic data exchange between those variables and their respective dialog box or window controls. The next section describes how to enhance data exchange by using data validation.

Dialog Data Validation (DDV)

When adding a new variable using the Data Transfer options in ClassExpress, you can define minimum and maximum values for numeric variables and maximum lengths for CString variables. This is illustrated in Figure 18-4 below.

[Figure 18-4 Adding a numeric member variable

In this example, the member variable m_PayTo is defined as an integer and is limited to values between 100 and 5000. This variable is bound to a dialog box edit control identified by IDC_PAYTO. The user of the application is not allowed to enter a value in that control that is outside the minimum and maximum bounds.

You do not have to write a single line of code to enforce this rule. The DDV functions in the MFC library do this for you. After adding the variable m_PayTo, as shown earlier, and clicking Close in ClassExpress's main window, ClassExpress writes the following lines to the DoDataExchange method of your dialog box class:

	DDX_Text(pDX, IDC_PAYTO, m_PayTo);
	DDV_MinMaxLong(pDX, m_PayTo, 100, 5000); 
The first line binds the edit control to your m_PayTo member variable. This uses a DDX function, as discussed earlier in this chapter. The second line is the DDV function that limits values in the textbox control to between 100 and 5000.

Note: For each member variable, the DDV function call should immediately follow the DDX function call in your DoDataExchange function. This is a requirement of the application framework and is enforced when ClassExpress writes new DDX/DDV function calls to the source code file.

DDV functions take the following form:

	DDV_xxx(pDX, Data, ...); 
where:

Calling UpdateData

Your dialog class's DoDataExchange method is called by another CWnd method, UpdateData, whose prototype follows:
	BOOL UpdateData(BOOL fSaveOrValidate); 
If the parameter to UpdateData is FALSE, then the function updates the dialog box controls with data from class member variables that have been mapped to the controls. If the parameter is TRUE, then the member variables are updated with data from the controls and validated.

You call UpdateData from the places in your program at which you want to exchange data with the dialog box. UpdateData is called for you automatically in only one place in the dialog initialization.

In response to the WM_INITDIALOG message, the CDialog::OnInitDialog method calls UpdateData with a parameter equal to FALSE, indicating that the controls are being set. Initialize the values of a dialog class's member variables in your OnInitDialog method. For example:

	BOOL CMainDialog::OnInitDialog() 
	{   
	    m_ColorIsRedCheckBox = TRUE; 
	    m_Filter = FILTER_NONE; 
	    CDialog::OnInitDialog(); 
	} 
Here two member variables, m_Color and m_Filter, are set to initial values. When the CDialog::OnInitDialog method is called, it uses those values to set the state of the dialog box controls mapped to these member variables.

Making Your Application an OLE Automation Server

This section covers the following topics: Note: Use of the acronym OLE (object linking and embedding) in this section refers to version 2 of OLE, which includes automation support.

What is an OLE automation server?

OLE automation is an architecture that allows programs to manipulate objects within other applications. The application that defines the objects is called the automation server. Any application that uses OLE to manipulate another application's objects is called an automation client. For example, Microsoft Excel is an automation server, and Microsoft Visual Basic is an automation client. From within Visual Basic, you can write a program that loads an Excel spreadsheet, runs Excel macros, and saves the spreadsheet.

OLE automation server vs. OLE server

OLE automation is an extension of the original object linking and embedding technology that originated in version 1 of OLE. The linking and embedding features determine how data from one application is used in another. For example, you can embed a spreadsheet document within a word processing document, or link a word processing document to a spreadsheet document that exists in a file.

Note: An embedded object's data is saved as part of the client application's data. A linked object's data is saved independently of the client's data; the client's data contains a reference to the filename of the linked data.

In these examples, the application that is the container for the spreadsheet is called an OLE client or a container application. The application that originally created the spreadsheet and that is used to edit the spreadsheet is called the OLE server application. The server application is responsible for creating and maintaining data objects embedded in or linked to another application.

When you create an OLE server application with AppExpress, you are making it possible for your application's data to be embedded in or linked to another application's data.

OLE automation was introduced in the second version of the OLE technology. Automation has nothing to do with embedding or linking to data objects. It is used to manipulate objects that an OLE automation server has created.

Using OLE automation to manipulate an object allows you to do some or all of the following:

Although an OLE server might provide embedding, linking, and automation support, all three options do not have to be provided. For example, you could create an automation server that only performs mathematical calculations, has no user interface, and is accessible only by function calls through the OLE automation interface. In this case, you only need an OLE automation server. Linking and embedding technology, which is packaged in a standard OLE server, is not required.

Enabling your application to be an OLE automation server

This section assumes that you have generated a sample MFC-based application framework with AppExpress. You use that framework in this section.

To enable your application to be an OLE automation server:

  1. With the project containing your sample application framework loaded in the IDDE, launch ClassExpress by choosing it from the Tools menu in the IDDE's main window.
  2. To act as an OLE automation server, your application needs a C++ class that defines an automation object. In ClassExpress, you take care of this by adding a class. Click on the Add Class button.
  3. Select a Class Type. This specifies the MFC class from which your new class is derived.
  4. Type the name of the class in the New Class Name textbox.
  5. Check the OLE automation box. If your class is derived from CCmd Target or CWnd, the Creatable check box and the External Name textbox become visible.
  6. For CCmdTarget-and CWnd-derived classes, if you want OLE client applications to be able to create instances of your OLE automation object, check the Creatable box as well.
  7. For CCmdTarget-and CWnd-derived classes, enter an External Name that will be used by OLE automation client applications to identify your automation object.
  8. Click OK. At this point, ClassExpress generates the new class in your project's source code and reports that the classes were generated correctly. You are returned to the main ClassExpress window.
Completing these steps creates the basic source code structure for your OLE automation class. However, you may also want to take advantage of ClassExpress's ability to add functions and properties to your class that will be exposed by OLE automation.

Adding exposed functions to an automation server class

First, select the class from the Class Name drop-down list. To add a function, follow these steps:
  1. Click the Add Function button on the Automation Server page of ClassExpress. The Add Function dialog box opens.
  2. In the External Name textbox of Add Function, type the name by which automation clients will refer to the new function. As you type, the Internal Name textbox mirrors the name you are entering.
  3. If you want your new function to have an Internal Name different from its External Name, type the desired Internal Name in that textbox. The Internal Name is the name the function will have in your source code.
  4. Select the function's Return Type from the drop-down list with that label. In addition to the standard types void, short, long, float, and double, this list contains the OLE types CY, DATE, LPDISPATCH, SCODE, BOOL, VARIANT, and LPUNKNOWN. If you are unfamiliar with these latter types, consult the OLE2 Programmer's Reference for their definitions.
  5. If your function takes arguments, add them one at a time by clicking on the Add button at the bottom of the Parameters List listbox. The Add Parameter dialog box that is displayed lets you specify the Name and Type of a parameter. Enter the parameter's name in the Name textbox. Select its type from the Type drop-down list. (The Type list contains more OLE types. See the OLE2 Programmer's Reference for details.) Click OK. You are returned to the Add Function dialog box, in which the parameter you just specified is displayed in the Parameters List listbox.

    Follow the procedure just described to add any other parameters the function requires.

  6. Click OK in the Add Function dialog box. You are returned to the Automation Server page of ClassExpress. The function you just created is added to the Name listbox, and is referred to using its external name. When this function is selected in the Name listbox, the Implementation listbox displays the prototype of the function that ClassExpress generates to implement it.

Adding properties to an automation server class

First, select the class from the Class Name drop-down list. To add a property, follow these steps:
  1. Click the Add Property button on the Automation Server page of ClassExpress. The Add Property dialog box opens.
  2. Select one of the radio buttons to the right of the Implementation label. If you want to grant automation clients read-only access to the property you are adding, select Variable. If you want to grant read/write access to the property, select Get/Set Function.
  3. In the External textbox, type the name by which automation clients will refer to this property.

    As you type, the values of the Get Function and Set Function fields are automatically filled in using the external name extname you specify. If you are creating a read-only property, it will be implemented as a member variable in your automation class. The Get Function textbox will contain the proposed name of that variable, m_extname. If you are creating a read/write property, it will be implemented by a pair of member functions- a Get and a Set function- in your automation class. The Get Function and Set Function textboxes will contain the proposed names of those functions, Getextname and Setextname.

  4. Select the Type of the property from the drop-down list with that label. In addition to the standard types short, long, float, and double, this list contains the OLE types CY, DATE, LPDISPATCH, SCODE, BOOL, VARIANT, and LPUNKNOWN. If you are unfamiliar with these latter types, consult the OLE2 Programmer's Reference for their definitions.
  5. If you want, change the names of the Get and Set Function.
  6. Click OK in the Add Property dialog box. You are returned to the Automation Server page of ClassExpress. The property you just created is added to the Name listbox and is referred to using its external name. When this item is selected in the Name listbox, the Implementation listbox displays the member variable or the pair of functions that ClassExpress generates to implement the property.

OLE automation server source code

This section examines some of the source code generated by ClassExpress that enables an application to be an OLE automation server.

As explained in the previous section, you create a new class using ClassExpress and indicate that the class should support OLE automation. When the source code is generated, the constructor for your new class contains the following code:

	EnableAutomation(); 
	// To keep the application running as long as 
	// an OLE automation 
	// object is active, the constructor calls 
	// AfxOleLockApp. 
	AfxOleLockApp(); 
OLE automation is first enabled for this object using the MFC function EnableAutomation. This function should only be called if there is a dispatch map declared for the class (discussed in more detail below). If your new class objects are creatable by other applications, then the MFC function AfxOleLockApp is called in your constructor.

This function increments a global count of the number of times this object has been activated by OLE clients. It is the MFC library's way of ensuring that an object is not destroyed by one OLE client, if it is in use by another client. In the destructor for your class, ClassExpress has written a call to the function AfxOleUnlockApp, which decrements the global count for this object.

ClassExpress also creates a new macro structure called a dispatch map, as shown in the following example:

	BEGIN_DISPATCH_MAP(COLEAutoObject, CCmdTarget) 
	    //{{ AFX_DISPATCH_MAP(COLEAutoObject) 
		// NOTE -the ClassExpress will add and 
		// remove mapping macros here. 
	    //}} AFX_DISPATCH_MAP 
	END_DISPATCH_MAP() 
As you can see, a dispatch map is similar to a message map, the MFC library macro for routing Windows messages to your class methods. Like message maps, you do not edit the dispatch map directly; AppExpress and ClassExpress do that for you. The dispatch map is a macro that generates dispatch table information used by the MFC library's OLE classes to route automation requests.

In addition to the OLE initialization code in the constructor and the dispatch map, ClassExpress optionally writes the following macro to your class implementation file (.cpp):

	IMPLEMENT_OLECREATE(COLEAutoObject,"MYOBJ",
		0xd73cfd60, 0x3cea, 0x101b, 0x80, 0x60, 
		0x4, 0x2, 0x1c, 0x0, 0x94, 0x2) 
This macro is written if you selected the Creatable check box when you added the new class in ClassExpress. The macro allows your OLE automation object, as defined by your new C++ class, to be created dynamically by an OLE client application. If you do not have this macro, your automation object would have to be created by your application before any OLE client could manipulate it using the automation interface.

The IMPLEMENT_OLECREATE macro takes these arguments:

The last parameters, the components of the OLE class ID, together represent a 128-bit value that uniquely defines the OLE object within Windows.

Another source code file created by ClassExpress has a filename consisting of the project name with the extension .odl. This file contains the Object Description Language implementation for your automation object class. You run the utility program mktyplib.exe, passing the .odl file as an argument. The result is a type library file with an extension of .tlb.

The type library file is used by OLE automation clients to query the objects, properties, and functions exposed by your application.

This section has given you a view of the source code generated for an OLE automation server. OLE automation has many more facets that you should explore. Refer to the Microsoft Foundation Class Library Reference and the OLE2 Programmer's Reference for additional details.

Making Your Application an OLE2 Automation Client

The Automation Client selection of ClassExpress lets you make an application an OLE2 automation client for type libraries that export an OLE2 automation interface. ClassExpress creates a C++ class in your program that acts as an interface to the type library class.

This section uses the OLE2 sample type library hello.tlb, found in samples\ole16\hello below your Digital Mars C++ installation directory. If you do not have this sample file installed, you can select any other type library file that exports an OLE2 automation interface. Otherwise, you should install the OLE2 samples.

To make your application an OLE2 automation client:

  1. Launch ClassExpress and, if necessary, open a project. For this example, the application type of the project does not matter.
  2. Select Automation Client from the list at the upper left of the ClassExpress window.
  3. Click the "..." button to the right of the Type Library File field. The Open dialog box is displayed.

    Note: This dialog box has filtered out all filenames that do not end with .tlb or .olb. These extensions are used for OLE type library files.

  4. Browse to the type library file samples\ole16\hello\hello.tlb within the Digital Mars C++ installation directory.
  5. Click OK in the Open dialog box. The type library file should now be displayed in the Type Library File field in the ClassExpress window.

    Note: Class names representing exported OLE2 automation interfaces in the type library are displayed in the Class list.

  6. Select _DHello from the Class list.
  7. ClassExpress fills in the New Header File and New Implementation File fields with the suggested file names for the new C++ class that will be generated in your framework.
  8. Click on the Generate button. ClassExpress creates the header and implementation file for your new class.
The C++ class _DHello that was generated by ClassExpress represents the client OLE automation interface to the _DHello type defined in hello.tlb. This class provides a number of methods that simplify the processes of attaching to and detaching from an OLE automation dispatch connection. ClassExpress generates additional methods that simplify the interface to IDispatch::Invoke. If you are not familiar with the OLE automation architecture, refer to the OLE2 Programmer's Reference.

Creating a C++ Wrapper Class for an Existing VBX

The VBXExpress section of ClassExpress lets you incorporate VBX controls into an MFC application. ClassExpress makes it easy to use a VBX by generating a C++ wrapper class through which you can directly program the VBX. The wrapper class makes use of the MFC base class CVBControl, which provides access to VBX properties and events.

You can use VBXExpress with any 16-bit MFC application. (The restriction arises because VBXs themselves are inherently 16-bit.) Follow these steps to create a wrapper class for a VBX and add it to the class hierarchy of a project:

  1. Launch ClassExpress- either from the IDDE or standalone. If you launch ClassExpress standalone, specify your project in the Open dialog box.
  2. Select VBXExpress from the list at the upper left of the ClassExpress window.
  3. The control labeled VBX File displays the name of the currently selected VBX file. Click the button labeled "...", to the right of the control. An Open dialog box is displayed. Select a VBX file and click OK.

    VBX File displays the name of the file selected.

    ClassExpress examines the VBX file to determine the name and capabilities (events and properties supported) of every VBX control contained in the file. (There can be more than one.) The drop-down list labeled VBX contains the names of all VBXs in the file. The capabilities of the control selected from this list are displayed in the Property and Event list.

  4. In the textbox labeled ClassName, specify the name of the C++ wrapper class that will be generated for the currently selected VBX control. In the textboxes labeled Header File, specify the names of the C++ files that will contain the definition and implementation of the class. Default names are provided in all three fields; you don't have to change them.
  5. Repeat the above step for each VBX control in the VBX file.
  6. Click on the Generate button. ClassExpress creates the C++ wrapper classes.
Examine the interface to the VBX control(s) generated by ClassExpress by opening the header file in an IDDE source window. You will see that the methods of the C++ class correspond in a natural way to the properties and events of the VBX.

Summary

This chapter covers ClassExpress in detail discussing these main points: With this information, you are able to add significant new functionality in a short period of time to the skeleton application framework that AppExpress generates.

19. Class Editor Reference

This chapter describes menu operations and mouse functions available in the Class Editor. For an introduction to this tool, see Chapter 5, "Defining Classes and Their Hierarchies."

The Class Editor Window

There are several ways to open a Class Editor window: Multiple instances of the Class Editor may be open at the same time. These windows share data among themselves and with Hierarchy Editor windows, so changes made in one window are transmitted instantly to the others.

Edit menu commands

With one exception, the commands in the Edit menu (Figure 19-1) operate on text in the Source pane and are identical in function to the corresponding Edit menu commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

[Figure 19-1 Edit menu commands

Global Undo

Cancels the last operation performed in the Class Editor or Hierarchy Editor (such as Add Class or Add Member). The text of this menu item changes to reflect the previous operation performed in the Class Editor.

Goto menu commands

The commands in the Goto menu (Figure 19-2) are used to move around within the Source pane and are identical to the corresponding Goto menu commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

[Figure 19-2 Goto menu commands

Macro menu commands

The commands in the Macro menu (Figure 19-3) are identical to Macro menu commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

[Figure 19-3 Macro menu commands

New! command

This command opens another Class Editor window.

Classes pane pop-up menu commands

The Classes pane pop-up menu (Figure 19-4) contains commands to add and modify classes and inheritance relationships, and to access Class Editor options.

[Figure 19-4 Classes pane pop-up menu commands

Add Derived

Opens a dialog box (Figure 19-5) that lets you add a new class to the hierarchy. The new class is a derived class of the currently selected class(es), whose name is shown in the dialog box's title.

[Figure 19-5 Create Derived Class dialog box

Class name
Specifies a name for the new class.
Header file
Contains the name of the header file into which the class declaration is placed. By default, the first eight characters of the class name (with .h appended) are used as the header file name. You may type an alternative filename into the textbox, or click on Browse to select a filename from the Class Header File dialog box.

Add Top

Adds a top-level (baseless) class. The dialog box that opens as a result of selecting this command is identical in function to the one that opens when you choose the Add Derived command.

Add Sibling

Adds a class that is a sibling of (derived from the same base class as) the currently selected class. The dialog box that opens as a result of selecting this command is identical in function to the one that opens when you choose the Add Derived command. You cannot add siblings to classes with multiple base classes.

Show Header

Opens a new Source window to edit the header file containing the declaration of the currently selected class.

Note: You can also perform this action by moving the cursor towards the left margin of the Class pane until its orientation changes and it points to the right. Then select a class and drag it onto the desktop while holding down the Control key.

Connect Base

Opens the Add Base dialog box (Figure 19-6) that lets you add a base class to the selected class.

[Figure 19-6 Add Base dialog box

Access
These options indicate the base class access specifier:
Public:
Public members of the base class are public members of the derived class, and protected members of the base class are protected members of the derived class.
Protected:
Public and protected members of the base class are protected members of the derived class.
Private:
Public and protected members of the base class are private members of the derived class.
Virtual
Specifies the base class to be virtual.
Base class
Specifies the class that is made a base of the selected class. You can select more than one class to make a base class by holding down the Control key while clicking on the class name, or by holding down the Shift key while selecting a range of classes.

Edit Base Attributes

Opens the Edit Base Attributes dialog box (Figure 19-7) with which you change the attributes of the connection between the selected class and its base class.

This command is disabled if classes are sorted alphabetically rather than hierarchically.

[Figure 19-7 Edit Base Attributes dialog box

Access
These options indicate the base class access specifier:
Public:
Public members of the base class are public members of the derived class, and protected members of the base class are protected members of the derived class.
Protected:
Public and protected members of the base class are protected members of the derived class.
Private:
Public and protected members of the base class are private members of the derived class.
Don't change:
Appears only if you are editing the attributes of more than one connection and the base class access specifiers are not all identical. It means that the base class access specifiers are not altered. It lets you change the Virtual specifier of all connections without affecting their individual access specifiers.
Virtual
If selected, this option specifies the base class to be virtual. If grayed, the virtual setting is left unchanged.

If the selected class is derived from multiple bases, only the attributes of the connection with the base class immediately above in the Classes pane are changed.

Delete Base Connection

Deletes the connection between the selected class and its base class. If the class is derived from multiple bases, only the connection with the base class immediately above it in the Classes pane is removed.

You will be prompted to confirm this if the Confirm Inheritance Changes option on the General page of the Editing/Browsing Settings dialog box is selected.

This command is disabled if classes are sorted alphabetically rather than hierarchically.

Settings

Opens the Editing/Browsing Settings dialog box, in which you set general Class Editor and text editor options. Details of this dialog box are discussed in "Class Editor Settings," later in this chapter.

Members pane pop-up menu commands

The Members pane pop-up menu (Figure 19-8) contains commands to add, delete, and modify class members, and to access Class Editor options.

[Figure 19-8 Members pane pop-up menu commands

Add

Opens the Add Member dialog box (Figure 19-9). The new member is added to the class whose members are currently displayed in the Members pane.

[Figure 19-9 Add Member dialog box

Access
These options specify the member access control:
Public:
Public members are accessible from outside the member's class.
Protected:
Protected members are accessible only within the member's class, derived classes, and their friends.
Private:
Private members are accessible only within the member's class and its friends.
Storage
These options specify the member storage class:
Normal:
The member has no storage modifiers.
Static:
Only one copy of the member exists; it is shared by all objects of the member's class.
Virtual (functions only):
The function may be overridden in derived classes.
Pure virtual (functions only):
The function must be overridden in derived classes; the class is abstract.
Friend (functions only):
The named function is allowed access to the class's private and protected members.
Inline
Requests inline implementation of a function. Causes its definition to be placed in the .h file.
Declaration
Contains the member declaration. For data items, enter the type and member name (for example, int nCats). For functions, enter the return type, function name, and argument types (for example, void AddCats(int)). Do not precede the declaration with storage specifiers; use the option buttons above. Trailing semicolons are optional.
Source file
Contains the name of the source file into which the member definition is placed. By default, the first eight characters of the class name (with .cpp appended) are used as the source file name. You may type an alternative filename into the textbox, or click on Browse to select an alternative filename from the Member Source File dialog box.

The member declaration is placed in the class declaration. If the specified source file does not already exist, it is created and added to the project. By default, empty definitions of inline functions are placed in the header file. Empty definitions of normal, static, and virtual functions, as well as static data members, are placed in the source file.

Delete

Deletes the currently selected member. If the Confirm Member Delete option on the General page of the Editing/Browsing Settings dialog box is selected, you are asked to confirm the deletion. The member's declaration and definition (if applicable) are removed from the header and source files.

Edit Attributes

Opens the Change Member Attributes dialog box (Figure 19-10), which you use to edit access and storage specifiers of the selected member.

[Figure 19-10 Change Member Attributes dialog box

Access
These options specify the member access control:
Public:
Public members are accessible from outside the member's class.
Protected:
Protected members are accessible only within the member's class, derived classes, and their friends.
Private:
Private members are accessible only within the member's class and its friends.
Don't change:
Only appears if you are editing the attributes of more than one member and their access controls are not all identical. It means that the access control is not altered. It lets you change other member attributes without also affecting their individual access controls.
Storage
These options specify the member storage class:
Normal:
The member has no storage modifiers.
Static:
Only one copy of the member exists; it is shared by all objects of the member's class.
Virtual (functions only):
The function may be overridden in derived classes.
Pure virtual (functions only):
The function must be overridden; the class is abstract.
Friend (functions only):
The named function is allowed access to the class's protected and private members.
Don't change:
Only appears if you are editing the attributes of more than one member and their storage classes are not all identical. It means that the storage class is not altered. It lets you change other member attributes without affecting their individual storage classes.
Inline
Requests inline implementation of a function. If grayed, the current setting is left unchanged.
Source file
If applicable, this option contains the name of the source file holding the member definition. You may change the filename in the textbox, or click on Browse to select an alternative filename from the Member Source File dialog box.

Show Source

Opens a new Source window to show the source file containing the definition of the currently selected member.

If you add new functions or static data definitions to the source file or alter function argument or return types, you must update the class header to reflect the changes.

Settings

Opens the Editing/Browsing Settings dialog box that lets you set general Class Editor and text editor options. Details of this dialog box are discussed in "Class Editor Settings," later in this chapter.

Source pane pop-up menu commands

With one exception, commands in the Source pane pop-up menu (Figure 19-11) are identical to the corresponding commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

[Figure 19-11 Source pane pop-up menu commands

Save

Saves the program code shown in the Source pane and places it in the appropriate source or header file.

Changes to static data and to function argument and return types made in the source code are updated automatically in the class declaration and Members pane.

Class editor mouse functions

The mouse is used to select classes and members, perform editing operations, open pop-up menus, and change the relative sizes of Class Editor panes. As mentioned in "The Class Editor Window" above, drag and drop operations are supported.

To resize the panes, first position the cursor over the dividing line between panes. The cursor changes to a two-headed arrow. Then, press the left mouse button and drag the separator to the desired location.

Classes pane

The right mouse button opens the pop-up menu (see "Classes pane pop-up menu commands," earlier in this chapter).

Select a class by clicking on it. Several classes may be selected by clicking on each one while holding down Control. The members of the class last selected appear in the Members pane. You may drag and drop a class into the source pane; the class name is inserted into the buffer.

Members pane

The right mouse button opens the pop-up menu (see "Members pane pop-up menu commands," earlier in this chapter).

Select a member by clicking on it. Several members may be selected by clicking on each one while holding down Control.

Double-clicking on a member causes its definition (if appropriate) or declaration to appear in the Source pane. If the source is not available, the declaration is displayed.

You may drag and drop a member into the source pane; the member declaration is inserted into the buffer.

Note: In addition to clicking on it, you can select a member when the Members pane is active by typing its name. As you type, the Class Editor attempts to automatically complete the name. (Depending on the rate at which you type, it may consider a character to be the first character of a new selection, rather than the next character in the current select operation.)

Source pane

The right mouse button opens the pop-up menu (see "Source pane pop-up menu commands," earlier in this chapter).

The source pane supports typical Source window mouse and cursor operations, as described in Chapter 21, "Text Editor Reference."

Toolbar commands

The Class Editor toolbar (Figure 19-12) offers quick access to several menu options.

[Figure 19-12 Class Editor toolbar

These options are the same as those in other menus:

Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
Add top:
Same as choosing Add Top from the Classes pane pop-up menu.
Add derived:
Same as choosing Add Derived from the Classes pane pop-up menu.
Add member:
Same as choosing Add from the Member pane pop-up menu.
Connect base:
Same as choosing Connect Base from the Classes pane pop-up menu.
Play macro:
Same as choosing Play from the Macro menu.

Class Editor Settings

You can access Class Editor settings by choosing Text Settings from the Edit menu, or Settings from the Classes or Members pane pop-up menus. These commands open the Editing/Browsing Settings dialog box, a workspace with tabs along the top margin. The tabs are used to switch between several sets of options. The Class, Member, and General options are discussed in this section; the remaining options pertain to text editing and are discussed in Chapter 21, "Text Editor Reference."

General options

The General options set (Figure 19-13) contains options for undo levels, class/member bar confirmations, output window actions, and key bindings, as well as some options related to the text editor.

[Figure 19-13 General options

Browser operations

Specifies the number of operations that can be undone in the Class and Hierarchy Editors with the Global Undo command.

Text edits, per buffer

Specifies the number of edit operations that can be undone, per buffer.

Confirmations

These options enable confirmation requests for various operations in the Class and Hierarchy Editors. You can enable confirmations of:

Open output window on message

Lets the IDDE open an error window whenever there is an error of any kind (during compilation, during parsing, and so on.)

Keyboard emulation file

Specifies the key bindings set to be used by the text editor.

Multiple selections

This option enables multiple selections in lists in the Class and Hierarchy editors:
Yes:
Multiple selections are allowed.
No:
Multiple selections are not allowed.
Confirm:
Multiple selections are allowed, but a confirmation request is displayed each time an operation is performed on multiple classes or members.

Class options

The Class options set (Figure 19-14) lets you specify the display order and font of classes in the Classes pane.

[Figure 19-14 Class options

List classes

This option defines how classes are arranged in the Classes pane:
Hierarchically:
Base classes are arranged alphabetically, with derived classes placed below and indented relative to their base classes. If a class has multiple bases, that class is listed below each base class.
Alphabetically:
Classes are arranged in alphabetical order, and each class is listed only once.

Font

Specifies the font used to display class names in the Classes pane. You can select a predefined font from the drop-down list, or you may click on Custom and select any installed font from a Windows Font dialog box.

Apply here only

Indicates that the settings specified here should be applied only to the current Class Editor window.

Member options

The Member options set (Figure 19-15) lets you specify the display parameters of class members in the Members pane.

[Figure 19-15 Member options

Grouping

This option indicates how class members are grouped. Any or all of the following options may be selected:
By access:
Members are grouped into Public, Protected, and Private. If By Access is not selected, each member is preceded by a colored diamond indicating its access specifier (green for public, yellow for protected, red for private).
By file:
Members are grouped by the source file containing their definitions. When this option is selected, only functions and static data are shown.
By kind:
Members are grouped into Data, Functions, and Typedefs. If more than one Grouping option is selected, members are grouped by kind within files, and by files within access category.

Sorting

This option indicates how members are arranged within each group:
Order defined:
Members are arranged in the order they are declared in the class header.
Alphabetical:
Members are arranged alphabetically.

Show full method names

Specifies that member names are displayed with their type specifiers and (if a method) their parameter type list (for example, int Multiply(int, int, int)). If this option is not selected, only the identifier name is displayed (for example, Multiply).

Font

Specifies the font used to display member names in the Members pane. You can select a predefined font from the combo box, or you may click on Custom and select any installed font from a Windows Font dialog box.

Apply here only

Indicates that the settings specified here should be applied only to the current Class Editor window. Otherwise, the settings are applied to all Hierarchy and Class Editor windows.

20. Hierarchy Editor Reference

This chapter describes menu operations and mouse functions available in the Hierarchy Editor. For an introduction to this tool, see Chapter 5, "Defining Classes and Their Hierarchies."

The Hierarchy Editor Window

To open a Hierarchy Editor window you have several choices: Multiple instances of the Hierarchy Editor may be open at the same time. These windows share data among themselves and with Class Editor windows, so changes made in one window are transmitted instantly to the others.

Edit menu commands

Commands in the Edit menu (Figure 20-1) let you undo Hierarchy Editor operations and print the graphical display.

Figure 20-1 Edit menu commands
Figure 20-1 Edit menu commands

Global Undo

Cancels the last operation performed in the Hierarchy Editor (such as Add Class or Add Member). The text of this menu item changes to reflect the previous operation performed in the Hierarchy Editor.

Print

Opens the Print dialog box. See Chapter 21, "Text Editor Reference."

Macro menu commands

The commands in the Macro menu (Figure 20-2) are identical to Macro menu commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

Figure 20-2 Macro menu commands
Figure 20-2 Macro menu commands

New! command

Opens another Hierarchy Editor window.

Pop-up menu commands

Contains commands to add and modify classes and inheritance relationships, and to access Hierarchy Editor options.

Figure 20-3 Hierarchy Editor pop-up menu commands
Figure 20-3 Hierarchy Editor pop-up menu commands

Add Derived

Opens a dialog box (Figure 20-4) that lets you add a new class to the hierarchy. The new class is a derived class of the currently selected class, whose name is shown in the dialog box's title.

Figure 20-4 Create Derived Class dialog box
Figure 20-4 Create Derived Class dialog box

Class name
Specifies a name for the new class.
Header file
Contains the name of the header file into which the class declaration is placed. By default, the first eight characters of the class name (with .h appended) are used as the header file name. You may type an alternative filename into the textbox, or click on Browse to select a filename from the Class Header File dialog box.

Add Top

Adds a top-level (baseless) class. The dialog box that opens as a result of selecting this command is identical in function to the one that opens when you choose the Add Derived command.

Add Sibling

Adds a class that is a sibling of (derived from the same base classes as) the currently selected class. The dialog box that opens as a result of selecting this command is identical in function to the one that opens when you choose the Add Derived command.

Show Header

Opens a new Source window to edit the header file containing the declaration of the currently selected class.

Connect Base

Opens the Add Base dialog box (Figure 20-5), with which you can add a base class to the selected class.

Figure 20-5 Add Base dialog box
Figure 20-5 Add Base dialog box

Access
These options indicate the base class access specifier:
Public:
Public members of the base class are public members of the derived class, and protected members of the base class are protected members of the derived class.
Protected:
Public and protected members of the base class are protected members of the derived class.
Private:
Public and protected members of the base class are private members of the derived class.
Virtual
Specifies the base class to be virtual.
Base class
Specifies the class that is made a base of the selected class. You can select more than one class to make a base class by holding down the Control key while clicking on the class name.

Edit Base Attributes

Opens the Edit Base Attributes dialog box (Figure 20-6), with which you can change the attributes of the selected connection between a derived class and its base class.

Figure 20-6 Edit Base Attributes dialog box
Figure 20-6 Edit Base Attributes dialog box

Access
These options indicate the base class access specifier:
Public:
Public members of the base class are public members of the derived class, and protected members of the base class are protected members of the derived class.
Protected:
Public and protected members of the base class are protected members of the derived class.
Private:
Public and protected members of the base class are private members of the derived class.
Don't change:
Appears only if you are editing the attributes of more than one connection and the base class access specifiers are not all identical. It means that the base class access specifiers are not altered. It lets you change the Virtual specifier of all connections without affecting their individual access specifiers.
Virtual
If selected, this option specifies the base class to be virtual. If grayed, the virtual setting is left unchanged.

Delete Base Connection

Deletes the selected connection between a derived class and its base class.

You are prompted to confirm this if the Confirm Inheritance Changes option on the General page of the Editing/Browsing Settings dialog box is selected.

Settings

Opens the Editing/Browsing Settings dialog box, in which you set global Hierarchy Editor and text editor options. Details of this dialog box are discussed in "Hierarchy Editor Settings," later in this chapter.

Mouse functions

The right mouse button opens the pop-up menu.

A class is selected by clicking on it. Additional classes may be selected by clicking while holding down Control. Members of the class last selected appear in the Members child window.

Double-clicking on a class opens a Class Editor window. A connection is selected by clicking on it. Additional connections may be selected by clicking while holding down Control.

A new derived class is added by clicking on the base class and dragging the cursor to an empty area of the display.

A new base-to-derived connection is made by clicking on the base class and dragging the cursor to the derived class.

A derived class's connection to a base may be moved to a different base by clicking the connection, then dragging the connection's handle to the new base class. (This is a shortcut for deleting one connection, then establishing a new one.)

Toolbar commands

The Hierarchy Editor toolbar (Figure 20-7) offers quick access to several menu choices.

Figure 20-7 Hierarchy Editor toolbar
Figure 20-7 Hierarchy Editor toolbar

The following options are the same as those on other menus:

Add top:
Same as choosing Add Top from the pop-up menu.
Add derived:
Same as choosing Add Derived from the pop-up menu.
Connect base:
Same as choosing Connect Base from the pop-up menu.
Print:
Same as choosing Print from the Edit menu.
Play macro:
Same as choosing Play from the Macro menu.

Members Child Window

The Hierarchy Editor's Members child window is enabled by setting the Members option on the Hierarchy page of the Editing/Browsing Settings dialog box. You can open this dialog box by choosing Settings from the Hierarchy Editor's pop-up menu.

Member menu commands

The Member menu (Figure 20-8) contains commands to add, delete, and modify class members, and to access Hierarchy Editor options.

Figure 20-8 Member menu commands
Figure 20-8 Member menu commands

Add

Opens the Add Member dialog box (Figure 20-9). The new member is added to the class whose members currently are displayed in the Members child window.

Figure 20-9 Add Member dialog box
Figure 20-9 Add Member dialog box

Access
These options specify the member access control:
Public:
Members are accessible from outside the member's class.
Protected:
Members are accessible only within the member's class, derived classes, and their friends.
Private:
Members are accessible only within the member's class and its friends.
Storage
These options specify the member storage class:
Normal:
The member has no storage modifiers.
Static:
Only one copy of the member exists; it is shared by all objects of the member's class.
Virtual (functions only):
The function may be overridden in derived classes.
Pure virtual (functions only):
The function must be overridden in derived classes; the class is abstract.
Friend (functions only):
The named function is allowed access to the class's private members.
Inline
Requests inline implementation of a function.
Declaration
Contains the member declaration. For data items, enter the type and member name (for example, int nCats). For functions, enter the return type, function name, and argument types (for example, void AddCats(int)). Do not precede the declaration with storage specifiers; use the option buttons above. Trailing semicolons are optional.
Source file
Contains the name of the source file into which the member definition is placed. By default, the first eight characters of the class name (with .cpp appended) are used as the source filename. You can type an alternative filename into the textbox, or click on Browse to select an alternative filename from the Member Source File dialog box.

The member declaration is placed in the class declaration. If the specified source file does not already exist, it is created and added to the project. By default, empty definitions of inline functions are placed in the header file. Empty definitions of normal, static, and virtual functions, as well as static data members, are placed in the source file.

Delete

Deletes the currently selected member. If the Confirm Member Delete option on the General page of the Editing/Browsing Settings dialog box is selected, you are asked to confirm the deletion. The member's declaration and definition (if applicable) are removed from the header and source files.

Edit Attributes

This command opens the Change Member Attributes dialog box (Figure 20-10), which you can use to edit access and storage specifiers of the selected member.

Figure 20-10 Change Member Attributes dialog box
Figure 20-10 Change Member Attributes dialog box

Access
These options specify the member access control:
Public:
Members are accessible from outside the member's class.
Protected:
Members are accessible only within the member's class, derived classes, and their friends.
Private:
Members are accessible only within the member's class and its friends.
Don't change:
Appears only if you are editing the attributes of more than one member and their access controls are not all identical. It means that the access control is not altered. It lets you change other member attributes without also affecting their individual access controls.
Storage
These options specify the member storage class:
Normal:
The member has no storage modifiers.
Static:
Only one copy of the member exists; it is shared by all objects of the member's class.
Virtual (functions only):
The function may be overridden in derived classes.
Pure virtual (functions only):
The function must be overridden; the class is abstract.
Friend (functions only):
The named function is allowed access to the class's protected and private members.
Don't change:
Appears only if you are editing the attributes of more than one member and their storage classes are not all identical. It means that the storage class is not altered. It lets you change other member attributes without affecting their individual storage classes.
Inline
Requests inline implementation of a function. If grayed, the current setting is left unchanged.
Source file
If applicable, this option contains the name of the source file holding the member definition. You may change the filename in the textbox, or click on Browse to select an alternative filename from the Member Source File dialog box. If you change the source file, the member definition moves.

Show Source

Opens a new Source window to show the source file containing the definition of the currently selected member.

If you add new functions or static data definitions to the source file, or alter function argument or return types, you must update the class header to reflect the changes.

Settings

Opens the Editing/Browsing Settings dialog box, in which you set global Hierarchy Editor and text editor options. Details of this dialog box are discussed in "Hierarchy Editor Settings," later in this chapter.

Pop-up menu commands

The Members child window pop-up menu is identical to the Member menu.

Mouse functions

The right mouse button opens the pop-up menu.

Select a member by clicking on it. Additional members may be selected by clicking on them while holding down Control.

Double-clicking on a member causes its definition (if appropriate) or declaration to be displayed in the Source child window.

You may drag and drop a member into the Source child window; the member declaration is inserted into the buffer.

Source Child Window

The Hierarchy Editor's Source child window is enabled by setting the Source option on the Hierarchy page of the Editing/Browsing Settings dialog box. You can open this dialog box by choosing Settings from the Hierarchy Editor's pop-up menu.

Edit menu commands

Commands in the Edit menu (Figure 20-11) are used to perform text editing operations, and are identical to the corresponding Edit menu commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

Figure 20-11 Edit menu commands
Figure 20-11 Edit menu commands

Goto menu commands

The commands in the Goto menu (Figure 20-12) are used to move around within the Source child window and are identical to the corresponding Goto menu commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

Figure 20-12 Goto menu commands
Figure 20-12 Goto menu commands

Pop-up menu commands

With one exception, commands in the Source child window pop-up menu (Figure 20-13) are identical to the corresponding commands in Source windows. For a description, see Chapter 21, "Text Editor Reference."

Figure 20-13 Pop-up menu commands
Figure 20-13 Pop-up menu commands

Save

Saves the program code shown in the Source child window and places it in the appropriate source or header file.

Changes to static data and to function argument and return types made in the source code are updated automatically in the class declaration and Members child window.

Mouse functions

The right mouse button opens the pop-up menu.

The Source child window supports typical source window mouse and cursor operations, as described in Chapter 21, "Text Editor Reference."

Hierarchy Editor Settings

You can access Hierarchy Editor settings by choosing Settings from the Hierarchy Editor pop-up menu, Settings from the Members child window Member or pop-up menus, or Text Settings from the Source child window Edit menu. These commands open the Editing/Browsing Settings dialog box, a workspace with tabs along the top margin.

The tabs are used to switch between several sets of options. The Hierarchy, Member, and General options are discussed in this section; the remaining options pertain to text editing and are discussed in Chapter 21, "Text Editor Reference."

General options

The General options set (Figure 20-14) contains options for undo levels and confirmations, as well as options related to the text editor.

Figure 20-14 General options
Figure 20-14 General options

Browser operations

Specifies the number of operations that can be undone in the Class and Hierarchy Editors.

Text edits, per buffer

Specifies the number of edit operations that can be undone per buffer.

Confirmations

These options enable confirmation requests for various operations in the Class and Hierarchy Editors. You can enable confirmations of:

Open output window on message

Lets the IDDE open an error window whenever there is an error of any kind (during compilation, during parsing, and so on.)

Keyboard emulation file

Specifies the key bindings set to be used by the text editor.

Multiple selections

Enables multiple selections in lists in the Class and Hierarchy editors.
Yes:
Multiple selections are allowed.
No:
Multiple selections are not allowed.
Confirm:
Multiple selections are allowed, but a confirmation request is displayed each time an operation is performed on multiple classes or members.

Hierarchy options

The Hierarchy options set (Figure 20-15) lets you enable the Members and Source child windows and specify the font used in the graphical display.

Figure 20-15 Hierarchy options
Figure 20-15 Hierarchy options

Pop-up windows

These options enable the Hierarchy Editor child windows:
Members:
Enables the Members child window.
Source:
Enables the Source child window.

Font

Specifies the font used to display class names. You can select a predefined font from the drop-down list, or you can click on Custom and select any installed font from a Windows Font dialog box.

Apply here only

Indicates that the specified settings should be applied only to the current Hierarchy Editor window.

Member options

Lets you specify the display parameters of class members in the Members child window.

Figure 20-16 Member options
Figure 20-16 Member options

Grouping

Indicates how class members are grouped. Any or all of the following options may be checked:
By access:
Members are grouped into public, protected, and private. If By Access is not selected, each member is preceded by a colored diamond indicating its access specifier (green for public, yellow for protected, red for private).
By file:
Members are grouped by the source file containing their definitions. When this option is selected, only functions and static data are shown.
By kind:
Members are grouped into Data, Functions, and Typedefs.
If more than one Grouping option is selected, members are grouped by kind within files and by files within access category.

Sorting

Indicates how members are arranged within each group.
Order defined:
Members are arranged in the order in which they are declared in the class header.
Alphabetical:
Members are arranged alphabetically.

Show full method names

Specifies that member names are displayed with their type specifiers and (if a method) their parameter type list (for example, int Multiply(int, int, int)). If this option is not selected, only the identifier name is displayed (for example, Multiply).

Font

Specifies the font used to display member names in the Members child window. You can select a predefined font from the combobox, or you can click on Custom and select any installed font from a Windows Font dialog box.

Apply here only

Indicates that the specified settings should be applied only to the current Hierarchy Editor window. Otherwise, the settings are applied to all Hierarchy and Class Editor windows.

21. Text Editor Reference

This chapter describes commands and options available in the text editor, including global search functions, key binding options, and macro functions. For an introduction to text editing, see Chapter 6, Editing Program Code.

The Source Window

To open a Source window, you have several choices: The Hierarchy Editor's Source child window, as well as the Source pane of the Class Editor, contain a subset of the standard Source window functionality. See Chapter 5, Defining Classes and Their Hierarchies, Chapter 19, Class Editor Reference, and Chapter 20, Hierarchy Editor Reference.

File menu commands

The File menu (Figure 21-1) contains commands to open, save, and print files, as well as other useful file-related commands. Note that the Save and Add to Project command changes to Add to Project, Save and Parse, or Parse, depending on whether the file is part of the project, up to date, or parsed.

[Figure 21-1 File menu commands

New

Opens a new, empty, and untitled Source window.

Open

Opens a Windows File Open dialog box, then creates a new Source window containing the selected file. If the Open command is chosen from an untitled, unmodified Source window, the selected file is opened in that Source window.

Load

Opens a Windows File Open dialog box, then loads the selected file into the current Source window. If there are unsaved changes in the previous file, you are asked if you would like to save the changes before loading the new file.

Close

Closes the Source window. If there are unsaved changes, you are asked if you would like to save the changes before closing the file.

Save

Saves the current buffer to disk. If the file is untitled, this command executes Save As.

Save as

Saves the current buffer using the Windows File Save As dialog box. This dialog box contains a check box- Add to Project, which lets you add the file to the current project.

Save All

Executes Save for every open Source window.

Compile

Saves the buffer and compiles the file.

Save and Add to Project

Saves the file to disk, adds the file to the project, and reparses all files in the project.

The Save and Add to Project command changes to Add to Project, Save and Parse, or Parse, depending on whether the file is part of the project, up to date, or parsed. These are the four changes:

  1. A new source file is created but not saved, or flagged as modified since the last save. The menu reads "Save and Add to Project."
  2. A source file which has not been added to the project is saved. The menu reads "Add to Project."
  3. A source file which exists in a project is loaded in the source editor. The menu reads "Parse."
  4. A source file exists in a project and has been flagged or modified. The menu read "Save and Parse."

Add to Project

Adds the file to the project and reparses all files in the project.

Save and Parse

Saves the file to disk and reparses all files in the project.

Parse

Reparses all files in the project.

Compare

Opens the Compare Files dialog box (Figure 21-2), which lets you select two files to compare.

[Figure 21-2 Compare Files dialog box

File 1 and File 2
Specifies the files to be compared. You may type the file names, select names from the drop-down lists, or click on Browse to select files from standard Windows filename dialog boxes.

If either file is open in a Source window, the editor uses the version in memory rather than the one in the disk file.

Line
Specifies the line number at which the comparison starts.
Display
Specifies the arrangement of the windows in which the two files are displayed:
Horizontal:
The files are displayed one above the other.
Vertical:
The files are displayed side-by-side. The editor performs the comparison on a line-by-line basis. When it finds a mismatch, it highlights the appropriate lines in both files. The Compare dialog box (Figure 21-3) indicates where the mismatch was found.

[Figure 21-3 Compare dialog box showing mismatch

Next match:
Click on this button to resynchronize the comparison. The editor highlights the next set of matching lines and the Compare dialog box indicates where the match occurs.

[Figure 21-4 Compare dialog box showing match

Next difference:
Click on this button to find the next mismatched line. You can continue the comparison in this way until no more differences are found.

Insert

Opens an Insert File dialog box. The editor inserts the contents of the file you select at the current insertion point.

Revert

Rereads the file from disk, abandoning any changes made since the last time it was saved.

Page Setup

Opens the Page Setup dialog box (Figure 21-5), which sets parameters for printing.

[Figure 21-5 Page Setup dialog box

Header and footer
The header and footer are single lines of text displayed at the top and bottom (respectively) of each page of the printed output. To omit the header or footer, leave the textbox empty.

You can embed the following special-purpose codes in the header and footer text:

Margins
Sets the page margins. The units are the standard units of measurement used in your country (inches or centimeters), set in the Windows Control Panel.
Font
Opens a Windows Font dialog box, with which you select a typeface, style, and size for the printed output. The entire document, including headers and footers, is shown in the selected font.
Printer
Opens a Windows Print Setup dialog box, with which you can set additional printing parameters.

Print

Opens the Text Print dialog box (Figure 21-6), to let you set additional print options and print the current file or text selection. After setting print options, click OK to print.

[Figure 21-6 Text Print dialog box

Print range
Specifies whether the entire file or just the current text selection is printed:
All:
Prints the entire file.
Selection:
Prints the highlighted text selection. (It is disabled if no text is selected.)
Print quality
This drop-down listbox specifies print quality. Options include the specified printer's output capabilities, expressed in dots per inch.
Copies
Specifies the number of copies to print.
Setup
Opens a Windows Print Setup dialog box, with which you can set additional printing parameters.

Edit menu commands

The Edit menu (Figure 21-7) contains standard edit and search commands, as well as commands to access text editor options.

[Figure 21-7 Edit menu commands

Undo

Reverses the last cut, paste, replace, or typed character. By repeatedly choosing this command, you can undo previous commands, up to the limit of the undo buffer.

Cut

Copies the selected text to the Clipboard, then deletes it from the buffer.

Copy

Copies the selected text to the Clipboard.

Paste

Inserts the text from the Clipboard at the insertion point.

Delete

Deletes the selected text from the buffer.

Find

Opens the Find dialog box (Figure 21-8), used to search the file for specified text.

[Figure 21-8 Find dialog box

Pattern
This drop-down listbox contains the text to be found.

You can initialize the pattern by selecting the text before choosing Find. (The text must not span a line break.) Otherwise, you may type the text you want to find into the textbox, or select text from previous search strings, stored in the drop-down listbox.

The pattern may also be a regular expression (text containing wildcard characters) if the Regular Expression option is selected. Regular expression syntax is discussed in "Using Global Find," later in this chapter.

Ignore case
If this option is turned on, the search is not case sensitive.
Whole words only
If this option is turned on, a string is considered a match only if it is not part of a larger alphanumeric string.
Regular expression
This option enables regular expression matching.

The search begins at the current insertion point. Click Next to search forward in the file, or Previous to search backward in the file. If the search is successful, the matching text is highlighted. Otherwise, the status line displays the message "Pattern not found."

Repeat Find

Continues the search begun by Find. The search resumes from the current insertion point and proceeds in the direction previously specified.

If the search is successful, the matching text is highlighted. Otherwise, the status line displays the message "Pattern not found."

Find Previous

Searches backward from the current insertion point for the text to be found.

Find Next

Searches forward from the current insertion point for the text to be found.

Replace

Opens the Replace dialog box (Figure 21-9), which lets you find and replace occurrences of text with different text.

[Figure 21-9 Replace dialog box

Pattern
This drop-down listbox contains the text to be found and replaced.

You can initialize the pattern by selecting text before choosing Replace. (The text must not span a line break.) Otherwise, you may type the text you want to find into the textbox, or select text from previous search strings, stored in the drop-down listbox.

The pattern may also be a regular expression (text containing wildcard characters) if the Regular Expressions option is selected. Regular expression syntax is discussed in the section "Using Global Find," later in this chapter.

Replacement
This drop-down listbox contains the text with which you replace occurrences of Pattern. Type the replacement text into the textbox, or select text from previous replacement strings, stored in the drop-down listbox.
Ignore case
If this option is turned on, the search is not case sensitive.
Regular expressions
Enables regular expression matching.
Confirm changes
Causes the text editor to request confirmation before each replacement. If this option is not selected, the editor replaces all occurrences of Pattern, starting at the current insertion point, without prompting you.
Restrict changes to selected text
Instructs the text editor to perform replacements only within the selected block of text.
Whole words only
If selected, the text editor considers text a match only if it is not part of a larger alphanumeric string.

The search/replace operation begins at the current insertion point. If you have selected Confirm Changes, the Confirm Replacement dialog box (Figure 21-10) is displayed when a match is found.

[Figure 21-10 Confirm Replacement dialog box

You may click Yes to make the replacement, No to skip this replacement, or Cancel to end the search/replace operation. Also, if you uncheck Confirm, then click Yes, the editor replaces all remaining occurrences of Pattern without prompting you.

Global Find

Opens the Global Find dialog box. See "Using Global Find," later in this chapter.

Current Buffer Settings

Opens the Current Buffer Options dialog box (Figure 21-11), with which you can change editing options for the current Source window.

[Figure 21-11 Current Buffer Options dialog box

Tab spacing
Specifies the number of columns between tab stops.
Right margin
Specifies the column that acts as the right margin.
Word wrap
Enables word wrap. While typing, lines extending beyond the right margin are broken automatically at the last word boundary before the margin.
Autoindent
Enables automatic indentation on newline. When you press Enter, the editor positions the cursor directly below the first nonblank character in the previous line.
Read only
Sets the read-only flag on the buffer, so the buffer may not be changed.
Use as default for ...
Saves the Current Buffer Options settings so they become the defaults for any subsequent file with the same file extension that is loaded. For example, if the file that is currently open is "test. cpp," the check box reads, "Use as default for .cpp." If this is an untitled buffer, the check box is disabled.
Expand tabs with spaces
Tabs are inserted into the text as an appropriate number of spaces rather than as tab characters.
C++ mode
The buffer is treated as C++ code. Special options for C++ code are set in the Editing/Browsing Settings dialog box.
Persistent
Causes the buffer options for this file to be saved during the current IDDE session, even if the file is closed. Otherwise, buffer options are set to their global defaults if a file is closed and reopened.

Text Setting

Opens the Editing/Browsing Settings dialog box, in which you set global text editing options. Details of this dialog box are discussed in the "Text Settings" section later in this chapter.

Goto menu commands

The Goto menu (Figure 21-12) contains commands to move within the source file.

[Figure 21-12 Goto menu commands

Line

Opens the Goto Line dialog box (Figure 21-13). Type the line number and click OK, and the insertion point is moved to the specified line.

[Figure 21-13 Goto Line dialog box

Function

Opens the Goto Function dialog box (Figure 21-14).

[Figure 21-14 Goto Function dialog box

The Function Name listbox holds the available function names. Either type in the function name or scroll and select the function name from the list. When you click OK, the insertion point moves to the beginning of the specified function.

Member functions in the list typically are displayed as member::class. To change the format to class::member, deselect the Reverse Class::Member Format option.

Matching Delimiter

Finds the delimiter that matches the one to the right of the current insertion point. The insertion point is moved to the front of the matching delimiter. This command can find matching parentheses, square brackets, or braces.

Bookmark

Opens the Bookmarks dialog box (Figure 21-15), which you can use to set and move to as many as ten different locations in your source files. Bookmarks are saved through the current IDDE session only.

[Figure 21-15 Bookmarks dialog box

Bookmark list
Shows the locations of the ten bookmarks by file, line, and column. Click on an entry to select it; double-click on an entry to go to it.
Goto
Moves the insertion point to the selected bookmark. This command opens a file if it is not already open. You can also double-click on the bookmark in the list.
Clear
Removes the selected bookmark.
Drop
Sets the selected bookmark to the current insertion point. The entry in the bookmark list is updated to show the file, line, and column.

Buffer

Opens the Edit Buffers dialog box (Figure 21-16). This dialog box presents a list of files currently open in Source windows; it allows you to view and change each buffer's editing options and to perform various file-related operations.

[Figure 21-16 Edit Buffers dialog box

Context
This drop-down listbox specifies File Buffers or Member Buffers. File Buffers are Source windows open to edit an entire file. Member Buffers are Class Editor Source panes and Hierarchy Editor Source child windows, open to edit a particular member definition.
Buffer list
Contains the names of files currently open in Source windows (or, if the Member Buffers context is selected, the names of member functions open in Class Editor Source panes and Hierarchy Editor Source child windows). Click on a filename to select it; double-click on it to bring the corresponding Source window to the front.
Buffer properties
Lets you view and set options for each individual buffer listed in the buffer list.
Tab spacing:
Specifies the number of columns between tab stops.
Right margin:
Specifies the column that acts as the right margin.
Word wrap:
Enables word wrap. While typing, lines that extend beyond the right margin are broken automatically at the last word boundary before the margin.
Autoindent:
Causes the text editor to indent automatically on newline. When you press Enter, the editor positions the cursor directly below the first nonblank character in the previous line.
Read only:
The buffer may not be changed.
Use as default for ...:
Saves the Current Buffer Options settings as the defaults for any subsequent file with the same file extension that is loaded. For example, if the currently open file is test.cpp, the check box reads, "Use as default for .cpp." If the currently open file is test.txt, the check box reads, "Use as default for .txt." If the currently open file has no extension, the check box reads, "Use as default." If this is an untitled buffer, the check box is disabled.
Expand tabs with spaces:
Tabs are inserted into the text as an appropriate number of spaces, rather than as tab characters.
C++ mode:
Text is treated as C++ code. Special options for C++ code are set in the Editing/Browsing Settings dialog box (see "Text Settings," later in this chapter).
Persistent:
Causes the buffer options for this file to be saved during the current IDDE session, even if the file is closed. Otherwise, buffer options are set to their global defaults if a file is closed and reopened.
Switch to
Brings the Source window containing the file selected in the listbox to the front.
Open
Opens a Windows File Open dialog box, with which you can select a file to open for editing.
Save
Saves the file selected in the listbox. If the file is untitled, this command executes Save As.
Save all
Saves all files in the listbox.
Save as
Opens a Windows File Save As dialog box, with which you can save the file selected in the listbox under a new name.
Close
Closes the file selected in the listbox.
Close all
Closes all files in the listbox.
Find
Opens the Global Find dialog box (see "Using Global Find," later in this chapter).

Macro menu commands

The Macro menu (Figure 21-17) allows you to record, play, and edit macros.

[Figure 21-17 Macro menu commands

Record Macro

Starts the recording of the default macro. While a macro is being recorded, this menu choice is replaced in the menu by Stop Recording. Menu and keystroke recording is limited to the current source window only. To record a macro:
  1. Choose Record Macro. If a default macro exists, you are asked to confirm that you want to record over the default macro. Click OK.
  2. Enter the sequence of keystrokes and menu selections you want to record.
  3. Choose Stop Recording to end the macro.

Play Macro

Plays back the default macro.

ScriptMaker

Opens the ScriptMaker dialog box (Figure 21-18), with which you copy, name, and edit macros.

[Figure 21-18 ScriptMaker dialog box

Existing macros
This is the list of macros. Click on a macro to select it; double-click on the macro to edit it.
Menu order
These buttons allow you to change the order of the macros listed in the Macro menu. Click on the Up Arrow to move the selected macro up in the menu; click on the Down Arrow to move it down in the menu. The default macro always remains at the top of the list.
Put in menu
Causes the selected macro to be listed in the Macro menu.
Edit
Opens the Macro Editor window. For information about the macro language and the Macro Editor window, see the Digital Mars C++ IDDE Help.
Rename
Opens the Rename/Clone Script dialog box (Figure 21-19), with which you can change the selected macro's menu name or filename.

[Figure 21-19 Rename/Clone Script dialog box

Menu name:
Name under which this macro is listed in the Macro menu.
File name:
Name of the file in which the macro is saved. You can change either or both names. Note that you cannot rename the default macro.
Clone
This button opens the Rename/Clone Script dialog box. This command makes a copy of the selected macro.
Menu name:
Name under which this macro is listed in the Macro menu.
File name:
Name of the file in which the macro is saved. When cloning, this filename must be different from that of any other macro.
Note: To create a new macro, first use the Record Macro command to record it as the default macro. Then choose Scriptmaker and use Clone to make a copy of the default macro under a new name.
Delete
Deletes the selected macro.

New! command

Opens another Source window on the current file.

Changes made to a file in one Source window are made automatically in other Source windows containing the same file.

Pop-up menu commands

The pop-up menu (Figure 21-20) is opened by clicking the right mouse button in the edit area of the Source window.

[Figure 21-20 Source window pop-up menu commands

Copy

Copies the selected text to the Clipboard.

Cut

Copies the selected text to the Clipboard, then deletes it from the buffer.

Paste

Inserts the text from the Clipboard at the insertion point.

Delete

Deletes the selected text from the buffer.

Query Implementors

Interprets the tokens or symbols surrounding the insertion point as a C++ class member name and locates all classes with a member of this name. The results are displayed in the Members window (Figure 21-21).

[Figure 21-21 Members window

For example, if the token is Test, Query Implementors shows a list of all implementors of Test, such as One::Test.

In the Members window, you can select an implementor and choose Show Source from the Member menu to open a Source window to the corresponding source code or, double-click an implementor to open a Class Editor window to the member source. Note that if only one implementor of a token is found, the Query Implementors command opens the Class Editor window directly, without first opening the Members window.

Select

Opens the Select submenu (Figure 21-22).

[Figure 21-22 Select submenu commands

Normal

Restores the original text select block to normal mode, undoing changes caused by Column and Line (see the following).

Column

Changes the text selection block to a column-oriented select block, in which only the characters in the columns between the start and end of the original text block are selected.

Line

Changes the text selection block to a line-oriented select block, in which all characters in the lines between the start and end of the original text block are selected.

Cancel

Deselects the current select block.

Format Text

Opens the Format Text submenu (Figure 21-23).

[Figure 21-23 Format Text submenu commands

Indent Block

Indents all nonblank lines in the selected text by one tab stop. Tabs are inserted as tab characters or as spaces, depending on the current buffer option settings. All text in a region will be indented if a region is selected upon issuing the command.

Unindent Block

Unindents all lines in the selected text by one tab stop. All text in a region will be unindented if a region is selected upon issuing the command.

Upper Case

Changes all alphabetic characters in the selected text to uppercase.

Lower Case

Changes all alphabetic characters in the selected text to lowercase.

Tabs to Spaces

Changes all tab characters in the selected text to spaces. The number of spaces used to replace each tab character depends on the Tab spacing option.

Spaces to Tabs

Changes spaces in the selected text to tab characters. The number of spaces used to create each tab character depends on the Tab spacing option.

Write Block

Opens a Write Block dialog box. Select a file or type a new name; the editor writes the currently selected text block to this file. To append the selection block to a file, check Append.

Save

Saves the current buffer to disk. If the file is untitled, this command executes Save As.

Toolbar commands

The Source window toolbar (Figure 21-24) offers quick access to several menu choices.

[Figure 21-24 Source window toolbar

New:
Same as choosing New from the File menu.
Open:
Same as choosing Open from the File menu.
Save:
Same as choosing Save from the File menu.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
Print:
Same as choosing Print from the File menu.
Find:
Same as choosing Find from the Edit menu.
Find previous:
Searches backward in the file for the search string.
Find next:
Searches forward in the file for the search string.
Play macro:
Same as choosing Play Macro from the Macro menu.
Note: The Find previous and Find next buttons are subtly different from Find Again in the Edit menu, which can only repeat the search in the original direction.

Text Settings

Choosing Text Settings from the Source window's Edit menu opens the Editing/Browsing Settings dialog box, a workspace with tabs along the top margin. The tabs are used to switch between several sets of options. Each set of options is described below.

General options

The General options set (Figure 21-25) contains options for undo levels and the key binding file, as well as some options related to the Class and Hierarchy Editors.

[Figure 21-25 General options

Browser operations

Specifies the number of operations that can be undone in the Class and Hierarchy Editors. See Chapter 19, Class Editor Reference, and Chapter 20, Hierarchy Editor Reference.

Text edits, per buffer

Specifies the number of edit operations that can be undone per buffer.

Confirmations

Enables confirmation requests for various operations in the Class and Hierarchy Editors. See Chapter 19, Class Editor Reference, and Chapter 20, Hierarchy Editor Reference.

Open output window on message

Lets the IDDE open an error window whenever there is an error of any kind (during compilation, during parsing, and so on.)

Keyboard emulation file

Specifies the key bindings set to be used. Key bindings allow you to associate keystroke sequences with functions and macros. Information about key bindings sets can be found in the Digital Mars C++ IDDE Help.

Multiple selections

Enables multiple selections in lists in the Class and Hierarchy editors. See Chapter 19, Class Editor Reference, and Chapter 20, Hierarchy Editor Reference.

Text options

The Text options set (Figure 21-26) contains options for indentation, cursor styles, keyboard emulation, and text editor font.

[Figure 21-26 Text options

Tab spacing

Specifies the default for the number of columns between tab stops. This value may be overridden locally in each buffer.

Right margin

Specifies the default for the column that acts as the right margin. This value may be overridden locally in each buffer.

Autoindent

Indents automatically on newline. When you press Enter, the editor positions the cursor directly below the first nonblank character in the previous line. This option may be overridden locally in each buffer.

Expand tabs with spaces

Tabs are inserted into the text as an appropriate number of spaces, rather than as tab characters. This option may be overridden locally in each buffer.

Show horizontal scroll bar

Enables the horizontal scroll bar at the bottom of the Source window.

Remove trailing spaces on save

Trailing spaces and Tabs are removed from the end of each line when a file is saved.

Cursor styles

Specifies caret style. You may set styles individually for the caret in Insert and Overwrite modes. Styles are:
Block:
The current character is displayed in inverse video.
Underline:
The current character is underlined.
Vertical bar:
A vertical bar appears to the left of the current character.
Blink:
The cursor blinks. The blink rate is specified in the Windows Control Panel.

Font

Specifies the text font. You can select a predefined font from the drop-down list, or you can click Custom and select any installed font from a Windows Font dialog box.

Brief-compatible select

If you choose this option, then enter the "Toggle Mode Select" mode. The editor remains in selection mode when you use the arrow keys.

Typing replaces selection

Enables the Windows standard convention of replacing selected text with any typed character or pasted text. If this option is not selected, typing or pasting inserts the text to the left of the current selection.

Cut/copy line without selection

If no text is selected, Cut and Copy, respectively, cut and copy the current line. If text is selected, Cut and Copy work as usual.

If this option is not selected, Cut and Copy have no effect if no text is selected.

Normal selection for debugging

Enables normal selection of text when in debugging mode. If disabled, you can drag from the source window to the Assembly, Data/Object, and Function windows while debugging.

Virtual cursor

Enables virtual cursor mode, in which you can position the caret anywhere in the window, regardless of line endings. Note that even with this option enabled, you still cannot position the caret beyond the last line in the file.

Enable menu accelerators

Enables menu accelerator keys. With this option selected, new windows have underscores beneath the top-level menu items to show the Alt key combination you can use to access the menu.

Help Files

Clicking on Help Files opens the Text Help File Configuration dialog box, as shown in Figure 21-27.

[Figure 21-27 Text Help File Configuration dialog box

This dialog box lets you associate particular Windows Help files with each of the four Text Help commands. The Text Help commands are run by key sequences such as Shift+F1. (The exact mapping of key sequences to Text Help commands depends on the current key mapping. See "Keys options," later in this chapter.) The Text Help commands call the Windows API function Windows Help, passing it the name of a Windows Help file and (optionally) a keyword. The Text Help commands are useful, for example, for gaining access to help on a particular API function or MFC class directly from the source code.

Text Help Command:
Specifies a Text Help command (TextHelp1, TextHelp2, TextHelp3, TextHelp4).
Help File:
Specifies the Windows Help file to be associated with the selected Text Help command. This filename is passed to Windows Help when the Text Help command is run.
Grab Token At Insertion Point:
If this box is checked, the Text Help commands pass the token at the insertion point in the text buffer to Windows Help as a keyword. This causes Windows Help to search for the associated topic, and, if found, to immediately display help on the keyword topic.

C++ options

The C++ options set (Figure 21-28) contains options to check delimiters, indent after braces, and auto-align comments. It also allows you to add custom keywords to the keyword dictionary.

[Figure 21-28 C++ options

Check delimiters

If you type a right parenthesis, square bracket, or brace, the editor briefly highlights the corresponding left delimiter. If no matching delimiter is found, an error message is displayed.

Enable C++ mode

This option enables C++ mode globally. If it is not selected, C++ mode features are disabled for all buffers, regardless of local buffer option settings.

Enable C++ mode for untitled files

When this option is on, new files that have not yet been given a name are assumed to be C/C++ source. This box should be checked in most circumstances, so that keywords can be recognized in new files, for example.

Indent after {

If the last character typed on a line is a left brace, the next line is indented automatically by an extra tab stop. This option works only if Autoindent is enabled in the buffer. Also, if the first character on a line is a right brace (}), the line is unindented automatically; this is independent of the Autoindent option.

Auto-align comments at column

If this option is enabled, when you type // to start a C++ comment, the editor automatically indents the comment to a specified alignment column. You can specify the alignment column in the adjacent textbox.

Enable C++ mode on extensions

Specifies the file extensions for which C++ mode is automatically enabled. Type the extensions into the textbox, separated by spaces.

Custom keywords

You can maintain a set of custom keywords that are highlighted in the edit window in a manner you specify (see "Display options," later in this chapter).

To add a new keyword, type the keyword into the textbox and click on Add. To remove a keyword from the list, click on the keyword in the list and click on Remove.

Keys options

The Keys options set (Figure 21-29) lets you customize key bindings and assign key combinations to macros.

[Figure 21-29 Keys options

A Key Bindings file (.key) associates keystroke sequences with editor commands and user-defined macros. You can select the particular key binding set you want to use either with the Key File option below, or with the Keyboard Emulation file option under the General tab (see General options, earlier in this section).

Commands are grouped into functional categories. The groups are:

Global:
Global commands, used anywhere (includes all user-defined macros)
Member:
Member-related commands, used in the Class and Hierarchy Editors
Text:
Text editor functions and commands, used in Source windows
Class:
Class-related commands, used in the Class and Hierarchy Editors
Project:
Project-related commands, used in the Project window
You may assign more than one keystroke sequence to a command. However, within a category, only one command may be associated with a particular keystroke sequence.

Key file

Specifies the key bindings set to be used. Select a keyboard emulation file from the drop-down list.

Keys

Specifies a key sequence. This is not an ordinary textbox; it can display any keystroke sequence.

There are two ways to enter a keystroke sequence into the textbox:

Commands/macros

The textbox displays the currently selected command (or macro). You can type in the command name or select a command from the list by clicking on it.

The list displays commands and associated key sequences. If more than one sequence is assigned to a command, it is listed as many times as necessary. The content and sorting of the list is determined by the Commands/Macros List Options.

Commands/macros list options

Determine the filtering and sorting of commands and macros shown in the Commands/Macros list.
Scope:
Displays commands only in the specified functional category. Categories are Global, Member, Text, Class, and Project. Specify All to see all commands.
Show bound keys only:
Shows only those commands with an associated keystroke sequence.
Sort by command:
Displays the list alphabetically by command. If this option is not selected, the list is ordered by key sequence.
Copy to clipboard:
Copies the current contents of the commands/ macros list to the Clipboard.

Assign

Assigns the keystroke sequence to the selected command.

If another command in the same functional category is already bound to this keystroke sequence, you are asked if you want to reassign the sequence to the new command.

Unassign

Dissociates the selected command from its keystroke sequence.

Save as

Saves the key bindings to a new file. When prompted, type the name of the new file, or select a file from the drop-down list.

Display options

The Display options set (Figure 21-30) lets you select special font colors and styles for keywords, comments, preprocessor symbols, and other special text.

[Figure 21-30 Display options

Source code display

Allows you to customize syntax highlighting. You can specify the highlighting for:
Comments:
C/C++ comments
Custom keywords:
Special keywords you specify. (See "C++ options," earlier in this chapter.)
Keywords:
C/C++ keywords
Current line:
The line containing the insert point
Preprocessor:
C/C++ preprocessor directives
Error highlight:
Lines on which compiler errors were found
Select Color and Font Style from the drop-down lists next to each item. (If you select the first color, which is labeled "none," the default text color is used for that item.)

Selection/highlight color

Specifies the text and background color of selected text.

Execution line color

Specifies the text and background color of the current execution line during debugging.

Backup options

The Backup options set (Figure 21-31) contains options for backing up files.

[Figure 21-31 Backup options

Autosave

Causes the editor to save your work automatically after a certain number of changes, or after a certain number of minutes since the last save. Specify the number of changes or minutes in the textbox, and select changes or minutes from the drop-down list.

Backup on file save

This enables automatic backup on save. You must also select the backup method:
Create .bak File:
Copies the previous saved version to file with the extension .bak.
Copy to backup directory:
Copies the previously saved version to another directory. Type the directory into the textbox, or click on Browse to select a directory from a Directory dialog box.
Invoke OnBackup script:
Runs a macro called OnBackup.
Note: The Autosave option also provides some protection against data loss in the event of a system crash. When you check Autosave, the editor saves the contents of each modified buffer to a temporary file on disk. If the editor does not exit normally (as with a crash), these files (named ~num.sav, where num is a unique number) will not be deleted. Line 1 of a .sav file specifies the drive, directory, name, and extension of the buffered file, also with the data and time it was last saved. The rest of the file stores the contents of the buffer, which you may be able to recover; use the editor's Save As option to save the .sav file as a source file.

Using Global Find

Global Find is a multi-file search facility. You specify the files to be searched and the string or regular expression to be searched for. Global Find presents a list of files in which a match was found and allows you to view and edit the files, add files to the project, or refine the search criteria and search again.

Defining the search

You open the Global Find dialog box (Figure 21-32) by choosing Global Find from a Source window's Edit menu, choosing Global Find from the IDDE's Tools menu, or clicking on the Find button in the Edit Buffers dialog box.

[Figure 21-32 Global Find dialog box

The Global Find dialog box has two sections. The upper section specifies the files to be searched, and the lower section specifies the pattern to be searched for.

Search Files...

Three options are available for specifying the files to be searched.
In the current project
All files in the current project are searched.
Currently listed in global search results window
Enabled only after an initial global search has been performed. It limits the search to files in which a match was found in the previous global search.
Matching the criteria
Specify files by filename patterns, directory, date, time, and attributes.
File names:
Comma-separated list of filenames and patterns. To search all files, use *.*.
Directory:
Search files in the specified directory. You can click on Browse to select a directory from the Choose Directory dialog box. Check Include Subdirectories to search files in subdirectories as well.
Date:
Select Ignore to ignore the date. Otherwise, specify a date and one of the relational options. For example, specify On and 11/6/94 to search files last modified on November 6, 1994, or After 4/1/90 and to search files last modified after April 1, 1990.
Time:
Select Ignore to ignore the time. Otherwise, specify a time and one of the relational options.
Attributes:
Search files with the given attributes. File attributes are Archive, Read Only, System, and Hidden.

The Attributes check boxes are three-state check boxes:

checked
files with the given attribute are searched.
cleared
files without the given attribute are searched.
grayed
the attribute is ignored when deciding which files to search.

For...

Type the pattern to search for into the textbox. These options modify the search:
Ignore case
Do not consider case when searching for a match.
Whole words only
Consider text a match only if it is not part of a larger alphanumeric string.
Regular expression
Enables regular expression matching. A regular expression is a string with wildcards, which are:
? Matches any character.
* Matches zero or more occurrences of any character.
@ Matches zero or more occurrences of the previous character or expression. For example, Ax@B matches AB, AxB, AxxB, and so on.
% Matches the beginning of a line. For example, %{ finds lines that start with left braces.
< Matches the beginning of a line. For example, <{ finds lines that start with left braces.
$ Matches the end of a line. For example, $ finds blank lines.
> Matches the end of a line. For example, > finds blank lines.
[...] Matches any of the characters listed between the square brackets. A hyphen can be used to specify a range of characters. For example, [axz] matches a, x, or z; [a-z] matches any lowercase letter.
[~...] Matches any characters except those listed.
\ Escape character indicates that the following character should be taken literally rather than used as a wildcard character. For example, \% matches a percent sign.
\t Matches a tab character.
\f Matches a formfeed character.

The Search window

After specifying the search criteria, click OK to start the search. As the search begins, the editor opens the Search window (Figure 21-33). This window contains a list of files in which a match is found.

[Figure 21-33 Search window

Also during the search, the Search Progress dialog box displays statistics (Figure 21-34). Click Stop to terminate the search at the current point, or click Revert to return to the Global Find dialog box.

[Figure 21-34 Search Progress dialog box

When the search is complete, the Search Progress dialog box closes and the Search window contains a list of files in which at least one match occurred.

Search menu commands

The Search window's Search menu (Figure 21-35) contains commands to open files in Source windows, add files to the project, and continue the global search.

[Figure 21-35 Search menu commands

Refine
Reopens the Global Find dialog box. You may refine your search criteria and continue the global search. This command is disabled if no matches were found.
Show File
Opens the selected file in a Source window. You can also open a file by double-clicking on the file in the list. The file is positioned to the first match of the search pattern.
Add Selected To Project
Adds the selected file to the current project.
Add All To Project
Adds all files listed in the Search window to the current project.

Toolbar commands

The Search window toolbar (Figure 21-36) offers quick access to menu choices.

[Figure 21-36 Search window toolbar

Refine
Same as choosing Refine from the Search menu
Show file
Same as choosing Show File from the Search menu

22. Using Version Control

The IDDE's Version Control System (VCS) allows programmers to work safely with the same source files simultaneously, integrate their changes, rebuild their own sources, and store updated master files in a common master archive.

The VCS works in combination with INTERSOLV's PVCS, a popular version control program for the PC. However, VCS offers significant functional improvements over PVCS alone, because it is integrated with the IDDE's project system and has access to information stored in the project (.prj) file. Digital Mars's VCS guards against accidentally overwriting changes made by others and provides the highest level of support possible for keeping both your private project directory and the master project directory fully synchronized.

Note: If you do not have PVCS, you need to purchase it from INTERSOLV before you can use Digital Mars's VCS. See the PVCS documentation for information on PVCS features and commands.

This chapter assumes a knowledge of PVCS and a familiarity with basic version control concepts. The chapter focuses on using the group-oriented model of software development that VCS makes possible, and it explains how to use VCS to build and maintain projects.

Note: The IDDE's Version Control System (VCS) is supported only in the 16-bit version of Digital Mars C++.

Overview of VCS Concepts

This section defines basic terms used in this chapter and compares the parallel model of version control to the linear model supported by other version control systems.

The next section, "Setting Up Version Control with VCS," presents an overview of how you or your project team can use VCS to establish and maintain version control on software development projects of any size.

Terminology

The following terms are used throughout this chapter:
Archive (or master archive):
All revisions of a source file, stored in a commonly accessible directory structure, usually on a network.
Revision:
A revised archived source file that has a revision number and timestamp that identifies when the revision was created.
Workfile:
Your private copy of the revision that you are currently working on.
Private project directory:
Your personal working directory to which others do not have access. You work with workfiles in your private project directory.
GET:
The process of obtaining a private copy of a revision of an archive (usually the latest revision).
MERGE:
The process of collating changes to a revision into the archive, without overwriting or corrupting any changes made by others since you got the revision.
PUT:
The process of creating a new revision of a file in the archive.
Version:
A group of revisions containing all source files that make up a project. Typically you create versions to correspond to milestones in the development process, such as the weekly build or the beta build.

Version control models

There are two basic models for version control:
Linear:
Only one person can work with a file at any one time.
Parallel:
Groups of people can work with the same set of files simultaneously.
Most version control systems support a linear model of version control. In practice, few support a parallel version control system because additional support is required to prevent losing changes. The Digital Mars C++ IDDE, however, fully supports the parallel model.

Setting Up Version Control with VCS

This section gives you an overview of how you can use VCS on your software development project. The remainder of the chapter explains how to use VCS to perform the operations introduced here.

Using the linear model with VCS

In the linear model, VCS locks a revision when someone GETs it; that is, VCS prevents others from making a private copy. Thus, only one person may work with a revision at a time. It is even possible to lock all revisions that make up a particular version.

After changing the revision, the person who receives it must PUT it back into the master archive before others can make changes to it.

The advantage of the linear method of version control is that you do not have to collate (merge) sets of changes to a revision. The obvious disadvantage is that only one person can work on a file at a time. In large development projects in which many people are making changes to related groups of files, this model is often unworkable.

Using the parallel model with VCS

The parallel version control model allows two or more people to work simultaneously with copies of the same revision- a clear advantage even in a small work group. The disadvantage of this model is that each person's changes must be merged with changes made by others, so the master archive of a revision incorporates everyone's work and the related changes made to other files (sometimes called "dependencies").

When working in a parallel version control environment, the revisions and versions used by the development team are stored in a master archive, usually on a network. Developers GET a revision (or more typically a group of related revisions) from the master archive and work with the copies (workfiles) in their own private project directory.

After making changes to a group of workfiles, developers must MERGE their changes into the latest version of revisions of the files. This is done in the private project directory because it often involves identifying changes made by others in the interim, along with resolving dependencies in other revisions that were affected by other people's changes.

Note: In your revised file, be sure to identify the revision with which you want your changes merged. You make this reference by adding a $revision entry in the file.

When changes are merged successfully, and all related changes have been made to affected revisions in the private project directory, each developer PUTs the new revisions back into the master archive.

If a revision has been modified during the MERGE, it must be remerged before it can be PUT into the archive. VCS warns you of this automatically and gives you a way to prevent other people from merging changes into the archived version of a revision until you have successfully PUT it.

The parallel model also supports branching of revisions. When you create a branch of a revision, you can PUT it back into the archive without performing a MERGE. This allows others to GET your changes to a revision. You use the branching mechanism if you want a set of changes available to you but you do not want to MERGE the changes until your work is complete. For more information, see "Creating a new branch," later in this chapter.

Setting VCS Options

This section explains how to use the options in the VCS page of the Project Settings dialog box to set up version control parameters that specify the rules VCS follows when you GET and PUT files.

To open this dialog box, open the project you want to work with, and choose Settings from the IDDE's Project menu. In the Project Settings dialog box, select the VCS tab. The VCS page is shown in Figure 22-1.

[Figure 22-1 VCS page in Project Settings dialog box

Choosing a Development Model

The Development Model radio buttons specify the development model that VCS uses. Select the Parallel model, described earlier in this chapter, unless you are the only person working on the files in a project.

Select Linear if you are working alone, or if you need to deny other developers access to revisions you are working on.

You can switch from the parallel to the linear mode when, for example, you need to prohibit GET operations on revisions you are merging (see "Merge Options," later in this chapter).

The IDDE sets the rest of the VCS options for you, based on the development model you select, as described later in this chapter. If you need more control over the version control process, you may change the default settings. This is not usually necessary.

Get Options

These options specify how VCS handles your requests to GET revisions from the master archive:
Get read only:
Lets you GET files from the master archive, but with read only access; you cannot modify the files you GET. Check this option if you want to view a revision (for example, an old revision), or if you want to ensure that you do not accidentally change the files. This option is off by default in both development models.
Get and lock:
Prevents others from successfully executing a GET operation on a revision once you GET it. The revision remains locked until you PUT it back in the archive again. This option is on by default when you choose the Linear development model.
Get and touch:
Sets the time-stamp for any revision you GET to the current date and time. This setting forces recompilation of your files. It is off by default in both development models.
Continue on overwrite error:
Tells the IDDE to overwrite a file on a GET operation without displaying a warning. Use this setting to wipe out all changes you have made to a revision and GET a new copy from the master archives. This option is off by default in both development models.

Merge Options

The Lock Master File on Merge Setting prohibits others from executing a PUT operation on a revision in the master archive while you are performing a MERGE on it. This option is off by default in both development models.

Creating a VCS Configuration File

A VCS configuration file defines a series of variables that tell VCS where to look for and create files. You can create a VCS configuration (.cfg) file with the integrated editor or any other text editor. You need a .cfg file for each project in which you use VCS.

A sample configuration file, vcs.cfg, comes with Digital Mars C++. (It is installed in \dm\samples\windows\wclock by default.) The sample vcs.cfg contains information that VCS needs to work:

vcsdir:
The directory in which VCS stores master archives. This variable must be defined for VCS to work. (All others are optional and default to the current directory.)
journal:
The file name and path in which VCS creates a journal (journal.vcs) that contains the information about changes to revisions in an archive.
archivework:
The directory in which VCS keeps backup copies of revisions as they are updated. (This command corresponds to the LOGWORK command in older versions of PVCS.) Do not specify a RAM disk as the ARCHIVEWORK directory.
workdir:
The VCS temporary directory.
It is a good idea to give the .cfg file for a project the same name as the project itself and to save it in your private project directory.

Selecting the configuration file

Before you use VCS for the first time on a project, you need to select the configuration file for the project:
  1. In the Project window, choose Configuration from the VCS menu. The Set VCS Configuration dialog box opens.

    [Figure 22-2 Set VCS Configuration dialog box

  2. Select the configuration file you want and click OK. You need to specify its location if it is not in the current directory.

The PVCS Registration dialog box

The first time you open the Set VCS Configuration dialog box, the PVCS Registration dialog box is displayed. You must have an INTERSOLV LAF (License Administration Facility) code to use PVCS in the IDDE. INTERSOLV supplies the LAF code to licensed users. For more information, please contact INTERSOLV. Type the code in the License Code textbox, then click OK to continue. After the PVCS Registration dialog box disappears, a message informs you that you must restart Windows.

The User database directory textbox shows the database directory in which the license database is placed. This directory should be a shared directory on the network if multiple developers are using the same copy of the IDDE from the network. If developers have individual copies of the IDDE, do not change the text in this box.

Note: If you have PVCS version 5.0 or later, the IDDE does not display the PVCS Registration dialog box.

Putting Revisions into the Archive

When you PUT a revision in the master archive, VCS updates its revision number and time stamp and marks it as "not changed" with respect to the corresponding workfile in your private project directory.

Note: If, while you were performing a MERGE, another person has PUT a new revision of a file you want to PUT, VCS warns you with a modal dialog box that you must perform another MERGE operation on the revision.

To prevent others from working on a revision while you are merging it, check Lock Master File on Merge. See the section "Merge Options," earlier in this chapter, for more information.

To begin a PUT operation, choose Put from the Project window's VCS menu. The Put dialog box is displayed.

[Figure 22-3 Put dialog box

The Put Candidate Files listbox shows those workfiles in your private project directory that have changed since you checked them out. Click the Add button to add files from this list to the Files to Put Back listbox; this shows the files you want to PUT into the master archive. To remove a revision from the Files to Put Back list, select it and click on Remove.

Click on Select All to select all files in the current listbox. Click on Unselect All to deselect them.

Select a file name and click on View Log for a summary of who changed the latest revision of that file and the changes that were made.

To associate comments with all selected files in the Files to Put Back listbox, type them into the Comments textbox.

Click on Put to PUT the files listed in the Files to Put Back listbox into the master archive.

Click on the Advanced button and the Put dialog box expands to show additional options.

When you PUT files into the archives, you can specify a group of files using the Put Special textboxes. The Put Special options are:

Revision:
Specifies the revision number you want to give the workfiles you are putting into the archives. The revision number has the format nn.xx, where nn is the major number and xx is the minor number. The numbers can range from 0 to 65,535.

If you do not explicitly assign a revision number to a revision, VCS assigns one automatically by incrementing the minor number of the most recent revision by one.

Version:
Assigns the name you want to a group of revisions, such as beta or alpha. VCS associates the version name with all revisions listed in the Files To Put Back listbox.
Date/Time:
The date and time of a version or revision you archive. The default date format is mmm/dd/yy; mmm is the month, dd the day, and yy the year. The time format is hh[:mm[:ss]]; hh is the hour, mm is the minute, and ss is the second.

Creating a new branch

Use the Create New Branch option to maintain a private set of revisions in the master archives without having to MERGE them. When you have a private branch, you can change a file and perform PUT operations as often as necessary, without affecting other developers.

When you are ready, you can MERGE your private revisions back into the master archive.

Note: A MERGE is the only way to make the changes in a branch available to other developers.

Getting Revisions from an Archive

Before you can work with archived revisions, you need to GET them from the archive and copy them to your private project directory using the Get dialog box, shown in Figure 22-4. (Both the archive directory and your private project directory are specified in the VCS configuration file for the project.)

When you GET a revision from an archive, VCS records the revision identification numbers of the files, marks them as unchanged and not new, and adds them to your project (if you so specify in the Get dialog box).

If you are using the linear development model, VCS locks the archived revisions when you GET them so nobody else can GET them until you PUT them back. If you are using the parallel model, more than one developer can check out the revision unless you specify Get and Lock on the VCS page in the Project Settings dialog box.

To GET revisions from the master archive:

  1. In the Project window, choose Get from the VCS menu. The Get dialog box is displayed.

    [Figure 22-4 Get dialog box

  2. The VCS File Name listbox shows the names of all revisions in the archive. Select from this list the files you want to move to your private project directory.

    To add one or more files, click on the file name(s), then click on the Add button. To add all files in the archive, click on the Select All button. VCS moves the files you select to the Work Files listbox.

    To view a summary of who made certain changes to a revision, click on View Log. (This is the same log that is available from the Merge dialog box.)

  3. When all the files you want are in the Work Files list, click the Get button. VCS copies those files to your private project directory.

    To remove files from the Work Files list, click on the file name(s), then click on the Remove button.

Click on the Advanced button to display the following additional options: Show Archives, Get Special, and Add Files to Project.

Show Archives provides the following settings:

All archives:
Displays all archives in the VCS File Name listbox. This is the default setting.
New archives:
Displays in the VCS File Name listbox the names of the new archives and archives that have changed since the last time you performed a GET operation. Choose this option to update your private copy of the project with the most current revision(s).
Except merges:
Displays in the VCS File Name listbox all the new revisions in the archive except those you just merged or need to merge. Select this option to choose only those additional archives you need to build and to test merged revisions.

The Add Files to Project option adds the revisions automatically to the current project when VCS gets them from the archive.

To retrieve a specific revision or version, use the Get Special textboxes:

Revision:
is the number of the revision you want to get from the archives. The revision number has the format nn.xx, where nn is the major number and xx is the minor number.
Version:
is the name of the version you want to GET. The version name identifies a particular version, such as alpha or beta.
Date/Time:
is the date and time of a particular version or revision. The default date format is mmm/dd/yy; mmm is the month, dd the day, and yy the year. The time format is hh[:mm[:ss]]; where hh is the hour, mm is the minute, and ss is the second.

Merging Revisions

If you are working with the parallel development model, after you GET a revision and make changes to it, you may need to MERGE those changes into the master archive. The master archive presumably contains changes made by others that your revision does not include. If no other developer has changed the file, then you do not need to MERGE; you simply PUT the new revision in the master archive.

Note: Remember that in your revised file, you must refer to the revision with which you want your changes merged. You do this by adding a $revision entry in the file.

When you MERGE a revision, VCS creates a backup of your revision in your private project directory. In addition, VCS provides all possible support for performing MERGE operations safely.

To merge your changes into another revision in the archive, choose Merge from the Project window's VCS menu. The Merge dialog box opens.

[Figure 22-5 Merge dialog box

The Merge dialog box contains four listboxes:

Files you modified:
Shows the files you modified in your private project directory since the last time you performed a GET operation.
Files new in VCS:
Shows archives that someone else has changed since the last time you performed a GET operation. The current (most recent) revision number is displayed. These are files you might need to GET to rebuild the project with your changes and to PUT your new revisions back into the archive.
Files to merge:
Shows files that both you and another person changed since the last time you performed a GET operation. These are the workfiles you need to MERGE.
Merged files:
Shows files that you merged during the current MERGE session.
To display a log showing who changed an archive and what changes were made at each revision, click on a file name in one of the listboxes and click on the View Log button. See the PVCS documentation for information on the display format.

Click the View Changes button to show the changes you need to resolve when you MERGE the selected revision. When you click View Changes, an annotated change file appears in an IDDE editor window. See the PVCS documentation for information on the format of the display and the meanings of symbols.

When you are ready to perform the MERGE operation, click on Merge. VCS guides you through a three-way merge, incorporating your changes and those made by others into a new revision.

Because the IDDE automatically makes backup copies of both the revision in your private project directory and the revision you want to MERGE it with, you can undo a MERGE (before closing the Merge dialog box) by clicking Undo Merge.

Testing the MERGE operation

To test the MERGE, return to the Get dialog box, click on Advanced, and select Except Merges. GET the files in this list and build them using the IDDE (see Chapter 8, "Testing an Application," for information).

Using the VCS Manager

Use the VCS Manager for additional flexibility in managing revisions and versions. You can apply a version name to a set of archives when the software reaches a significant release step, such as beta or final release. You can also delete a named version or revision from an archive. Before deleting a version or revision, make sure that you are deleting the right one, as a deleted version or revision cannot be recovered. Finally, the VCS manager lets you lock or unlock a version or revision.

To use the VCS Manager in the Project window, choose Manager from the VCS menu.

The VCS Manager dialog box shown in Figure 22-6 is displayed.

[Figure 22-6 VCS Manager dialog box

Note: You probably will not need to use the VCS Manager dialog box on most projects.

The VCS Directory listbox contains the names of revisions to add to a version or revision. Double-click on the file name to add it to the Selected Files listbox. Click on Select All to select all files.

To assign a version name, type the name, such as beta, in the Version textbox, and click on the Assign button. This assigns the version name to all files in Selected Files. The Assign and Unassign buttons are available only if you specify a version name in the Version textbox.

To control access to a particular version or revision, specify the revision (its number) or version (its name) in the appropriate textbox, then click on Lock to deny access or Unlock to allow access.

To delete a version or revision, specify the appropriate information in the Revision or Version textbox, and click on the Delete button.

Creating a Master Archive

When you begin using VCS, it may be your job to create the master archive to and from which others GET and PUT files. This section describes the process of creating a master archive.

The master archive contains the revisions to all source files in a project. It also records information about changes from the previous revision, a history of the changes since the first revision, a record of who changed the files, the comments attached to the revisions as they were changed, and the date and time that each revision was PUT into the archive. See the PVCS documentation for additional information.

To set up a master archive, you PUT the workfiles in your project directory in the archives using the Put command. This command takes files from the original directory and creates the archives automatically. See "Using the VCS Manager," earlier in this chapter, for more information on the Put dialog box and how to use it.

When you PUT files in an archive, VCS changes their extensions automatically. The last character of the extension on each file is changed to V. For example, the file extension on abc.cpp becomes abc.cpv. If the file does not have an extension, VCS adds the extension .__v to the filename (two underscores and a v).

To create a master archive from the workfiles in your private project directory:

  1. Choose Put from the VCS menu in the Project window.
  2. PUT the workfiles from your private project directory into the archive by double-clicking on the file in the Put Candidate Files listbox.

    The Put Candidate Files listbox displays the names of workfiles that you changed since the last time you performed a GET operation. The listbox also shows the files that do not yet have archives. Because you are creating the archives, all files in the project are displayed. Files you select are added to the Files To Put Back listbox.

  3. To add all your workfiles to the master archive, click on Select All. To remove a workfile from the list of files to archive, select the file in the Files To Put Back list and click on the Remove button.
  4. Optional: Type a comment in the Comments textbox. VCS applies your comment to all selected files in the Files to Put Back listbox.
  5. Click the Put button to create the master archives and PUT your workfiles in them.

23. Controlling and Configuring the Debugger

This chapter describes the commands on the IDDE's Debug menu that you use to run the debugger. This chapter also explains how to use breakpoints and watchpoints effectively.

Chapter 8, "Testing an Application," presents an overview of the Digital Mars C++ debuggers and explains how to perform typical debugging tasks.

Chapter 24, "Commands Available in Debugging Mode," describes the commands and the functionality of each of the debug windows that you can open from the Views palette.

Commands on the Debug Menu

Debugging commands are located in the Debug menu on the IDDE's main menu bar. Figure 23-1 shows the Debug menu commands.

[Figure 23-1 Debug menu commands

This section describes the commands in the Debug menu in the order shown in Figure 23-1.

Note: Frequently used debugging commands are available from the Debug toolbox. See "Debug Toolbox Icons" in this chapter to learn how to use the Debug toolbox.

Start/Restart Debugging

Starts a debugging session. During a debugging session, any open Source window changes from editing mode to debugging mode. In debugging mode you can set breakpoints, jump to a specific line, or view assembly instructions generated for a line of code. You cannot, however, edit the source code. You must exit the debugging session (return to the editing session) to modify the source code.

Note: If you need to specify command-line parameters in your application, you can do so in the Run Arguments dialog box, available by choosing the Arguments command from the IDDE's Project menu.

If debugging is in progress, choosing Start/Restart Debugging restarts the application.

Note: If you want to run the program without debugging it, choose the Execute Program from the Project menu.

Stop Debugging

Exits the current debugging session and switches the IDDE into editing mode.

Step Into

Executes the program until it reaches the next source-level statement. This command lets you step through the program's code at the source level, statement by statement.

If Step Into is used on a procedure or function call, the debugger steps into the first statement of the function only if tracing is enabled for the module containing that function. For more information, see "The Project Window," in Chapter 24, "Commands Available in Debugging Mode."

If the Assembly window is the active window, this command executes to the next assembly (as opposed to source level) instruction. If the assembly window is open but is not the active window when you use this command, it updates to show the next instruction to be executed.

Step Over

Executes the program to the next statement, or until a breakpoint or watchpoint is triggered or an exception is raised. If the current statement is a call to a procedure or function, the program executes to the next statement following the call.

If the Assembly window is the active window, this command executes the program to the next assembly instruction without tracing into function calls. If the current instruction is a call to a function, the program executes to the assembly instruction following the call.

Return from Call

Executes the program up to the current function's return address, or until a breakpoint or watchpoint is triggered or an exception is raised. This command is useful when executing the rest of the current function or procedure after having stepped into it, then stopping execution at the point immediately after the call was made.

Go until Breakpoint

Executes the program until a previously set breakpoint or watchpoint is triggered.

Go until Next Function

Executes the program until the entry point of the next function call is reached, or until a breakpoint or watchpoint is triggered or an exception is raised. This command is useful when executing from any point in a function to the next function call.

Go until End

Executes the program to the end, ignoring any breakpoints and watchpoints that are set. If a Windows protection fault or other exception occurs, the program breaks at the point of the violation.

Break

(32-bit IDDE only) Stops the process currently being debugged, and shows the location of the current execution point. Choosing Break is equivalent to typing CTRL+ALT+SYSREQ in a debugging session with the 16-bit IDDE.

Animate

Executes the program until the next source-level statement is reached, waits for a short delay (the animate delay), and again executes the program until the next source-level statement is reached. This command is equivalent to repeatedly executing the Step Into command and waiting for a short delay. To stop the animation mode, choose Stop Animate.

To set the animation delay time, choose the Animate Delay command from the Settings submenu of the Debug menu (see the section "Animate delay," later in this chapter).

Stop Animate

Stops the animation mode.

Settings

Brings up the Debugger Settings tabbed dialog box (Figure 23-2). The tabs at the top allow you to switch between the General page, the Exceptions page, and the Multiple EXE/ DLL page.

General

Options on this page of the Debugger Settings dialog box control the general debugger settings, such as the animation delay.

[Figure 23-2 General page of the Debugger Settings dialog box

Flip screen

Specifies whether the IDDE flips control of the screen between the debugger and the text-mode application window each time the debugger executes some part of the application code.

When Flip Screen is turned on, the application gets control of the screen each time it runs. When Flip Screen is turned off, the debugger does not activate the application to bring it to the foreground each time the debugger gives control to the application.

Animate delay

Opens the Animate Delay dialog box. This dialog box allows you to specify the amount of time the debugger pauses between steps while in animation mode. In animation mode, the debugger executes the program step by step, pausing between steps by the amount of time you have specified. (See the section "Animate" earlier in this chapter for information on the Animate command.)

The Animate Delay dialog box lets you specify the delay in milliseconds. For example, to pause for one second between steps, specify 1000; the default is one-half second (500 milliseconds) delay.

Load symbols when editing

When this option is checked, the IDDE loads debug symbols from the compiled executable or the DLL when the IDDE is in editing mode. This gives you access to the data definitions in the Data Window, as well as to line number information, while editing your source code. For this option to work properly, you must build your project with debug symbols enabled. Note that in editing mode some of your operations in editing mode might take longer when this option is on because IDDE has to load the debug symbols from your compiled project.
Warning: No changes that you have made to the source files since the last time you compiled your project are reflected in the debug symbols shown while you are editing. To update the debug symbols, you must rebuild your project.

Debug application startup

Controls whether debugging starts at the beginning of a program or at the WinMain() or main() entry point.

If you check this option, the debugger automatically sets a fixed breakpoint at the main entry point and lets you trace through the application's startup code. If not, the debugger starts tracing from WinMain() or main() onward.

Automatic switch to debug workspace

When you check this option, the debugger automatically debugs the current project in the IDDE debugging workspace.

Automatic check of project dependencies

When you check this option, the debugger automatically checks the project dependencies in the current project.

Show local data on start debugging

When you check this option, the debugger automatically displays local data at the start of a debugging session. By default, the Data window shows no data.

Enable C++ class display

Specifies whether the debugger displays C++ types in the Data/Object window using the form class::object. When you do not check this option, the debugger does not display C++ class names in the Data/Object, Call, or Function windows.

Alternate class display

Reverses the order in which C++ information is displayed in the Data/Object window to the form object::class. This command is disabled unless you check the Enable C++ Class Display option.

Source search path

Specifies the search path for source files when debugging.

Working directory

Specifies the working directory for a debugging session.

Exceptions (32-bit IDDE only)

Options on this page let you control how the debugger responds to the operating system when an exception occurs. This capability helps you diagnose the cause of unforeseen, and possibly serious, errors.

Exceptions presented on this page are NT exceptions, which are part of the Structured Exception Handling mechanism of Win32. NT exceptions comprise both hardware exceptions (such as access violations, division by zero, or stack overflow) and software exceptions (explicitly initiated either by Win32 APIs- HeapAlloc, for instance- or by your own code). However, C++ exceptions are also accommodated on the Exceptions page. When you throw a C++ exception in a Win32 program, an NT exception is raised. The exception code of the NT exception is the same value, unique to Digital Mars C++, regardless of which C++ exception was thrown.

Note: For more information on Structured Exception Handling, see Microsoft Win32 Programmer's Reference, Volume 2.

You can specify whether or not the debugger should stop on a particular exception, or should stop only if you have not provided a handler for it. (Uses of these options are discussed below.) The Exceptions page is shown in Figure 23-3.

[Figure 23-3 Exceptions page of the Debugger Settings dialog box

Number:
Contains an exception code- a DWORD that uniquely identifies an exception. Exception codes are displayed and entered in the Number field as eight-digit hexadecimal numbers. Symbolic constants for the exception codes of predefined NT exceptions can be found in include\win32\winnt.h, located beneath the directory in which you installed Digital Mars C++.

The layout of an exception code's 32 bits is summarized in a comment in the header file include\win32\winerror.h. If you define your own exceptions, your exception code should adhere to that format.

Name:
Contains a descriptive string. No restrictions are placed on the contents of this field.
Action:
This drop-down list box contains two choices: Stop if not Handled, and Always Stop. For both actions, the debugger stops before the operating system itself responds to the exception.
Stop if not handled:
The debugger stops only if no outstanding __try/__except or __try/catch block will handle this exception.
Always stop:
The debugger stops, whether or not the exception will be handled.
If you have written a handler for a particular exception, you can choose to always stop on that exception to determine the point at which it was raised. If an exception occurs that you have not anticipated and for which you have not written a handler, either Action will make the debugger stop. You can then diagnose the cause of the exception by examining values of variables and the call chain. Stop if not Handled can also be used to debug existing exception handlers. It assists you in diagnosing situations where an exception for which you have written a handler is being raised, but which none of your handlers is catching.
Add:
Adds a new exception to the list contained in the main pane, as specified in the Number, Name, and Action fields. The Number field must contain a value not used by any exception already in the list.
Replace:
Replaces information for the currently selected exception in the main pane with the contents of the Number, Name, and Action fields. This button is disabled if the Number field contains a value different from the Number (exception code) of the selected exception.
Remove:
Deletes the currently selected exception from the list in the main pane.
Reset:
Undoes any changes to the built-in exception entries, without altering any added exceptions. If any built-in exception entries have been deleted, they are restored; all Actions and Names for built-in exception entries are reset.

Multiple EXE/DLL debugging

Options on this page (Figure 23-4) allow you to specify how to debug a project with multiple executables or dynamic link libraries.

[Figure 23-4 Multiple EXE/DLL page of the Debugger Settings

Single executable:
Debugs only the executable file. Does not debug DLLs called by the executable.
All loading EXE/DLLs:
Debugs the executable file and all DLLs or EXEs called or spawned by the executable, including DLLs loaded at run-time via explicit calls to the LoadLibrary API.
Specific EXE/DLLs:
Debugs the executable file and specific DLLs or EXEs. Select those you want in the Specify Libraries and/or Modules to Debug portion of the dialog box (enabled only when this radio button is selected).
Calling program:
For a DLL project, this textbox lets you specify the application that calls the DLL.

Debug Toolbox Icons

The Debug toolbox contains icons that correspond to the commands on the IDDE's Debug menu. Figure 23-5 shows the command that each icon invokes. For information on how to use these commands, see the previous section.

Debug toolbox icons
Figure 23-5 Debug toolbox icons

Working with Breakpoints

This section explains how to set and use breakpoints with the Digital Mars C++ debuggers. The debuggers support three types of breakpoints: Note: Breakpoints persist across debugging sessions; the debuggers automatically save them to and restore them from project configuration files.

Unconditional breakpoints

An unconditional breakpoint causes the debugger to stop execution of the program when the breakpoint is encountered.

You set unconditional breakpoints using the Set Breakpoint or the Set/Clear Breakpoint command (F9) in the Source, Assembly, Function, Data/Object, or Breakpoint windows (as well as in the Spy window when debugging a Windows application). After setting an unconditional breakpoint, choose the Go until Breakpoint command from the IDDE's Debug menu to execute your program until it reaches the breakpoint. When the breakpoint is reached, the program halts and returns control to the debugger.

Note: While in debugging mode, you can also set an unconditional breakpoint by double-clicking in the left margin of the Source window at the line where you want execution to stop.

Conditional and delayed breakpoints

Conditional breakpoints let the debugger: You can set these kinds of breakpoints using the Set Conditional Breakpoint command in the Source, Assembly, Function, or Breakpoint windows. After you execute this command, the Set Code Breakpoint dialog box shown in Figure 23-6 is displayed.

Note: When you choose Set Conditional Breakpoint in the Breakpoint window, the Expression dialog box is displayed first. Enter the address or procedure name (for example) where you want to set the breakpoint. The Set Code Breakpoint dialog box is then displayed to allow you to specify the kind of breakpoint to set.

[Figure 23-6 Set Code Breakpoint dialog box

The debugger automatically sets the Line, Address, and Procedure fields, based on the location of the breakpoint.

Limit:
Use this field to reach the breakpoint a specified number of times before the debugger stops program execution. This sets a delayed breakpoint.
Condition:
Use this field when you want an expression to be evaluated every time execution of the program reaches this breakpoint. If the expression evaluates to TRUE (nonzero), the debugger performs the action( s) specified in the Actions group. In the Condition field, enter the expression to be evaluated.
Evaluate:
Check this option if you want the debugger to evaluate the next field's expression whenever the program reaches this breakpoint. If you use the Condition field, a breakpoint is triggered only if the Condition evaluates to TRUE.

This field allows you to insert into your code a statement that you had neglected to include, or to test (in the debugger) that a modification works before editing, compiling, and linking.

Note: Please refer to Appendix A, "Expression Evaluation," for more information about expressions.

Break:
Check this option if you want the debugger to stop execution of the program whenever the program reaches this breakpoint. If you use the Condition field, the debugger stops execution on reaching this breakpoint only if the Condition evaluates to TRUE.

Examples of conditional breakpoints

The following are examples of conditional breakpoints:

Example 1

To execute your program to a point at which a certain condition is met- such as stopping the execution at this breakpoint only if the value of i + j is greater than 2000 -- execute a Set Conditional Breakpoint command. Specify the expression i + j > 2000 in the Condition field.

The debugger executes your program and evaluates the condition every time it executes the line on which the breakpoint is set. If the condition specified does not evaluate to TRUE, the debugger continues to execute your program. As soon as the value of i + j exceeds 2000 when this line is executed, the debugger stops executing the program and regains control.

Example 2

You omitted a statement from a line in which you should have called the function AddRes from the module Results with the parameter i as defined in the current function. You can use a conditional breakpoint to direct the debugger to evaluate this call whenever it encounters the breakpoint, and to do this before this line is executed and without stopping execution.

Set a conditional breakpoint on the line and specify the Evaluate option, as shown in Figure 23-7.

[Figure 23-7 Setting a breakpoint in your code

Every time the debugger reaches this line and i + j > 2000 is TRUE, it calls RESULTS.AddRes(i). However, it does not stop executing your program because you did not check the Break check box.

For information on breakpoint and watchpoint commands in windows, see "The Command Window," in Chapter 24, "Commands Available in Debugging Mode."

Working with Watchpoints

Watchpoints are vital to debugging. A watchpoint stops program execution while the debugger either writes to or reads from a location in memory. A variable or location in memory is often improperly overwritten, causing the program to crash. Use watchpoints to find these kinds of errors.

You can set watchpoints using the debugger. First, highlight either a variable in the Data/Object window or a memory location in the Memory window, then execute the Set Watchpoint command in that window's Watch menu. You need not specify an address for the watchpoint. The debugger sets the watchpoint on the address of the highlighted variable or on the highlighted location in memory.

Digital Mars C++ uses the debugging capabilities of the 80386 and higher microprocessors to provide full-speed execution of watchpoints. These microprocessors relieve the debugger of the need to check for the use of watchpoint locations when certain instructions or functions are executed. Watchpoints implemented with hardware assistance are called hardware watchpoints, in contrast to the slower software watchpoints that debuggers must implement in the absence of hardware support.

Setting watchpoints

When setting a watchpoint, the Set Watchpoint dialog box, shown in Figure 23-8, prompts for information. This dialog box displays the address of the watchpoint and the size of the watched area in bytes. It lets you set the type of access mode on which the watchpoint should break. You can set the watchpoint to break on read access, write access, or both.

[Figure 23-8 Set Watchpoint dialog box

You can set up to four 1-byte watchpoints. You can also set four 2-byte watchpoints if all the addresses in memory for which the watchpoints are set are word aligned.

Use watchpoints on local variables with caution

If you set a watchpoint on a stack location such as a local variable, the debugger displays a warning message on the status line:
	Warning: Setting a watchpoint on stack memory 
Clear any watchpoint set on a local variable before the function to which it is local returns. Otherwise, Windows itself can subsequently access the location, thus triggering the watchpoint and possibly causing Windows to crash.

24. Commands Available in Debugging Mode

This chapter describes the commands available in debug windows. The IDDE has several windows dedicated to debugging, each with a different view of a program and a specific set of commands for manipulating or examining the program during a debugging session.

The descriptions of the debug windows and their menu commands follow, in alphabetical order. Each window's commands are discussed in the order in which they are listed in the menu bar.


Debug Windows and Commands

Using the debug windows, the Digital Mars C++ debugger gives you up to 18 different kinds of views into a program's state at run-time. You open these windows from the Views toolbox (see Chapter 2, "Introducing the IDDE" ).

Because many of the commands associated with these views are applicable only while a specific window is active, each debug window has its own menu, located below the window's title bar.

A window's commands are available only while that window is active. For example, because you would not set a breakpoint when using the Call window, no breakpoint commands appear among the Call window's menus. Because setting breakpoints is a typical source-level operation, several breakpoint commands are available when the Source window is active.

Drag and drop

One of the IDDE's unique features is the ability to drag and drop updated information between debug windows, saving you the trouble of choosing menu commands. This chapter covers all the valid drag-and-drop operations among the IDDE's debug windows.

Accelerator keys

You can also execute most debug window commands through an accelerator key combination (a function key or a Control key combination). For example, you can choose the Start/Restart Debugging command by pressing F4. A command's description provides the accelerator key combination (if any) that invokes it.

The Assembly Window

The Assembly window, shown in Figure 24-1, displays the disassembled instructions of your program at a selected memory location. The Assembly window's menus (View, Bpt, and Others) let you set and clear assembly-level breakpoints, set the disassembly address, and determine the amount of symbolic information to display.

[Figure 24-1 Assembly window

The header line in the Assembly window (below the menu bar) displays the module and function for the currently highlighted assembly instruction. The first column of information in the window area shows code addresses of the assembly instructions. If you choose the Source command from the View menu to enable the interleaved display of C++ source code, this column also shows the line numbers of source-level statements.

If you execute the Step Into (F8) or Step Over (F10) commands from the IDDE's Debug menu while the Assembly window is active, the debugger steps at the assembly level as opposed to at the source level. For more information on controlling the execution of the debugged program, refer to Chapter 23, "Controlling and Configuring the Debugger."

By default, the disassembly location is set to the address of the next statement to be executed. However, by using the Set Disassembly Address command in the Others menu, you can select another address to disassemble.

The arrow, located to the left of the code address, indicates where execution has currently stopped.

When Opcodes is checked in the View menu, the first column contains source code addresses. The second column displays source-level information and/or assembly instructions. The last column displays opcodes for each assembly instruction if Source is checked in the View menu.

The Assembly window has three menus (shown in Table 24-1) in the debuggers: View, Bpt, and Others.

	Table 24-1 Assembly window commands 

	Menu	Menu Item			Shortcut 
	View	Symbols				none 
		Source				none 
		Opcodes				none 
	Bpt	Set/Clear Breakpoint		Ctrl+S/Ctrl+F9 
		Set Conditional Breakpoint	Ctrl+B 
		Clear All Breakpoints		Ctrl+K 
	Others	Set Disassembly Address		Ctrl+A 
		Jump To Line			Ctrl+J 
The menu items in the Assembly window are described next.

View menu

This menu sets the display modes of the Assembly window. The Assembly window displays assembly language code mixed with symbols and source, as well as opcodes. A checkmark indicates the current display mode.

[Figure 24-2 Assembly window View menu

Symbols

Enables disassembled instructions mixed with symbolic information such as variable names, function calls, and function entry points.

Source

Enables disassembled instructions mixed with the corresponding source code (if debugging information is available for the disassembled module).

Opcodes

Toggles the display of assembly instruction opcodes.

Bpt menu

The Bpt Menu commands set and clear breakpoints at the assembly language level in the program. See the section "Working with Breakpoints," in Chapter 23, "Controlling and Configuring the Debugger," for information on how to use breakpoints.

Set/Clear Breakpoint

Sets an unconditional breakpoint at the selected assembly line. The next time a Go command is executed (except the Go until End command), execution of the program stops when it reaches this line. If a breakpoint is already set on the selected assembly line, this command clears that breakpoint.

[Figure 24-3 Assembly window Bpt menu

Note: To set a breakpoint, you can drag and drop from the Assembly window to the Breakpoint window. The presence of a breakpoint is indicated by a solid black diamond to the left of the instruction's address. You can move the breakpoint to a different line by dragging the black diamond to a different line. Drop the diamond outside the window to clear the breakpoint.

Set Conditional Breakpoint

Opens the Set Code Breakpoint dialog box. You use this dialog box to set a conditional breakpoint at the selected assembly line.

Clear All Breakpoints

Clears all breakpoints set anywhere in the program.

Others menu

Using the Others menu, you can set a particular disassembly location and change the execution location.

[Figure 24-4 Assembly window Others menu

Set Disassembly Address

Sets the disassembly address. When this command is executed, the debugger prompts you to enter an address. In the dialog box, enter a hexadecimal address conforming to the language in use for the expression evaluator. (See Appendix A, "Expression Evaluation.") For segment:offset addressing, use the following format:
0xnnnn:0xnnnn 
where nnnn is a 4-digit hexadecimal number. You may omit the segment address (and the colon) to specify an address in the same segment as the one currently displayed. If you are running in the 32-bit flat memory model, specify the address in the following form:
0xnnnnnnnn 
where nnnnnnnn is an 8-digit hexadecimal number.

Jump to Line

Changes the execution location of the current thread to the selected assembly line. (The execution location, also known as the instruction pointer, is stored in the CS: IP or EIP registers.) To execute the Jump To Line command, select the assembly line where you want execution to resume, then press Ctrl+ J.

The Jump to Line command simulates a jump instruction, skipping sections of code without executing them. When stepping through the program, it continues executing from the new location.

Pop-up menu

You can access the Assembly window pop-up menu by pressing the right mouse button anywhere in the window. The pop-up menu provides quick access to three commands: Set/Clear Breakpoint, Set Conditional Breakpoint, and Jump to Line. These commands are described above.

[Figure 24-5 Assembly window pop-up menu


The Breakpoint Window

The Breakpoint window, shown in Figure 24-6, displays status information about all breakpoints set in the program. Breakpoint window commands show the source location of a breakpoint and clear, set, enable, or disable breakpoints.

When a breakpoint in the Source, Assembly, or Spy windows is set, cleared, or triggered, the status of the breakpoint is displayed in this window.

[Figure 24-6 Breakpoint window

The Breakpoint window lists all breakpoints currently defined in the program. You can view the different parameters of any breakpoint and enable or disable the currently defined breakpoint.

The Breakpoint window displays the following information for every line:Location, Address, Count/Limit, Act, Condition, and Action Expr.

Location:
Gives the name of the module in which the breakpoint is set, followed by the function name and the line number in the module.
Address:
Provides the code address of the breakpoint setting.
Count/Limit:
Displays the number of times the breakpoint is triggered. If you specify a break Condition, the count is the number of times the breakpoint has been reached with the specified expression evaluating to TRUE. The limit is the number of times the breakpoint must be reached for it to be triggered. This field is displayed only if you have specified a limit.
Act:
Corresponds to the Action field in the Set Code Breakpoint dialog box. It can contain either or both of the characters B or E, or nothing. If B is present, execution breaks when it reaches this breakpoint location. (If a break condition is specified, execution breaks only if the Condition expression evaluates to TRUE when the location is reached.) If E is present, the Action Expr. field (see below) is evaluated every time the breakpoint is reached.
Condition:
Shows the expression entered for a conditional breakpoint. This expression is evaluated every time execution reaches this breakpoint location. If the expression evaluates to TRUE and the Action field contains B, execution stops.
Action Expr.:
The expression entered for a conditional breakpoint to be evaluated at each breakpoint hit. If you specify a Condition, the action expression is evaluated only if the Condition expression evaluates to TRUE. This expression is evaluated every time the execution reaches this breakpoint location if the Action field contains E. Evaluation does not stop execution of the program unless the Action field also contains B.
You can set a breakpoint on any program statement in the Source window or on any assembly instruction in the Assembly window, with no limit to the number of breakpoints set.

The Breakpoint window has two menus, as shown in Table 24-2: Show and Bpt.

	Table 24-2 Breakpoint window commands 

	Menu	Menu Item			Shortcut 
	Show	Source				Ctrl+S 
		Assembly			Ctrl+A 
	Bpt	Set Breakpoint			F9 
		Set Conditional Breakpoint	Ctrl+B 
		Clear Breakpoint		Ctrl+C 
		Clear All Breakpoints		Ctrl+K 
		Enable Breakpoint		Ctrl+E 
		Disable Breakpoint		Ctrl+D 
The Breakpoint window menus are described next.

Show menu

The Show menu commands show the Source and Assembly windows, positioned at the selected breakpoint.

[Figure 24-7 Breakpoint window Show menu

Source

Opens the Source window if it is not already open, makes it the active window, and positions its contents to display the selected breakpoint. Double-clicking on a source-code breakpoint in the Breakpoint window or dragging and dropping from the Breakpoint window to the Source window also executes this command.

Assembly

Updates the Assembly window, if it is open, to display the assembly location of the selected breakpoint. Dragging and dropping from the Breakpoint window to the Assembly window also executes this command.

Bpt menu

Bpt menu commands set breakpoints, clear individual breakpoints or all breakpoints, and enable and disable breakpoints.

[Figure 24-8 Breakpoint window Bpt menu

Set Breakpoint

Displays an Expression dialog box. To set an unconditional breakpoint, type the address and press Enter. You also can enter a symbolic name, such as the name of a procedure. The new breakpoint is added to the Breakpoint window. After executing any Go command (except the Go until End command), execution of the program stops when it reaches this line.

Set Conditional Breakpoint

Displays an Expression dialog box. To set a conditional breakpoint, type the address or a procedure name and press Enter. The debugger displays the Set Code Breakpoint dialog box. In this dialog box, you specify the condition of the breakpoint.

Clear Breakpoint

Clears the selected breakpoint.

Clear All Breakpoints

Clears all breakpoints set in the program.

Enable Breakpoint

Enables the selected breakpoint (if currently disabled).

Disable Breakpoint

Disables the selected breakpoint (if currently enabled). Use this command to temporarily disable a breakpoint that you can later enable without having to set it again.

Pop-up Menu

The Breakpoint window pop-up menu allows you to access frequently used commands quickly. You can bring up the pop-up menu by pressing the right mouse button anywhere in the Breakpoint window. The five commands in the pop-up menu appear in other Breakpoint window menus and are described in detail in the preceding sections.

[Figure 24-9 Breakpoint window pop-menu


The Call Window

The Call window, shown in Figure 24-10, lists the function calls a program has made since it began running. The entries in this list, often referred to as the call chain, are displayed in reverse chronological order, from the last (most recent) call to the first (initial) call.

Each entry lists the name of the function called, followed by the name of the module containing that function.

[Figure 24-10 Call window

Use the Call window to display:

If no function calls have been made or all function calls have returned, the Call window displays one of the two following status messages:
	No call chain (loading) 

	No call chain (terminating) 
If the call chain is invalid, the Call window displays the following message:
	No call chain (error) 
If no debugging information is available for a function in the call chain, its entry in the Call window is displayed as:
	PROCEDURE AT segment:offset 
where segment:offset is the address of the function called. In the 32-bit flat memory model, addresses are displayed as 8-digit hexadecimal numbers rather than in segment:offset format.

If no local symbols are available, the address is displayed as:

	Unknown Procedure 
The Call window's local Show menu is shown in Table 24-3.
	Table 24-3 Show Menu commands 

	Menu	Menu Item	Shortcut 
	Show	Source		Ctrl+S 
		Data		Ctrl+D 
		Functions	Ctrl+U 
		Assembly	Ctrl+A 
		All		Ctrl+L 
		Code Address	none 
The menu items in the Call window are described in the following section.

Show menu

Show menu commands update the position and information displayed in the Source, Data, and Assembly windows. Use these commands to view local data and the source-or assembly-level execution position of the selected function in the Call window.

[Figure 24-11 Call window Show menu

Source

Opens the Source window (if not already open), makes it the active window, and updates it to show the source-level location at which the selected function is executing. Dragging and dropping from the Call window to the Source window or double-clicking on the line in the Call window also executes this command.

Data

Updates the Data/Object window to show the local data and variable information of the selected function. Dragging and dropping from the Call window to the Data/Object window also executes this command.

Functions

Updates the Function window to show the current entry in the call chain.

Note: Dragging and dropping from the Call window to the Function window shows all functions in the module in which the selected entry in the Call window resides.

Assembly

Updates the Assembly window to show the assembly-level location at which the selected function is executing. Dragging and dropping from the Call window to the Assembly window also executes this command.

All

Updates the Source, Data, and Assembly windows. You also can double-click on a call chain entry to execute this command.

Code Address

Displays the code address of the selected function in a message box.

Note: Dragging and dropping from the Call window to the Memory window displays memory contents starting at the instruction pointer address of the selected entry in the Call window.

Pop-up menu

The pop-up menu in the Call window has the same commands as the Call window's Show menu (see previous section). To access the pop-up menu, press the right mouse button anywhere in the Call window.

[Figure 24-12 Pop-up menu for Call window


The Command Window

The Command window, shown in Figure 24-13, provides a CodeView-like command-line interface to the debuggers. To pass a command to the debugger from the Command window, type one of the CodeView commands or functions in Table 24-4 at the prompt in the Command window.

[Figure 24-13 Command window, showing its response to the help command]

To see a list of the supported commands, type help at a Command window prompt and press Enter.

Note: The Command window must be the active window for the debugger to accept commands typed into it.

	Table 24-4 Command window commands 

	Commands and 
	Function Keys 		Action 


	BC *			Clears all breakpoints set in the program 

	BD [number]		Disables the specified breakpoint 
				(numbering of breakpoints starts at 1) 

	BE [number]		Enables the specified breakpoint 
				(numbering of breakpoints starts at 1) 

	BL			Opens the Breakpoint window 

	BP [.[line]][address]	Sets an unconditional breakpoint on the 
				specified source line or on the specified 
				address given in the format appropriate 
				to the memory model 

	CLS			Clears the command window screen 

	DA [address]		Opens the Memory window to address 
				(displays in ASCII) 

	DB [address]		Opens the Memory window (displays in 
				bytes) 

	DD [address]		Opens the Memory window (displays in 
				double words) 

	DI [address]		Opens the Memory window (displays in 
				integers) 

	DL [address]		Opens the Memory window (displays in 
				long real numbers) 

	DS [address]		Opens the Memory window (displays in 
				short real numbers) 

	DT [address]		Opens the Memory window (displays in 
				10-byte real numbers) 

	DU [address]		Opens the Memory window (displays in 
				unsigned integers) 

	DW [address]		Opens the Memory window (displays in 
				words) 

	G			Executes a Go until Breakpoint 
				command 

	HELP			Displays a list of supported commands 
				and functions 

	K			Opens the Call window 

	L			Restarts the program being debugged 

	M			Opens the Memory window 

	P			Executes a Step Over command 

	Q			Closes the Command Line window 

	R			Opens the Register window 

	SA			Opens the Assembly window 

	SS			Opens the Source window 

	T			Executes a Step Into command 

	U[address]		Opens the Assembly window to the 
				specified address 

	V.[line_number]		Updates the Source window to the 
				specified line number 

	F2			Opens the Register window 

	F3			Switches between the Source and 
				Assembly windows 

	F5			Executes a Go Until Breakpoint 
				command 

	F7			Executes a Find Next command 

	F8			Executes a Step Into command 

	F9			Sets or clears a breakpoint 

	F10			Executes a Step Over command 

The Console Window

The Console window displays the output of a text-mode program that is being debugged. This is not a debugger window but rather an independent window under the control of the program.

The Console window looks and behaves much like a DOS Window. It cannot be closed during program execution; choose Stop Debugging to terminate the application.

In the debugger, the IDDE's Flip Screen option affects the Console window. (This option is described in Chapter 23, "Controlling and Configuring the Debugger.") When the debugger executes the text-mode program, the output is displayed in the foreground by default. Choosing Flip Screen allows you to control whether or not the debugger displays the Console window while it executes your program.

Note: Do not turn off the Flip Screen option when working in text mode unless the program you are working with has no output.

The Console window has no local menus.


The Data/Object Window

The Data/Object window, shown in Figure 24-14, displays the local variables, global (including static) variables, and objects in the program. The header line indicates the function or module for the local or global variables that are displayed. Each line in the Data/ Object window shows a different variable (or element of a variable), together with its name, value, and type.

This view makes it easy to examine the elements of structures and arrays, as well as the contents of pointers and sets. Use the Data/ Object window to set watchpoints on data or to modify data. You can view a graphical representation of any data structure using the Graphic Data window, described later in this chapter.

[Figure 24-14 Data/Object window

The Module and Call windows can update the Data/Object window to display global and local data, respectively. After the variable information is displayed in the Data/Object window, you can examine and modify it.

The Data/Object window supports the display of C++ data type names either in the form member::class or in the form class::member. To control how these data type names are displayed, use the Alternate Class Display option in the Debugger Settings dialog box described in Chapter 23, "Controlling and Configuring the Debugger."

If you didn't select a module or function to show data for, the Data/Object window displays the message:

	No data context selected 
If the debugger attempts to show local data for a function that does not have any local data, the Data/Object window displays the global data of the module the function resides in. If there is no local or global data available to view, the Data/Object window displays the message:
	No global data 
Before execution has started or after it has terminated, the Data/ Object window displays the message:
	No local data (no call chain) 
Table 24-5 shows the Data/Object window commands.
	Table 24-5 Data/Object window commands 

	Menu	Menu Item				Shortcut 
	Find	In Current Scope			none 
		In All Modules				Ctrl+F 
		Next					F3 
	View	Child/Contents				Ctrl+C 
		Parent					Ctrl+P 
		Right (Next Element)			Ctrl+R 
		Left (Prev. Element)			Ctrl+L 
		Specific Index				Ctrl+I 
		Variable Level				Ctrl+V 
		Local/Global Data			Ctrl+X 
		Methods in Class			none 
	Show	Graphic Data Structure			Ctrl+G 
		Memory					Ctrl+E 
		Source of Method			none 
		Address					Ctrl+A 
	Expr	Evaluate Expression			none 
		Convert Decimal to Hex			none 
		Convert Hex to Decimal			none 
	Bpt	Set/Clear Breakpoint on Method		F9 
		Set Conditional Breakpoint on Method	Ctrl+B 
		Clear All Breakpoints			none 
	Watch	Set Watchpoint				Ctrl+W 
		Clear Watchpoint			none 
		Clear All Watchpoints			Ctrl+K 
	ShowAs	Show as Original Type			none 
		Show Value in Hex			Ctrl+H 
		Show Value with Type			Ctrl+T 
		Show Pointer as Array			none 
		Examine String Pointer			Ctrl+S 
		Show Char Ptrs as Strings		none 
	Modify						N/A 
	Inspect!					N/A 
	New!						N/A 
The menu items in the Data/Object window are described below.

Find menu

Find menu commands locate variables in the current scope and in all modules.

[Figure 24-15 Data/Object window Find menu

In Current Scope

Displays a dialog box that allows you to enter the name of the variable to find. Enter the name of the variable (or field) for which you want to search, and press Enter. The standard wildcards (* and ?) are supported in the name specification; case is significant. The debugger searches in the current scope for the variable and selects the line with that variable in the Data/Object window. If there is more than one local variable with the same name, you can continue the search using Next.

In All Modules

Displays a dialog box that allows you to enter the name of the variable to find. Enter the name of the global variable (or field) you want to search for and press Enter. The standard wildcards (* and ?) are supported in the name specification; case is significant. The debugger searches all the modules for the variable and selects that line in the Data/Object window. If there is more than one global variable with the same name, continue the search using Next.

Next

Repeats the last search executed using a Find command.

View menu

Commands in the View menu let you navigate within data structures and arrays, toggle between displaying local and global data, and toggle the inclusion of methods in the display.

[Figure 24-16 Data/Object window View menu

Child/Contents

Displays the next level of the data structure beneath the selected data structure, allowing you to navigate down through arrays, structures, and pointers to view their elements. You may also double-click on a data item to execute the Child/Contents command on it. This command operates in the following manner: Note: For faster compilation, Digital Mars C++ can optionally compile C++ modules without class debugging information. However, you cannot view objects (instances of classes) or structures in such modules unless you recompile with class debugging information.

Parent

Displays the parent data structure of the current data structure. This command lets you move up a level in the data structure you previously moved down in with the Child/Contents command. When the Parent command is executed, the Data/Object window displays the structure one level up from the current data structure.

Right (Next Element)

Displays the next index of the current array. If you use the Child/Contents command to view the elements of an array, use the Right (Next Element) command to quickly select the next index in the array.

Left (Prev. Element)

Displays the previous index of the current array. If you used the Child/Contents command to view the elements of an array, use this command to quickly select the previous index in the array.

Specific Index

Specifies a particular index to view in the array. If you used the Child/Contents command to view the elements of an array, this command lets you quickly view the contents of a specific index in the array.

When this command is executed, the debugger prompts you to enter an expression to be evaluated. The result of the evaluation becomes the index of the newly displayed or selected array element.

Note: Use any one of the commands Right (Next Element), Left (Prev. Element), or Specific Index when you are viewing the fields of an array element. The Data/Object window displays the fields of the array with the new index.

For example, if there is an array of records and the record fields of the first element of the array are displayed, you can use the Right (Next Element) command to directly view the record fields of the second element of the array. This is faster than executing the Parent command, changing the selection to the next index, and executing the Child/Contents command.

Variable Level

Returns to the top nesting level (the variable level) of the data display. Use this command if you chose the Child/Contents command to descend into a data structure and want to return to the top variable level without repeatedly using the Parent command.

Local/Global Data

Toggles the data view between the current function's local variables and the global variables of the current module. The command toggles between the local data of a function and the global data of the module that contains the function.

Methods in Class

Toggles on and off the option to view the methods in C++ objects. Use this command if you don't want to view methods mixed with data items.

Show menu

The Show menu is used to update the Graphic Data, Memory, and Source windows to reflect the selected item in the Data/Object window. It also is used to display the location- an address or a CPU register -- of the currently selected item.

[Figure 24-17 Data/Object window Show menu

Graphic Data Structure

Select this menu item to display a graphic data representation of the selected variable. A drawing of the selected data structure is displayed in the Graphic Data window. This command provides a visual overview of your structure, in addition to the data browsing capabilities provided by the Data/Object window. For information about the Graphic Data display, see the section "The Graphic Data Window," later in this chapter.

Dragging and dropping from the Data/Object window to the Graphic Data window also executes this command.

Note: The Graphic Data Structure command is disabled if there are not enough Windows resources available to generate a view for the Graphic Data window.

Memory

Updates the Memory window to display the memory location of the variable selected in the Data/Object window. Dragging and dropping from the Data/Object window to the Memory window also executes this command.

Source of Method

Updates the Source window to the location of the code for the method highlighted in the Data/Object window.

Address

Displays the memory location of the selected variable at the left of the menu bar. If the variable is a register variable, this command displays the register( s) it is contained in on the status line.

Expr menu

Commands in the Expr menu let you evaluate expressions, change the value of a variable, and convert values between decimal and hexadecimal.

[Figure 24-18 Data/Object window Expr menu

Evaluate Expression

Opens an Expression dialog box. In the text field, enter the expression you want to evaluate. Use this command to modify a variable.

See Appendix A, "Expression Evaluation," for more information on entering and evaluating expressions.

Convert Decimal to Hex

Converts a decimal value to hexadecimal and displays the result on the status line.

Convert Hex to Decimal

Converts a hexadecimal value to decimal, and displays the result on the status line.

Bpt menu

The Bpt menu contains commands to set and clear breakpoints on methods in the Data/Object window. Refer to Chapter 23, "Controlling and Configuring the Debugger," for details on the types of breakpoints that can be set.

[Figure 24-19 Data/Object window Bpt menu

Set/Clear Breakpoint on Method

Sets a breakpoint on the method currently selected in the Data/Object window or clears a breakpoint that is currently set in the selected method. Dragging and dropping from the Data/Object window to the Breakpoint window also executes this command.

Set Conditional Breakpoint on Method

Sets a conditional breakpoint in the method currently highlighted in the Data/Object window.

Clear All Breakpoints

Clears all breakpoints in the program.

Watch menu

Commands in the Watch menu are used to control data watchpoints in the program. When a watchpoint is set on a variable, a change in the variable's value or the implementation of a read access to the variable causes the program to stop near the point at which the variable was accessed. This feature helps you locate data modifications or accesses that may be incorrect. Refer to the section "Working with Watchpoints," in Chapter 23, "Controlling and Configuring the Debugger," for more information about watchpoints.

[Figure 24-20 Data/Object window Watch menu

Set Watchpoint

Sets a data watchpoint on the selected variable. The debugger displays a Set Watchpoint dialog box. This dialog box allows you to choose whether to trigger the watchpoint on a read access or on a write access. When executing a Go command, the debugger stops execution of the program as soon as the program accesses the specified variable.

Dragging and dropping from the Data/Object window to the Watchpoint window also executes this command.

Clear Watchpoint

Clears a watchpoint set on a selected variable. This command reverses the effect of the Set Watchpoint command.

Clear All Watchpoints

Clear all watchpoints set in the program.

ShowAs Menu

ShowAs menu commands let you change the data type that a variable is displayed as.

[Figure 24-21 Data/Object window ShowAs menu

Show as Original Type

Displays a variable using its actual type after it has been typecast to another type. Executing Show Value in Hex on an already cast variable has the same effect.

Show Value in Hex

Toggles the view between the originally declared type of the variable and its hexadecimal display.

Show Value with Type

Changes a variable from its original type to another named type.

Note: The / symbol to the left of the variable name indicates that the variable is cast to a different type.

When executing Show Value with Type, the debugger prompts you to enter the type name. If the type entered is not a predefined type, the debugger prompts you to enter the module in which that type is defined. The selected variable is then cast to that type. To reset the variable to its original type, choose Show as Original Type.

Show Pointer as Array

Displays the data pointed to as an array. This command allows you to browse dynamically allocated arrays by displaying the data pointed to as an array.

Examine String Pointer

Displays the string that the selected character pointer points to in a message box. To view the string, select the pointer and execute this command.

Show Char Ptrs as Strings

Updates the Data/Object window to display the character strings to which character pointers point.

Modify!

Modifies the contents of the selected variable or field. Select the variable or field you want to modify in the Data/Object window, then execute this command. The debugger prompts you to enter an expression to modify the variable.

The expression must evaluate to a value of the same size as the variable, but not necessarily to the same type. Refer to Appendix A, "Expression Evaluation," for more information.

Inspect!

Creates a new line for the selected variable in the Inspector window. Dragging and dropping a variable from the Data/Object window to the Inspector window has the same effect.

New!

Creates a new, empty Data/Object window.

Pop-up menu

The Data/Object window pop-up menu provides quick access to frequently used menu choices in the Data/Object window local menu. The View, Show, ShowAs, Breakpoint, and Watch commands access submenus that have some of the commands available from the similarly named menus on the Data/Object window menu bar. The Modify and Inspect commands function the same way as do the similarly named commands in the local menu.

[Figure 24-22 Pop-up menu for the Data/Object window


The Function Window

The Function window, shown in Figure 24-23, displays the functions in your program, the names of the modules in which they are defined, their addresses, and their memory model type (near or far- applicable only in 16-bit programs). Commands let you find functions and modules, set breakpoints on functions, and examine the local and global data of any function in the program.

[Figure 24-23 Function window

The Function window shows information for one function per line. The first column contains the breakpoint indicator. If a breakpoint has been set on or in the function, the first column contains a solid black diamond. If execution has stopped at a breakpoint in the function, the first column contains the outline of a diamond with a line through it.

The next column contains the execution indicator. If the program has executed into the function, the column contains a right arrow.

Next is the name of the function, followed by the name of the module in which the function is defined, the address of the function, and- if a 16-bit program is being debugged- the memory model type (near or far).

The Function window has four local menus: Find, Show, Bpt, and View, listed in Table 24-6.

	Table 24-6 Function window commands 

	Menu	Menu Item			Shortcut 
	Find	Function			Ctrl+F 
		Module				Ctrl+M 
		Next				F3 
	Show	Source				Ctrl+S 
		Local Data			Ctrl+D 
		Global Data			Ctrl+G 
		Assembly			Ctrl+A 
		All				Ctrl+L 
	Bpt	Set/Clear Breakpoint		F9 
		Set Conditional Breakpoint	Ctrl+B 
		Clear All Breakpoints		Ctrl+K 
		Set On All Functions		none 
		Clear From All Functions	none 
	View	Current Module			none 
		All Modules			none 
The menu items in the Function window are described below.

Find menu

Find menu commands locate functions and modules in the Function window.

[Figure 24-24 Function window Find menu

Function

Locates a specific function in the Function window. When the command is executed, the debugger prompts you to enter the name of the function you want to find. The standard wildcards (* and ?) are supported in the name specification; case is significant. If the function is found, its entry is selected.

Module

Searches for a module in the Function window. When the command is executed, the debugger prompts you to enter the name of the module you want to find. The standard wildcards (* and ?) are supported in the name specification. This command is not case sensitive. If the module is found, its entry is selected.

Next

Repeats the last search executed, using a Find command.

Show menu

The Show menu contains commands that update the Source, Data, and Assembly windows for any function in the Function window.

[Figure 24-25 Function window Show menu

Source

Updates the Source window and displays the selected function's source code. It is used to view the source code of any function in the program. If the debugger cannot locate the source file, a dialog box prompts you to enter its filename (including a path, if necessary). Dragging and dropping from the Function window to the Source window also executes this command.

Local Data

Updates the Data/Object window and displays the selected function's local data. If the selected function is not found in the call chain (and therefore cannot have any local data), the debugger displays an error message. Dragging and dropping from the Function window to the Data/Object window also executes this command.

Global Data

Updates the Data/Object window and shows the global data declared in the selected function's module. Dragging and dropping a module from the Project window to the Data/Object window also executes this command.

Assembly

Updates the Assembly window to the code address of the function. Dragging and dropping from the Function window to the Assembly window also executes this command.

Note: You can drag and drop from the Function window to the Memory window to show the starting address in which the code for the selected function resides.

All

Updates the Source, Data, and Assembly windows. You can also execute this command by double-clicking on a function entry.

Bpt menu

The Bpt menu contains commands to set and clear breakpoints in the Function window. Refer to Chapter 23, "Controlling and Configuring the Debugger," for details on the types of breakpoints that can be set.

[Figure 24-26 Function window Bpt menu

Set/Clear Breakpoint

Sets an unconditional breakpoint at the entry point of the selected function. The next time any Go command is executed (except for the Go until End command), execution of the program stops when it reaches this line. If a breakpoint is already set on the selected function, this command clears it.

Dragging and dropping from the Function window to the Breakpoint window also executes this command.

Set Conditional Breakpoint

Displays the Set Code Breakpoint dialog box, which you use to set a conditional breakpoint at the entry point of the selected function.

Clear All Breakpoints

Clears all breakpoints set in your program.

Set On All Functions

Sets breakpoints on all functions currently being viewed in the Function window.

Clear From All Functions

Clears any breakpoints set in the Function window.

View menu

The View menu contains commands for functions that you choose to include in the Function window. A checkmark indicates the currently selected mode.

[Figure 24-27 Function window View menu

Current Module

Causes the Function window to redraw and display only those functions belonging to the module you dropped into the Function window.

All Modules

Selects all functions contained in the program and displays them in the Function window.

Pop-up menu

The pop-up menu of the Function window provides easy access to commands also found in the Show and Bpt menus, described earlier.

[Figure 24-28 Function window pop-up menu


The Graphic Data Window

The Graphic Data window, shown in Figure 24-29, is a sophisticated tool that lets you display a graph of a simple or complex data structure. The structure can be referenced by any variable defined in your program. The menu commands in the Graphic Data window let you view information and zoom in on specific parts of the graph.

[Figure 24-29 Graphic Data window

Data structures are displayed as boxes connected by lines or arrows. Each box represents a particular data object, each line a relationship between data objects, and each arrow a pointer relationship between data objects.

Data objects are items in the structure that can have either a value or a meaning. Any of the following variables can be data objects: simple types, pointers, arrays, structures, or objects (class instances).

To display a graph, select a variable in the Data/Object window and choose the Graphic Data Structure command from the Show menu. This variable becomes the starting (or root) data object of the graph. When you open the Graphic Data window, the root data object is displayed.

The graph generated from the root data object can be either simple or complex. Simple graphs are created when the form of the structure is a singly linked list. Complex graphs are created when the form of the structure is a tree (with multiple pointers of the same type). If the graph cannot be displayed as a simple graph, it is displayed as a complex graph.

Simple graphs

Simple graphs (and simple portions of graphs) can be fully displayed in the Graphic Data window. An overview of the entire graph is visible after it is created. You can zoom in and scroll through the graph to examine the information in more detail. A simple graph may contain nodes that hide subgraphs, as in the case of a node representing a tree with multiple pointers of the same type. Use the Show Subgraph command- that is, the Subgraph command in the Show menu- to view the subgraph.

Complex graphs

Complex graphs are displayed initially in the Graphic Data window as a box representing the root data object of a subgraph. An object represents a complex subgraph when the variable name in the box is surrounded by vertical bars. To view the subgraph of a complex graph object, choose the Show Subgraph command.

When viewing a complex subgraph, each object in the complex structure is displayed. You can zoom in and scroll through the graph to examine the information more closely.

If you are viewing a complex subgraph and want to view its parent graph, choose the Show Parent command.

Creating a graph might take a few seconds, depending on the speed of your machine, the amount of memory available, and the complexity of the data structure. The menu commands of the Graphic Data window are not available until a graph is displayed in the Graphic Data window.

Each object in the graph displays information about itself, such as its name or value. To obtain more information about an object, use the Show Information command. Note that if an object is too small to display its information, you must zoom in on it before the information is displayed.

The Graphic Data window has three local menus: Show, Zoom, and Others.

	Table 24-7 Graphic Data Window commands 

	Menu	Menu Item	Shortcut 
	Show	Information	Ctrl+A 
		Subgraph	Ctrl+S 
		Parent		Ctrl+P 
	Zoom	Zoom In		Ctrl+I 
		Zoom Out	Ctrl+U 
		Zoom Reset	Ctrl+R 
	Others	Clear Graph	Ctrl+C 
The menu items in the Graphic Data window are described below.

Show menu

The Show menu displays a complex subgraph, additional information about an object, and the parent graph of a complex subgraph.

[Figure 24-30 Graphic Data window Show menu

Note: To use the following commands on a particular object, first click on the object, then execute the command.

Information

Displays in a message box the object name and its type information or value for the selected object. Select the object by clicking on it.

Subgraph

Causes the Graphic Data window to display the associated subgraph of the object when a complex subgraph object is selected.

Parent

Displays the parent graph of the current subgraph. When viewing a complex subgraph, this command lets you return to the parent graph.

Zoom menu

Zoom menu commands control the view magnification of the selected object.

[Figure 24-31 Graphic Data window Zoom menu

Zoom In

Zooms in on the selected object. Select the object by clicking on it, then execute the command. The window redraws, enlarging the selected object. Double-clicking on an object also zooms in.

Zoom Out

Zooms out from the selected object. Select the object by clicking on it, then execute this command. You can also double-click the right mouse button on an object to zoom out.

Zoom Reset

Resets the display of the graph to its initial state. Use this command if you have zoomed or scrolled the display of the graph and want to restore the graph to its original state.

Others

The Others menu contains the Clear Graph command.

[Figure 24-32 Graphic Data window Others menu

Clear Graph

Clears the current graph from the Graphic Data window. In addition, this command frees the memory used by the graphical representation of the current data structure you are viewing. If the debugger is running low on memory, this command frees up the memory used by the Graphic Data window.

The Inspector Window

The Inspector window, shown in Figure 24-33, is similar in function to the Data/Object window, allowing you to display and modify variables and objects. Unlike the Data/Object window, it can display any mix of local and global variables. It can also display the same variable more than once, a useful feature if you want to view the same variable in different ways- for example, in hexadecimal, as an int, and as a pointer- all at the same time. With the Inspector window you can select several local variables from a function, or several global variables, and view them all simultaneously.

[Figure 24-33 Inspector window

Initially the Inspector window is empty. You add variables to it by dragging them from the Data/Object window, or by selecting a variable in the Data/Object window. then selecting Inspect! from the Data/Object window's local menu. You can also add multiple instances of the same variable to the Inspector window. To delete an instance of a variable from the Inspector window, select Delete! from the Inspector window's menu.

	Table 24-8 Inspector window commands 

	Menu	Menu Item		Shortcut 

	Find	Entry			none 
		Next			F3 
	View	Child/Contents		Ctrl+C 
		Parent			Ctrl+P 
		Right (Next element)	Ctrl+R 
		Left (Prev. element)	Ctrl+L 
		Specific Index		Ctrl+I 
		Variable Level		Ctrl+V 
	Show	Graphic Data Structure	Ctrl+G 
		Memory			Ctrl+E 
		Source of Method	none 
		Address			Ctrl+A 
	ShowAs	Show Pointer as Array	none 
		Show Value in Hex	Ctrl+H 
		Show Value with Type	Ctrl+T 
		Show as Original Type	none 
		Examine String Pointer	Ctrl+S 
		Show Char Ptrs as Strings none 
	Watch	Set Watchpoint		Ctrl+W 
		Clear Watchpoint	none 
		Clear All Watchpoints	Ctrl+K 
	Modify!				Alt+M 
	Delete!				Alt+D 
The menu items in the Inspector window are described in the next section.

Find Menu

Commands in the Find menu let you search for all instances of a variable in the Inspector window.

[Figure 24-34 Inspector window Find menu

Entry

Displays a dialog box that allows you to enter the name of a variable to find. Enter the name of the variable (or field) for which you want to search, and press Enter. The standard wildcards (* and ?) are supported in the name specification; case is significant. The debugger searches in the current scope for the variable and selects that line in the Inspector window. If there is more than one local variable with the same name, continue the search by using Next.

Next

Repeats the last search executed using a Find command.

View Menu

Commands in the View menu let you navigate within data structures and arrays.

[Figure 24-35 Inspector window View menu

Child/Contents

Displays the level of the data structure one level down from the selected data structure. This command lets you navigate down through arrays, structures, and pointers to view their elements. You can also double-click on a data item to execute the Child/Contents command on it. This command operates in the following manner: Note: For faster compilation, Digital Mars C++ can optionally compile C++ modules without class debugging information. However, you cannot view objects or structures in such modules unless you recompile with class debugging information.

Parent

Displays the parent data structure of the current data structure. This command lets you move up a level in a data structure that you previously moved down in with the Child/Contents command. When the Parent command is executed, the Inspector window displays the structure one level up from the current data structure.

Right (Next Element)

Displays the next index of the current array. If you used the Child/Contents command to view the elements of an array, use the Right (Next Element) command to quickly select the next index in the array.

Left (Prev. Element)

Displays the previous index of the current array. If you used the Child/Contents command to view the elements of an array, use this command to quickly select the previous index in the array.

Specific Index

Specifies a particular index to view in the array. If you used the Child/Contents command to view the elements of an array, use this command to quickly view the contents of a specific index in the array.

When this command is executed, the debugger prompts you to enter an expression to be evaluated. The result of the evaluation becomes the index of the newly displayed array element.

Note: Use any one of the commands Right (Next Element), Left (Prev. Element), or Specific Index when you are viewing the fields of an array element. The Inspector window displays the fields of the array with the new index.

For example, if there is an array of records and the record fields of the first element of the array are displayed, use the Right (Next Element) command to directly view the record fields of the second element of the array. This is faster than executing the Parent command, changing the selection to the next index, and executing the Child/Contents command.

Variable Level

Returns to the top nesting level (the variable level) of the data display. Use this command if you chose the Child/Contents command to descend into a data structure and want to return to the top variable level without repeatedly using the Parent command.

Show Menu

The Show menu is used to update the Graphic Data Memory and Source windows to reflect the selected item in the Inspector window. It is also used to display the location of an address or a CPU register of the currently selected item.

[Figure 24-36 Inspector window Show menu

Graphic Data Structure

Displays a graphic data representation of the selected variable. A drawing of the selected data structure is displayed in the Graphic Data window. This command provides a visual overview of your structure in addition to the data browsing capabilities provided by the Inspector window. For information about the Graphic Data display, see the section "The Graphic Data Window" later in this chapter.

Dragging and dropping from the Inspector window to the Graphic Data window also executes this command.

Note: The Graphic Data Structure command is disabled if there are not enough Windows resources available to generate a view for the Graphic Data window.

Memory

Updates the Memory window to display the memory location of the variable selected in the Inspector window. Dragging and dropping from the Inspector window to the Memory window also executes this command.

Source of Method

Updates the Source window to the location of the code for the method highlighted in the Inspector window.

Address

Displays in a message box the memory location of the variable on the selected line. If the variable is a register variable, this command displays the register( s) it is contained in on the status line.

ShowAs Menu

The commands in this menu change the way the Inspector window displays variables.

[Figure 24-37 Inspector window ShowAs menu

Show Pointer as Array

Displays the data pointed to by the variable on the selected line as an array. This command allows you to browse dynamically allocated arrays by displaying the data pointed to as an array.

Show Value in Hex

Changes to hexadecimal the display type of a variable on the selected line. The command toggles the view between the originally declared type of the variable and its hexadecimal display. If the Inspector window displays the same variable more than once, only one instance of this variable is affected.

Show Value with Type

Changes a variable from its original type to another named type. If the Inspector window displays the same variable more than once, only the selected instance of this variable is affected.

Note: The / symbol to the left of the variable name indicates that the variable is cast to a different type.

When executing Show Value with Type, the debugger prompts you to enter the type name. The variable on the selected line is then cast to that type. To reset the variable to its original type, choose Show as Original Type from the ShowAs menu.

Show as Original Type

Displays a variable using its actual type after it has been typecast to another type. Executing Show Value in Hex on an already cast variable has the same effect.

Examine String Pointer

Displays the string that the selected character pointer points to in a message box. To view the string, select a line with a pointer variable and execute this command.

Show Char Ptrs as Strings

Updates the Inspector window to display the character strings to which the character pointers point.

Watch menu

Commands in the Watch menu are used to control data watchpoints in the program. When a watchpoint is set on a variable, a change in the variable's value or in the implementation of a read access to the variable causes the program to stop near the point at which the variable was accessed. This feature helps locate data modifications or accesses that may be incorrect. Refer to Chapter 23, "Controlling and Configuring the Debugger," for more information about watchpoints.

[Figure 24-38 Inspector window Watch menu

Set Watchpoint

Sets a data watchpoint on the selected variable and causes the debugger to display a Set Watchpoint dialog box. This dialog box allows you choose whether to trigger the watchpoint on a read access or on a write access. When executing a Go command, the debugger stops execution of the program as soon as the program accesses the specified variable.

Dragging and dropping from the Inspector window to the Watchpoint window also executes this command.

Clear Watchpoint

Clears a watchpoint set on a selected variable. This command reverses the effect of the Set Watchpoint command.

Clear All Watchpoints

Clears all watchpoints set in the program.

Modify!

Modifies the contents of the selected variable or field. First select the variable or field you want to modify in the Inspector window before executing the command. The debugger prompts you to enter an expression to modify the variable.

The expression must evaluate to a value of the same size as the variable, but not necessarily of the same type. Refer to Appendix A, "Expression Evaluation," for more information.

Delete!

Deletes the selected line. If the variable or object that is displayed on this line is also displayed on other lines in the Inspector window, these lines are not affected.

Pop-up menu

The Inspector window pop-up menu provides quick access to frequently used menu choices in the Inspector window local menu. The View, Show, ShowAs, and Watch commands access submenus that have some of the commands that are available from the similarly named menus on the Inspector window menu bar. The Modify and Delete commands function the same way as do the similarly named commands in the local menu.

[Figure 24-39 Inspector window pop-up menu


The Memory Window

The Memory window, shown in Figure 24-40, displays the memory contents of a given address in different formats. Memory window commands modify a memory location, set memory watchpoints, and set the memory address to view.

[Figure 24-40 The Memory window

The Memory window shows the contents of a range of memory addresses. You can display memory in 11 different formats, ranging from hexadecimal bytes to real numbers. To display memory, either specify a particular address to view or view the address of a variable by using the Data/Object window's Show Memory command.

In addition to examining a particular address, you can scroll through the Memory window to view all the memory in a segment. In 32-bit flat memory, you can scroll through your application's entire address space. You may not have access to certain memory areas that are restricted to your application. In that case, the memory contents are displayed as Xs. You can modify memory and set memory watchpoints as well.

The Memory window in the debugger has three local menus: View, Watch, and Others.

	Table 24-9 Memory window commands 

	Menu	Menu Item		Shortcut 
	View	Character		Ctrl+H 
		Text			Ctrl+T 
		Byte			Ctrl+B 
		Word			Ctrl+R 
		Unsigned		Ctrl+U 
		Integer			Ctrl+I 
		Long Integer		Ctrl+G 
		Short Real		Ctrl+S 
		Long Real		Ctrl+E 
		Extended Real		Ctrl+X 
		Address			Ctrl+D 
	Watch	Set Watchpoint		Ctrl+W 
		Clear Watchpoint	none 
		Clear All Watchpoints	Ctrl+K 
	Others	Modify			Ctrl+M 
		Set Memory Address	Ctrl+A 
		Set Live Memory Expression Ctrl+L 
		Show Child		Ctrl+C

View menu

The View menu sets the display mode of the Memory window. To set the display format, select one of the formats from the menu. The currently selected format is displayed in the upper-left corner of the window.

[Figure 24-41 Memory window View menu

Character

Sets the display format to character. The contents of memory are displayed as ASCII characters enclosed in single quotes. If an address does not contain a standard U. S. ASCII character, the octal value of the character is displayed.

Text

Sets the display format to complete text. The contents of memory are displayed as characters in the PC's code page. Each memory value is displayed as a single character. The complete extended character set is used to display the text. Values that cannot be displayed are represented by dots.

Byte

Sets the display format to hexadecimal bytes. The contents of memory are displayed as 2-digit hexadecimal values.

Word

Sets the display format to hexadecimal words. The contents of memory are displayed as 4-digit hexadecimal values.

Unsigned

Sets the display format to unsigned integers. The contents of memory are displayed as 2-byte unsigned integers in the range of 0 to 65535.

Integer

Sets the display format to signed integers. The contents of memory are displayed as 2-byte signed integers in the range of -32768 to 32767.

Long Integer

Sets the display format to signed long integers. The contents of memory are displayed as 4-byte signed integers in the range of -2147483648 to 2147483647.

Short Real

Sets the display format to short real numbers. The contents of memory are displayed as 4-byte, single-precision real numbers. The 4-byte memory ranges that are not valid 4-byte reals are denoted by the phrase "not a real."

Long Real

Sets the display format to extended real numbers. The contents of memory are displayed as 8-byte, double-precision real numbers.

Extended Real

Sets the display format to long real numbers. The contents of memory are displayed as 10-byte, extended-precision real numbers.

Address

Sets the display format to addresses. The contents of memory are displayed as addresses of the form segment: offset. If you are running in 32-bit flat memory space, the addresses are displayed as 8-digit hexadecimal numbers.

Watch menu

The commands on the Watch menu control memory watchpoints in the program. After you set a watchpoint on a memory location, a write to or a read from that location causes the program to stop near the point where the access occurred. This feature allows you to catch memory modifications that may be incorrect. For more information about watchpoints, refer to Chapter 23, "Controlling and Configuring the Debugger."

[Figure 24-42 Memory window Watch menu

Set Watchpoint

Sets a memory watchpoint on the selected memory location. Dragging and dropping from the Memory window to the Watchpoint window also executes this command.

Clear Watchpoint

Clears a watchpoint set on the selected memory location, reversing the effect of the Set Watchpoint command on the location.

Clear All Watchpoints

Clears all watchpoints set in the program.

Others menu

Use the Others menu commands to modify data, to specify the direct memory address to display, to link the memory address to an expression, or to set the memory address through an address in memory.

[Figure 24-43 Memory window Others menu

Modify

Displays an Expression dialog box modifying the contents of the selected memory location.

Set Memory Address

Updates the Memory window to the address specified. When a debugger dialog box prompts you for an address, enter the hexadecimal address.

Type the address in the form 0Xnnnn:0Xnnnn to specify a 16-bit segment:offset pair; type the address in the form 0Xnnnnnnnn, where nnnnnnnn is an 8-digit hexadecimal number, to specify a 32-bit address. For 16-bit code, to view another offset in the same segment ac is currently displayed, enter only the offsed location. The Memory window then displays the contents of memory at the new location.

Set Live Memory Expression

Links the address displayed in the Memory window to an expression (such as CS:IP or SS:SP) and causes the debugger to display an Expression dialog box. Each time control returns to the debugger after a Go command, the expression is evaluated and the result is used to update the memory location to display.

Show Child

Sets the Memory window display address to the location contained in the currently selected Memory window location. (The Memory window must be displaying memory in the Address format.)

Pop-up menu

The Memory window pop-up menu provides quick access to frequently used menu choices in the Memory window local menu. The Set Watchpoint, Clear Watchpoint, Modify, and Show Child commands function the same way as do the similarly named commands in the local menu.

[Figure 24-44 Memory window pop-up menu


The Output Window

The Output window is used to display the messages generated by the compiler, the linker, and the IDDE. For example, errors and warnings generated by the compiler when it builds your code are displayed in the Output window.

[Figure 24-45 Output window

The Output window's local menus are described below.

	Table 24-10 Output window menu commands 

	Menu	Menu Item	Shortcut 

	Edit	Copy All	none 
		Clear		none 
	Stop!			none 

Edit

The commands on the Edit menu preserve and erase the contents of the Output window.

[Figure 24-46 Output window Edit menu

Copy All

Copies the contents of the Output window to the Clipboard.

Clear

Clears the Output window.

Stop!

Choosing this menu causes the IDDE to stop a build or a parse operation running in the background.

The Project Window

The Project window, displays in its left pane the names of the project and any subprojects that form your program; in its right pane it shows the source and object modules that comprise the project or subproject selected on the left. Entries in the right pane can be sorted along any of the columns displayed in that pane by clicking on the column title; the title of the column along which entries are sorted is shown in boldface.

[Figure 24-47 Project window

Two columns in the right pane contain meaningful information only when the IDDE is in debugging mode; otherwise they display N/A. The EXE/DLL column indicates the executable to which a module belongs. The Virtual column indicates whether or not a module whose debug information has been loaded has not had its code loaded. You can set breakpoints for such a module; however, you cannot set watchpoints because the module's data has not yet been loaded.

The icon to the left of each entry in the Project window's right pane contains status information about the module or file:

When the right pane is sorted according to name, the module entries in the Project window are listed in alphabetical order by extension within directories, with the executable name to the right.

The Project window in the debugger has four local menus: Parse, View, Trace, and VCS (shown in Table 24-11).

	Table 24-11 Project window commands

	Menu	Menu Item	Shortcut

	Parse	Update All	none
		Parse All	none
		Parse File	none
		Unparse File	none
		Stop Parse	none
	View	Source		Ctrl+R
		Global Data	Ctrl+G
		Functions	Ctrl+U
		Assembly	Ctrl+A
		All		Ctrl+L
		Code Address	none
	Trace	Enable		Ctrl+E
		Disable		Ctrl+D
		Enable All	none
		Disable All	none
	VCS	Configuration	none
		Get		none
		Put		none
		Merge		none
		Manager		none
		Settings	none
The menu items in the Project window are described below.

Parse menu

The Parse menu is not used during debugging. For more information about the commands on this menu, see Chapter 15, "More about Projects and Workspaces."

View menu

The View menu updates the Source and Data/Object windows to display the source code and global data of the selected module. It is also used to update the Assembly window to show the assembly code of the module, to update the Function window to show the functions in the module, and to display the starting code address of the module.

[Figure 24-48 Project window View menu

The commands in this menu are grayed out unless the selected file contains code. For example, they are grayed out for header files, .def files, and .res files.

Source

Updates the Source window to show the source code of the selected module. If the debugger cannot locate the source file, a dialog box prompts you to enter the path of the source file. Dragging and dropping from the Project window to the Source window also executes this command.

Note: To search for source files in different directories, include those directories in the DPATH environment variable.

[Figure 24-49 Project window View menu

Global Data

Updates the Data/Object window to show the global variables in the selected module. Use this command to view the global data of any module in the program. Dragging and dropping from the Project window to the Data/Object window also executes this command.

Functions

Updates the Function window to show the functions in the selected module. Dragging and dropping from the Project window to the Function window also executes this command.

Assembly

Updates the Assembly window to the starting code address of the module. Dragging and dropping from the Project window to the Assembly window also executes this command.

All

Updates the Source, Data, Function, and Assembly windows. Double-clicking on a module entry also executes this command.

Code Address

Displays a dialog box showing the code address of the first statement in a module.

Note: Dragging and dropping from the Project window to the Memory window displays memory starting from the code address of the selected entry in the Project window.

Trace menu

Sometimes you don't want to trace into a particular module or set of modules. The Trace menu contains commands that control whether the debugger can step into, set breakpoints in, or watch data in a particular module. By default, all modules in a program have tracing enabled.

While stepping through a program using the Go menu commands, the debugger does not stop the program in modules that have tracing disabled. To prevent stepping into a particular module, disable tracing for that module.

[Figure 24-50 Project window Trace menu

Enable

Enables tracing in the selected module.

Disable

Disables tracing in the selected module.

Enable All

Enables tracing in all program modules.

Disable All

Disables tracing in all program modules.

VCS menu

This menu is used to control the version control system and is not used during debugging. See Chapter 22, "Using Version Control," for more information.

Pop-up menus

The Project window provides a pop-up menu for each of its two panes. They are accessible by clicking on the left or the right side of the Project window. Most of the commands in these menus are generally not used during debugging. They are documented in detail in Chapter 15, "More about Projects and Workspaces."

[Figure 24-51 Project window pop-up menu

There are three items in the Don't Show submenu: Modules, Parsed, and Dependencies. When Modules is checked, the right pane excludes files explicitly added to the project. Checking Parsed excludes files added to the project only as a result of parsing. Checking Dependencies excludes files added to the project only as a result of building the project.


The Register Window

The Register window, shown in Figure 24-52, displays the CPU register values of the processor. If a math coprocessor is installed in the system, or if the CPU has a built-in floating-point unit (FPU), those floating-point register values are displayed as well. Commands are provided for changing the contents and the display mode of the registers.

[Figure 24-52 Register window

The Register window displays the registers either horizontally or vertically, and in either hexadecimal or decimal format. Select a specific register by clicking on it or by using the arrow keys. The Register window has two local menus, View and Others, listed in Table 24-12.

	Table 24-12 Register window commands 

	Menu	Menu Item		Shortcut 

	View	Hex			Ctrl+H 
		Decimal			Ctrl+D 
		Vertical/Horizontal	Ctrl+X 
	Others	Modify			Ctrl+M 
		Out Byte to Port	none 
		Out Word to Port	none 
		In Byte from Port	none 
		In Word from Port	none 

View menu

The View menu contains commands that switch the display mode of the registers between hexadecimal and decimal, and the display orientation between horizontal and vertical.

[Figure 24-53 Register window View menu

Hex

Sets the register display mode to hexadecimal. After this command is executed, register values are displayed as hexadecimal words. HEX is displayed in the status line.

Decimal

Sets the register display mode to decimal. After it is executed, register values are displayed as unsigned integers. DEC is displayed in the status line.

Vertical/Horizontal

Toggles the register orientation between vertical and horizontal. The chosen orientation persists from one session to the next.

Others menu

The Others menu commands modify the selected register.

[Figure 24-54 Register window Others menu

Modify

Opens the Expression dialog box to modify the selected register.

Out Byte to Port

Prompts for the I/O port number and a byte value. After you press Enter, the debugger executes an OUT instruction to the specified port.

Out Word to Port

Prompts you for I/O port number and a word value. After you press Enter, the debugger executes an OUT instruction to the specified port.

In Byte from Port

This command prompts you for the I/O port number and a byte value. After you press Enter, the debugger executes an IN instruction to the specified port.

In Word from Port

Prompts for the I/O port number and a word value. After you press Enter, the debugger executes an IN instruction to the specified port.

Pop-up menu

The pop-up menu of the Registers window contains the Modify command, described above in the Others menu.

The Source Window

The Source window, shown in Figure 24-55, displays the source code of a program. When you start debugging, the Source window changes from an editing to a debugging window.

In debugging mode, you can view or change the current execution position, manipulate source-level breakpoints, and set the Assembly window view to a particular source line in a Source window. See Chapter 6, "Editing Program Code," for information on editing in a Source window.

[Figure 24-55 Source window

Use any of the following methods to view the source file of a particular module:

The location of the selection line in the Source window also determines the current local scope for evaluation of local variables in the expression evaluator. Refer to Appendix A, "Expression Evaluation," for more information.

Several different status messages can appear in the Source window. If the source file cannot be found, the window displays the following message:

	Source file not found 
If there is insufficient debug information in the module, the Source window displays the following message:
	No source associated 
In debugging mode, the left margin of the Source window expands to a vertically bordered pane two columns wide that contains the breakpoint and execution indicators. If a breakpoint has been set on a particular line, the first column of the margin contains a flag (displayed as a circle on some systems) in the same row as the line on which the breakpoint has been set.

If a line contains a function call that has not yet returned, the second column contains an arrow. If execution has stopped at a breakpoint in the program, the line with the breakpoint is similarly marked with an arrow. Because it is the current line, it is also highlighted. (Refer to "Working with Breakpoints," in Chapter 23, "Controlling and Configuring the Debugger," for more information about breakpoints.)

The Source window has five local menus: File, Edit, Goto, Macro, and New!. The commands in the Macro menu also can be useful during debugging, because some Source window debugging commands can be recorded, edited, and played back. See Digital Mars C++ IDDE Help for more information on the Digital Mars BASIC scripting language. Some Goto commands also can be useful during the debugging session. The other menus contain commands that are generally applicable to editing. These are discussed in detail in Chapter 21, "Text Editor Reference."

Pop-up menu

The pop-up menu contains commands for executing the following: setting and clearing breakpoints, changing execution location, showing the code address of the current selection, updating the Assembly, Function, Memory, and Data/Object windows, and looking up the current value of a variable and locating the source for a particular number.

[Figure 24-56 Source window debugging mode pop-up menu

Commands in the Source window debugging mode pop-up menu are listed in Table 24-13.

	Table 24-13 Source window debugging mode pop-up menu 

	Menu Item		Shortcut 

	Set/Clear Breakpoint	none 
	Set Conditional Breakpoint none 
	Clear All Breakpoints	none 
	Go Until Line		none 
	Skip to Line		none 
	Show Assembly		none 
	Show Functions		none 
	Show Data		none 
	Show Memory		none 
	Show Code Address	none 
	Query Implementors	none 
	Query Value		none 
These Source window pop-up menu items are described below.

Set/Clear Breakpoint

Sets an unconditional breakpoint at the selected source line if no breakpoint is set on that line. The next time any Go command is executed (except for the Go until End command), execution of the program stops when it reaches that line. If a breakpoint is already set on the selected source line, this command clears it.

Move a breakpoint by dragging the flag (circle) in the left side to a new line, signifying that a breakpoint has been set on this line. Clear a breakpoint by dragging the flag out of the Source window and dropping it on the desktop.

You also can set an unconditional breakpoint by dragging a source line from the Source window to the Breakpoint window. It is possible to clear the breakpoint by dragging the source line it is set on into the Breakpoint window. You can perform these drag operations only if the Normal Selection for Debugging option on the Text page of the Editing/Browsing Options dialog box is unchecked.

Set Conditional Breakpoint

Sets a conditional breakpoint at the entry of the selected function. This command displays the Set Code Breakpoint dialog box for specifying the condition of the breakpoint. (Refer to "Conditional and delayed breakpoints," in Chapter 23, "Controlling and Configuring the Debugger," for more information about conditional breakpoints.)

Clear All Breakpoints

Clears all breakpoints in the current module.

Go until Line

Allows the program to run until execution reaches the current line, at which point execution halts and the debugger regains control. If the current line will not be executed again before the program terminates, this is equivalent to the Go until End command. Double-clicking on a line in the Source window also executes up to that line.

Skip to Line

Changes the execution location to the address of the selected source line. After you execute the program again, it resumes execution from the new location.

To use this command, select the source line on which you want execution to resume and choose Skip to Line from the pop-up menu.

If there is more than one source-level statement on that line, the debugger uses the first statement on the line.

After this command is executed, the code and instruction pointer registers are updated and the Source window shows the new execution location. This command simulates a jump instruction and lets you skip portions of code you don't want to execute.

Show Assembly

Updates the Assembly window to the code address of the current selection. If more than one source-level statement is on that line, the debugger uses the first statement on the line. You also can do this by dragging and dropping from the Source window to the Assembly window if the Normal Selection for Debugging option on the Text page of the Editing/Browsing Options dialog box is disabled.

Show Functions

Updates the Function window to show the functions in the current source module. You also can do this by dragging and dropping from the Source window to the Function window if the Normal Selection for Debugging option on the Text page of the Editing/Browsing Options dialog box is disabled.

Show Data

Updates the Data/Object window to show the data objects in the current scope. Choose this command when you want to see the local variables in the scope of the current source line. You also can do this by dragging and dropping from the Source window to the Data/ Object window if the Normal Selection for Debugging option on the Text page of the Editing/Browsing Options dialog box is disabled.

Show Memory

Updates the Memory window to display a range of memory, starting with the code address of the selected source line. You also can do this by dragging and dropping from the Source window to the Memory window if the Normal Selection for Debugging option on the Text page of the Editing/Browsing Options dialog box is disabled.

Show Code Address

Displays the code address of the selected line. If more than one source-level statement is on that line, the command prompts you to enter the statement number of the address you want to view, such as 1 or 2. If you don't enter a statement number, the debugger uses the first statement on the line.

Query Implementors

Displays the Class Editor showing the implementation of the selected member.

Query Value

Looks up the current value of the selected token and displays it on the status line.

Toolbar

The Source window, when in debugging mode, has a debugging toolbar that provides easy access to common debugging commands. Refer to Figure 24-57 for the debugging toolbar icons. The function of these icons is described below, in order, from left to right.

[Figure 24-57 Source window debugging mode toolbar]

Open:
Same as choosing Open from the File menu.
Toggle Breakpoint:
Same as choosing Set/Clear Breakpoint from the pop-up menu.
Conditional Breakpoint:
Same as choosing Set Conditional Breakpoint from the pop-up menu.
Query Value:
Same as choosing Query Value from the pop-up menu.
Find:
Same as choosing Find from the Edit menu.
Find Previous:
Searches backward in the file for search string.
Find Next:
Searches forward in the file for search string.
Play Macro:
Same as choosing Play Macro from the Macro menu.

The Spy Window

The Spy window, available only in the 16-bit and Win32s IDDEs, is shown in Figure 24-58. It lets you:

[Figure 24-58 Spy window

The Spy window has four local menus: File, Show, Bpt, and Commands, as listed in Table 24-14.

	Table 24-14 Spy window commands 

	Menu	Menu Item		Shortcut 

	File	Open			none 
		Close			none 
		Pause			none 
	Show	Window Proc Source	Ctrl+S 
		lParam Memory		Ctrl+E 
	Bpt	Set Breakpoint on Message	Ctrl+Z 
		Set Breakpoint		Ctrl+B 
		Clear All Breakpoints	Ctrl+K 
	Commands Spy Enabled		Ctrl+Y 
		Clear Spy Window	Ctrl+C 
		Specify Windows		Ctrl+W 
		Specify Messages	Ctrl+M 
		Post Message		Ctrl+P 
Menu items in the Spy window are described below.

File menu

The File menu contains commands for opening, closing, and pausing a message file.

[Figure 24-59 Spy window File menu

Open

Opens a message log file in which window messages are logged. The command prompts you to enter a filename. The log file is created, and all subsequent messages appearing in the Spy window are written to that file until you close or pause logging to the file.

Close

Closes a message log file so messages are no longer written to that file. To begin message logging again, open a file with the Open command.

Pause

Acts as a toggle switch that pauses message output to the message log file. To continue message logging to the file, execute the Pause command again. This command is checked when logging to the file is paused.

Show menu

The Show menu contains two commands, one to update the Source window to display the window procedure that handled a message, and the other to update the Memory window with the address specified by the lParam parameter of a message.

[Figure 24-60 Spy window Show menu

Window Proc Source

Updates the Source window to the location of the window procedure to which the selected message was delivered. Dragging and dropping from the Spy window to the Source window also executes this command.

lParam Memory

Uses the selected message's lParam parameter as an address and updates the Memory window to that address. The Memory window then displays the contents of the structure passed in the message.

Dragging and dropping from the Spy window to the Memory window also executes this command.

Bpt menu

The Bpt menu commands set and clear breakpoints on messages. (Refer to Chapter 23, "Controlling and Configuring the Debugger," for details about setting breakpoints.)

[Figure 24-61 Spy window Bpt menu

Set Breakpoint on Message

Sets a breakpoint on the message currently selected in the Spy window. Dragging and dropping from the Spy window to the Breakpoint window also executes this command.

Set Breakpoint

Displays a dialog box that lets you select a window and a message on which to set a breakpoint.

Clear All Breakpoints

Clears all breakpoints that have been set, whether unconditional or conditional.

Commands menu

The commands on this menu are used to enable and disable the spying of messages, to specify particular messages and windows to spy on, and to post messages to a window message queue.

[Figure 24-62 Spy window Commands menu

Spy Enabled

Enables or disables the spying of messages. A checkmark is displayed when message spying is enabled.

Clear Spy Window

Clears any messages logged in the Spy window.

Specify Windows

Specifies windows you want to spy on. A dialog box prompts you to select or deselect windows to spy on when you choose this command. If the specified window does not exist, the debugger watches for and activates message spying after its creation.

Specify Messages

Specifies which messages you want to spy on. A dialog box opens, in which you select the messages.

Post Message

Displays the Post Message dialog box, which allows you to post one or more messages to one or more windows. This dialog box lets you select a window handle and enter wParam and lParam values for the message. The Queue for Posting button places this message at the end of a queue that holds the messages you have specified.

Once you have queued at least one message for posting, the Exit and Post button becomes enabled; clicking on it posts all the messages you have queued to their respective windows, in the order in which you queued them.


The Thread Window (32-Bit IDDE Only)

The Thread window, shown in Figure 24-63, presents at a glance all the currently extant threads your program has created, together with their states. All 16-bit applications can have only one thread; 32-bit applications can be designed to have more than one thread. The Thread window provides no benefits when debugging a single-thread application. When debugging a 32-bit multithreaded application, you can use the Thread window to:

[Figure 24-63 Thread window

Current threads are listed one per row, with the currently selected thread highlighted. You can change the selection by clicking on a different row or by using the arrow keys. The primary thread is identified by a bold arrow in the left margin. This thread receives user input and is automatically created by the operating system when a process (an instance of an application) is created. The active thread- the one from which the debugger regained control- is identified by a normal arrow in the left margin. The columns of the Thread window have the following significance:

	Table 24-15 Thread window columns 

	Column Title	Meaning 

	id		Thread ID number. Thread IDs are unique 
			within a process. 
	stat		Status. Possible values of this field are: 
			Frz -the thread is "frozen" 
			(suspended) 
			Thw -the thread is "thawed" (resumed 
			or not suspended) 
	prty		Priority. 
	esp		Current top of stack for thread. 
	eip		Current instruction location for thread. 
The Thread window has two local menus, Show and Action, as detailed in Table 24-16.
	Table 24-16 Thread window commands 

	Menu	Menu Item	Shortcut 

	Show	Source		Ctrl+S 
		Data		Ctrl+D 
		Call Chain	Ctrl+C 
		All		Ctrl+L 
	Action	Freeze		Ctrl+F 
		Thaw		Ctrl+T 
		Freeze Others	Ctrl+O 
		Thaw Others	Ctrl+M 

Show menu

The Show menu contains commands for updating the Source window, Data/Object window, and Call window to reflect the state of the currently selected thread.

[Figure 24-64 Thread window Show menu

Source

Updates the Source window to display the location of the selected thread.

Data

Updates the Data/Object window to reflect the data of the selected thread. The local variables of the active functions in the thread are displayed with the values they have in the selected thread. Dragging and dropping from the Thread window to the Data/Object window also executes this command.

Call Chain

Updates the Call window to display the call chain for the selected thread. Dragging and dropping from the Thread window to the Call window also executes this command.

All

Updates the Source window, Data/Object window, and Call window. This command is equivalent to executing the above three commands at once. Double-clicking on any thread in the Thread window also executes this command.

Action menu

The Action menu contains commands for setting the status of threads.

Freeze

Freezes (suspends) the currently selected thread.

Thaw

Unfreezes (resumes) the currently selected thread.

Freeze Others

Freezes (suspends) all threads other than the active thread.

Unfreeze Others

Unfreezes (resumes) all threads other than the active thread.

Pop-up menu

The pop-up menu contains all the commands in the Show and Action menus, described above.

The Trace Messages Window

The Trace Messages window, shown in Figure 24-71, is a simple scrolling window in which you can view debugging messages written by the debugging version of Windows, by MFC, and by your own program (using the MFC TRACE macros or the OutputDebugString Windows API). You can log all messages written to this window to a file (see the Open Trace File command below).

Note: Because of differences in system level support for debugging, tracing does not begin in the Trace Messages window on Windows 95 or Windows NT until you start debugging and choose Go Breakpoint or Go End. On Windows 3.1, tracing begins when you start debugging.

[Figure 24-65 Trace Messages window

The top line of the Trace Messages window displays the destinations of messages. The possible messages are:

	Table 24-17 Trace Messages window message destinations 

	Top Line		Meaning

	No output		Messages are neither 
				written to the window 
				nor saved to the file. 

	Output to window only	Messages are written 
				to the window only. 

	Output to window, File:pathname		Messages go to both 
						the Trace Messages 
						window and to the 
						trace file. 
The Trace Messages window has three local menus: File, Options, and Clear!, listed in Table 24-18.
	Table 24-18 Trace Window commands 

	Menu	Menu Item		Shortcut 

	File	Open Trace File		none 
		Close Trace File	none 
		Pause Trace File	none 
	Options	Windows Debug Messages	none 
		MFC Debug Messages	none 
		OLE2 LRPC Spy		none 
		Output to Window	none 
		No Output		none 
	Clear!				none 
Menu items in the Trace Messages window are described below.

File Menu

File menu commands open a new trace file, close a trace file, and pause the output to the trace file.

[Figure 24-66 Trace Messages window File menu

Open Trace File

Opens a trace file, to which the Trace Messages window output is saved. You are prompted to enter a filename. Provided you have chosen Output to Window in the Options menu (see below), the file is created and all subsequent Trace Messages window output is written to this file, until you close or pause trace output to the file.

Close Trace File

Closes the trace file so that trace messages no longer are written to it. To begin logging output again, open a trace file using the Open Trace File command.

Pause Trace File

Acts as a toggle to pause any Trace Messages window output to an open trace file. To resume logging output to the log file, choose the Pause Trace File command again. When output is paused, the menu option has a checkmark next to it.

Options Menu

The Options menu commands let you specify the debug messages you want to display in the Trace window (and in the trace file, if you have one opened ). The commands also let you toggle the display of debug messages on and off.

Note: In the 32-bit IDDE, only the commands Output to Window and No Output are present in the Options menu..

[Figure 24-67 Trace Messages window Options menu

Windows Debug Messages

(Not in 32-bit IDDE) Displays the Windows Trace Debug Options dialog box, which lets you specify the categories of errors, warnings and debug messages that you want the debugging version of Windows to trap and notify you of..

[Figure 24-68 Windows Trace Debug Options dialog box

The Break Options group lets you specify whether errors, warnings, or messages should cause a break to the debugger. Unless Break with INT 3 is checked, a stack trace is written to the Trace Messages window whenever the debugging version of Windows causes a break to the debugger.

The Debug Options group lets you direct the debugging version of Windows to perform various operations that assist you in diagnosing problems.

The Trace Options group lets you specify which informational messages are written to the Trace Messages window.

The options chosen here are stored in the [Windows] section of win.ini. The Trace Options group corresponds to the DebugOptions entry in win.ini: each check box corresponds to a single bit of the hexadecimal number stored as the value of DebugOptions. The Break and Debug groups correspond to the FilterOptions entry in win.ini: here also, each check box corresponds to a single bit of the hexadecimal number stored as the value of FilterOptions.

For further information on these options, see the documentation for the WINDEBUGINFO structure in Microsoft Windows Programmer's Reference, Volume 3. In particular, the bits of the fields dwOptions and dwFilter of WINDEBUGINFO correspond to the DebugOptions and FilterOptions entries in win. ini.

Note: If you choose this command and are not running the debug version of Windows, a message box informs you:

	This command requires installed 
	debugging Windows system binaries. 

MFC Debug Messages

(Not in 32-bit IDDE) Displays the MFC Trace Debug Options dialog box.

[Figure 24-69 MFC Trace Debug Options dialog box

This dialog box lets you choose which MFC debug messages to capture. The options chosen here are stored in the [Diagnostics] section of the file afx. ini, located in the Windows directory. The Enable Tracing check box corresponds to the TraceEnabled entry in afx. ini. The remaining check boxes correspond as a group to the single entry TraceFlags in afx. ini, and each check box corresponds to a single bit of the hexadecimal number stored as the value of TraceFlags.

OLE2 LRPC Spy

(Not in 32-bit IDDE) Enables monitoring of OLE Lightweight Remote Procedure Calls (LRPC), the mechanism by which OLE2 transports procedure calls across process boundaries from an OLE container to an OLE server or vice-versa. The command brings up the OLE2 LRPC Trace Debug Options dialog box.

[Figure 24-70 OLE LRPC Trace Debug Options dialog box

Output to Window

Displays debug messages in the window. If you have opened a trace file, you must choose this command for messages to be written to the file. Choosing this checks the item on the menu and unchecks No Output.

No Output

Disables display of debug messages in the window. It prevents messages from being written to any opened trace file. Choosing this command checks the item on the menu and unchecks Output to window.

Clear!

Removes all messages in the Trace window, but does not remove them from the trace file.

The Trace Messages Window

The Trace Messages window, shown in Figure 24-71, is a simple scrolling window in which you can view debugging messages written by the debugging version of Windows, by MFC, and by your own program (using the MFC TRACE macros or the OutputDebugString Windows API). You can log all messages written to this window to a file (see the Open Trace File command below).

[Figure 24-71 Trace Messages window]

The top line of the Trace Messages window displays the destinations of messages. The possible messages are:

The Trace Messages window has three local menus: File, Options, and Clear!, listed in Table 24-18.
	Table 24-20 Trace Window commands 

	Menu	  Menu Item	 	   Shortcut 

	File	  Open Trace File	   none 
		  Close Trace File	   none 
		  Pause Trace File	   none 
	Options	  Windows Debug Messages   none 
		  MFC Debug Messages	   none 
		  OLE2 LRPC Spy		   none 
		  Output to Window	   none 
		  No Output		   none 
	Clear!				   none 
Menu items in the Trace Messages window are described below.

File Menu

File menu commands open a new trace file, close a trace file, and pause the output to the trace file.

[Figure 24-72 Trace Messages window File menu

Open Trace File
Opens a trace file, to which the Trace Messages window output is saved. You are prompted to enter a filename. Provided you have chosen Output to Window in the Options menu (see below), the file is created and all subsequent Trace Messages window output is written to this file, until you close or pause trace output to the file.
Close Trace File
Closes the trace file so that trace messages no longer are written to it. To begin logging output again, open a trace file using the Open Trace File command.
Pause Trace File
Acts as a toggle to pause any Trace Messages window output to an open trace file. To resume logging output to the log file, choose the Pause Trace File command again. When output is paused, the menu option has a checkmark next to it.

Options Menu

The Options menu commands let you specify the debug messages you want to display in the Trace window (and in the trace file, if you have one opened ). The commands also let you toggle the display of debug messages on and off.

Note: In the 32-bit IDDE, only the commands Output to Window and No Output are present in the Options menu..

[Figure 24-73 Trace Messages window Options menu]

Windows Debug Messages
(Not in 32-bit IDDE) Displays the Windows Trace Debug Options dialog box, which lets you specify the categories of errors, warnings and debug messages that you want the debugging version of Windows to trap and notify you of.

[Figure 24-74 Windows Trace Debug Options dialog box The Break Options group lets you specify whether errors, warnings, or messages should cause a break to the debugger. Unless Break with INT 3 is checked, a stack trace is written to the Trace Messages window whenever the debugging version of Windows causes a break to the debugger.

The Debug Options group lets you direct the debugging version of Windows to perform various operations that assist you in diagnosing problems.

The Trace Options group lets you specify which informational messages are written to the Trace Messages window.

The options chosen here are stored in the [Windows] section of win.ini. The Trace Options group corresponds to the DebugOptions entry in win.ini: each check box corresponds to a single bit of the hexadecimal number stored as the value of DebugOptions. The Break and Debug groups correspond to the FilterOptions entry in win.ini: here also, each check box corresponds to a single bit of the hexadecimal number stored as the value of FilterOptions.

For further information on these options, see the documentation for the WINDEBUGINFO structure in Microsoft Windows Programmer's Reference, Volume 3. In particular, the bits of the fields dwOptions and dwFilter of WINDEBUGINFO correspond to the DebugOptions and FilterOptions entries in win.ini.

Note: If you choose this command and are not running the debug version of Windows, a message box informs you:

	This command requires installed 
	debugging Windows system binaries. 
	
MFC Debug Messages
(Not in 32-bit IDDE) Displays the MFC Trace Debug Options dialog box.

[Figure 24-75 MFC Trace Debug Options dialog box This dialog box lets you choose which MFC debug messages to capture. The options chosen here are stored in the [Diagnostics] section of the file afx.ini, located in the Windows directory. The Enable Tracing check box corresponds to the TraceEnabled entry in afx.ini. The remaining check boxes correspond as a group to the single entry TraceFlags in afx.ini, and each check box corresponds to a single bit of the hexadecimal number stored as the value of TraceFlags.

OLE2 LRPC Spy
(Not in 32-bit IDDE) Enables monitoring of OLE Lightweight Remote Procedure Calls (LRPC), the mechanism by which OLE2 transports procedure calls across process boundaries from an OLE container to an OLE server or vice-versa. The command brings up the OLE2 LRPC Trace Debug Options dialog box.

[Figure 24-76 OLE LRPC Trace Debug Options dialog box]

Output to Window
Displays debug messages in the window. If you have opened a trace file, you must choose this command for messages to be written to the file. Choosing this checks the item on the menu and unchecks No Output.
No Output
Disables display of debug messages in the window. It prevents messages from being written to any opened trace file. Choosing this command checks the item on the menu and unchecks Output to window.

Clear!

Removes all messages in the Trace window, but does not remove them from the trace file.

The Watch Window

Watchpoints are used to determine the approximate point in the code where a specific memory location or a location in a range of memory is written to or read from. A watchpoint defines a range in memory and causes the debugger to stop the program if any value in that memory range changes or is accessed.

You can set watchpoints on variables in the Data/Object window, on memory locations in the Memory window, or on ranges.

The Watch window, shown in Figure 24-77, displays a list of all watchpoints set in the program. You can view the memory locations of watchpoints and clear watchpoints selectively.

[Figure 24-77 Watch window]

If no watchpoints are set in the program, the Watch window displays the following message:

	No watchpoints defined 
After watchpoints are set on data in the program, the Watch window displays the following information:
	name [address range] 
name: If the watchpoint has been set on a variable in the Data/Object window, this field contains the name of the variable. For Memory window watchpoints, the field contains the string memory.

address range: This is the range of memory being watched.

Byte1: This shows the successive bytes being watched in the memory range.

The Watch window has two local menus, Show and Commands, listed in Table 24-21.

	Table 24-21 Watch window commands 

	Menu		Menu Item		Shortcut

	Show		Memory			Ctrl+E 
	Commands	Clear Watchpoint	Ctrl+C 
			Clear All Watchpoints	Ctrl+K 
The local menu commands of the Watch window are described below.

Show menu

The Show menu contains one command that shows the starting address of the memory, and displays the memory.

[Figure 24-78 Watch window Show menu]

Memory
Displays the starting address of the watchpoint range and updates the Memory window to display the memory at that address.

Commands menu

The commands in this menu let you clear selected watchpoints or all the watchpoints in the program.

[Figure 24-79 Watch window Commands menu]

Clear Watchpoint
Clears selected watchpoints.
Clear All Watchpoints
Clears all watchpoints set in the program.

Pop-up menu

The pop-up menu of the Watch window contains the commands Show Memory and Clear Watchpoint. These behave identically to the local menu commands Memory and Show Watchpoint described above.

[Figure 24-80 Watch window pop-up menu]

25. ResourceStudio Resource Editor

This ResourceStudio reference chapter contains details about the commands and options found in the Shell and Browser windows. For an introduction to ResourceStudio, see Chapter 7, Adding Look and Feel with Resources.

The Shell Window

The ResourceStudio Shell window is:

Figure 25-1 The Shell window

Figure 25-1 The Shell window

The Shell window is ResourceStudio's main control center. It opens resource files, creates new resource files, sets preferences, arranges windows, and accesses online help.

File menu commands

The File menu (see Figure 25-2) contains commands to create and open resource files and to exit ResourceStudio. In addition to the commands listed below, the File menu contains a list of recently opened resource files.

Any of these files may be reopened by choosing its name from the menu.

[Figure 25-2 Shell window File menu

New
Opens the New File dialog box (see Figure 25-3). Use this dialog box to create a new resource file.

[Figure 25-3 New File dialog box

Type
Specifies the type of resource file to create.
Resource script Creates a resource script (.rc) file
Binary resource Creates a binary resource (.res) file
Icon Creates an icon (.ico) file
Cursor Creates a cursor (.cur) file
Bitmap Creates a bitmap (.bmp) file
Font Creates a font (.fnt) file
For Resource Script or Binary Resource, the new file opens in a Browser window; otherwise, the appropriate resource editor opens in a separate window.
Platform
Specifies the target platform for the resource file.
Windows 3.1 Creates resources for Windows 3.1
Windows NT Creates resources for Windows NT
Windows 95 Creates resources for Windows 95
Windows 95 resources use the MENUEX and DIALOGEX resource types for menus and dialogs, respectively. For more information, see your Windows 95 documentation.
Support MFC
Applies to resource script files; specifies that the file should include MFC resource headers. Check this box if you plan to use your resources in an MFC application.
Open
Opens the File Open dialog box (see Figure 25-4). This is a standard dialog box for opening files, with an extra field for specifying the target platform.

[Figure 25-4 File Open dialog box

Target platform
Specifies the target platform. Choices include Windows 3.1, Windows NT, and Windows 95.
Exit
Closes ResourceStudio.

Edit menu commands

The Edit menu (see Figure 25-5) contains a single command, used to set ResourceStudio preferences.

[Figure 25-5 Shell window Edit menu

Preferences

Opens the Preferences dialog box, used to set miscellaneous ResourceStudio options. This dialog box has three tabs of options.

Note: The Controls tab of options is not available when running ResourceStudio on Windows 95 and Windows NT.

The General tab (see Figure 25-6) contains miscellaneous ResourceStudio options.

[Figure 25-6 General tab of Preferences dialog box

Undo
Specifies the number of previous states that are saved and, therefore, the number of actions that can be undone. Each Browser window and each individual resource editor keeps a separate list of actions that were undone.
Assume File Platform
These options specify default file platforms for creating and loading resource files.
When Creating Files:
Specifies default platform for new resource files.
When Opening Files:
Specifies default platform for opened resource files.
3D Look for New Dialogs
If checked, new dialogs are given a 3-dimensional look by default.
The RC Script tab (see Figure 25-7) contains options for resource script files.

[Figure 25-7 RC Script tab of Preferences dialog box

Definitions
Contains a list of symbols to be defined with a #define directive in each .rc file. Click on a symbol to copy its name and value to the textboxes below the list. You can edit the name or value, then click on the symbol in the list again to copy the new name and value back to the list.
Name
Contains a symbol name.
Value
Contains a symbol value.
Add
Adds the current symbol and value to the Definitions list.
Remove
Deletes the currently selected symbol from the Definitions list.
The Controls tab (see Figure 25-5) contains options for installing custom controls. A custom control resides in a DLL that implements the standard functions which allow a dialog editor (such as ResourceStudio) to manipulate and display the control.

Note: The Controls tab of options is not available when running ResourceStudio on Windows 95 and Windows NT.

[Figure 25-8 Controls tab of Preferences dialog box

Installed Controls
Contains a list of custom control DLLs that are currently installed.
Add
Adds a custom control DLL to the list of installed controls.
Remove
Removes a custom control DLL from the list of installed controls.

Window menu commands

The Window menu (see Figure 25-8) contains commands to arrange ResourceStudio windows. These commands execute the standard Windows Cascade, Tile, and Close All functions. Attached to the bottom of the menu is a list of currently opened Browser and editor windows. Choose a window name to bring that window to the foreground or to restore it after it has been minimized.

[Figure 25-9 Shell window Window menu

Help menu commands

The Help menu (see Figure 25-9) contains commands to access online help and to display program information.

[Figure 25-10 Shell window Help menu

Index
Opens ResourceStudio online help to the index.
Using Help
Opens online help to information about how to use help.
About ResourceStudio
Opens a dialog box that displays ResourceStudio version and copyright information.

Toolbar commands

The Shell window toolbar provides quick access to menu commands and to context-sensitive help:

Figure 25-11 Shell window toolbar

[Figure 25-11 Shell window toolbar]

Creates a new resource script file and opens it in a Browser window. The platform is set to the default platform for creating new files (as set in the Preferences dialog box).
Same as choosing Open from the File menu, except that the target platform for the resource is automatically set to the last platform chosen with File Open.
Same as choosing About ResourceStudio from the Help menu.
Enters context-sensitive help mode. A question mark is appended to the cursor while in this mode. Select any component of ResourceStudio, such as a menu item or a toolbar icon, to open the online help for information about that component.

The Browser Window

The Browser window (see Figure 25-11) supervises the editing of a multiresource file, such as a resource script file. The resource types contained in the file are listed in the upper-left pane; when a type is selected, the resources of that type are listed in the lower-left pane. The right pane contains a preview of the currently selected resource.

[Figure 25-12 The Browser window

Individual resources can be edited either in separate windows or in the right pane of the Browser window. In the latter case, the menu bar of the resource editor replaces the Browser window's menu bar during editing.

File menu commands

The File menu (see Figure 25-12) contains commands to save the resource file, to edit resources, and to perform other miscellaneous functions.

[Figure 25-13 Browser window File menu

Save
Saves the resource file. If the file is unnamed, this command executes Save As.
Save As
Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.
Edit Resource
Opens the selected resource in the right pane of the Browser window so that the resource can be edited. This command is also executed by double-clicking on a resource, or double-clicking in the right pane when a preview of the resource is displayed there.
Edit in Separate Window
Opens the selected resource in a separate window so that the resource can be edited.
Export Resource
Opens a dialog box that can be used to save the currently selected resource in a separate file. This command is only available when the current resource is a bitmap, icon, cursor, or font.
Edit Resource IDs
Opens the Resource ID Browser dialog box (see Figure 25-13). This dialog box is used to browse and modify resource IDs.

[Figure 25-14 Resource ID Browser dialog box

For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."

ClassExpress
Runs ClassExpress and passes the filename of the resource file as the project that ClassExpress should open. You should run ClassExpress, for example, after creating a dialog box. With ClassExpress you can create a class for the dialog box, set up a message map, and add member variables corresponding to controls. For more information, see Chapter 18, "More about ClassExpress," and Chapter 14, "Lesson 5: Add a Dialog Box with ClassExpress."
Close
Closes the Browser window.

Edit menu commands

The Edit menu (see Figure 25-15) contains standard editing commands. You can copy and paste entire resources, making it easy to move resources from one file to another.

[Figure 25-15 Browser window Edit menu

Undo
Undoes the last Browser window operation.
Redo
Redoes the last Browser window operation that was undone.
Cut
Copies the selected resource to the Clipboard, then deletes it from the resource file.
Copy
Copies the selected resource to the Clipboard.
Paste
Copies the resource in the Clipboard into the resource file. Delete
Deletes the selected resource from the resource file.

Resource menu commands

Commands in the Resource menu (see Figure 25-16) are used to create new resources. In each case, a new ID is automatically created and assigned to the resource, and the resource is opened in the right pane of the Browser window so that the resource can be edited.

[Figure 25-16 Browser window Resource menu

New Dialog Box
Creates a new dialog box. As the resource is created, the DialogExpress dialog box lets you select a predefined dialog type to use as a starting point (see "Dialog Editor," in Chapter 26, "Dialog Editor").
New Bitmap
Creates a new bitmap. As the resource is created, the BitmapExpress dialog box lets you specify initial bitmap parameters (see "Bitmap Editor," in Chapter 28, "Bitmap, Cursor, Icon, and Font Editors").
New Icon
Creates a new icon.
New Cursor
Creates a new cursor.
New Menu
Creates a new menu.
New Font
Creates a new font. As the resource is created, the FontExpress dialog box lets you specify initial font parameters (see "Font Editor," in Chapter 28, "Bitmap, Cursor, Icon, and Font Editors").
New String Table
Creates a new string table.
New Accelerator Table
Creates a new accelerator table.
New Version
Creates a new version information resource.
New Other
Opens the Create Custom Resource dialog box (see Figure 25-17). Use this dialog box to select a custom resource type to create and to define new custom resource types.

[Figure 25-17 Create Custom Resource dialog box

To create one of the listed resource types, select it and click OK. To define a new resource type, click on Add Type. The New Resource Type dialog box opens (see Figure 25-18).

[Figure 25-18 New Resource Type dialog box

Type a name for the new resource type in the textbox and click OK. The new type is added to the list in the Create Custom Resource dialog box.

Toolbar commands

The Browser window toolbar provides quick access to frequently used menu commands:

Figure 25-19 Browser window toolbar

[Figure 25-19 Browser window toolbar]

Same as choosing Save from the File menu.
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Same as choosing Cut from the Edit menu.
Same as choosing Copy from the Edit menu.
Same as choosing Paste from the Edit menu.
Same as choosing Edit Resource IDs from the File menu.
Same as choosing New Bitmap from the Resource menu.
Same as choosing New Cursor from the Resource menu.
Same as choosing New Dialog Box from the Resource menu.
Same as choosing New Icon from the Resource menu.
Same as choosing New Menu from the Resource menu.
Same as choosing New Font from the Resource menu.
Same as choosing New String Table from the Resource menu.
Same as choosing New Accelerator Table from the Resource menu.
Same as choosing New Version from the Resource menu.

Resource properties

When the Browser window is active and a resource in the lower-left pane is selected, the Property Sheet displays properties of the resource, which specify the resource ID and the resource memory options. Figure 25-20 shows the properties of a Menu resource.

[Figure 25-20 Resource properties

ID Specifies the resource ID by one of the following:
  • Select an existing ID from the drop-down list.
  • Type a new symbol for the resource ID. The ID is assigned a new, unique value.
  • Type a new symbol, followed by an equal sign, followed by a value (for example, IDC_NAME=550). If you do not specify a value, one is supplied. The ID is assigned the value.
  • Type a textual resource identifier, enclosed in double quotes (for example, "MenuOne"). Textual IDs cannot be assigned to font resources.
Preload Specifies that the resource should be loaded into memory when the application is started. If this option is not checked, the resource is loaded when it is needed.
Moveable Lets Windows move the resource in memory after it is loaded.
Discardable Lets Windows remove the resource from memory when it is no longer needed.
Pure Protects the resource in memory from being modified.

26. Dialog Editor

This ResourceStudio reference chapter contains details about the commands and options found in the Dialog editor. For an introduction to ResourceStudio, see Chapter 7, "Adding Look and Feel with Resources."

Dialog Editor

The Dialog editor (see Figure 26-1) is used to edit dialog resources.

[Figure 26-1 The Dialog editor

The Dialog editor displays the dialog box and its controls as they will appear at run time. To add a new control to the dialog box, select a tool from the Tool menu (or from the toolbox), then place the control in the dialog box by clicking and dragging. Controls can be moved and resized by clicking and dragging as well. Commands in the Controls menu can be used to center and align controls. The dialog box can be tested by choosing Test Dialog in the Dialog menu. For more information about using the Dialog editor, see Chapter 7, "Adding Look and Feel with Resources."

DialogExpress

As a new dialog resource is created, the DialogExpress dialog box opens (see Figure 26-2). DialogExpress lets you select a predefined dialog box type to use as a starting point for your dialog resource.

[Figure 26-2 DialogExpress

Select dialog type

Specifies a type of dialog box to create as a starting point for the dialog resource.
Standard:
Creates a dialog box with no controls.
About box:
Creates a dialog box with static text and an OK button.
Standard, buttons on the bottom:
Creates a dialog box with OK and Cancel buttons along the bottom.
Standard, buttons on the right:
Creates a dialog box with OK and Cancel buttons along the right edge.

3-dimensional look

Specifies that the dialog box and controls should look 3-dimensional.

File menu commands

The File menu (see Figure 26-3) contains commands to save the resource file, edit resource IDs, and perform other miscellaneous functions.

[Figure 26-3 Dialog editor File menu

Save

Saves the resource file. If the file is unnamed, this command executes Save As.

Save As

Opens a Windows File Save As dialog box, which is used to save the resource file under a new name.

Edit Resource IDs

Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."

ClassExpress

Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Dialog editor is running in the right pane of the Browser window.

Close Editing

Closes the Dialog editor.

Edit menu commands

The Edit menu (see Figure 26-4) contains standard editing commands. You can undo operations, and can cut, copy, paste, and delete single or multiple controls. Note that to select multiple controls, you must press Shift or Control while clicking the second and subsequent controls, or must use the selection tool to drag a box around the controls.

[Figure 26-4 Dialog editor Edit menu

Undo

Undoes the last Dialog editor operation.

Redo

Redoes the last action that was undone.

Cut

Copies the selected control to the Clipboard, then deletes it from the dialog box.

Copy

Copies the selected control to the Clipboard.

Paste

Copies the control in the Clipboard to the dialog box.

Delete

Deletes the selected control from the dialog box.

Select All

Selects all controls in the dialog box.

Dialog menu commands

The Dialog menu (see Figure 26-5) contains commands to control the grid, display tab stops, test the dialog, and check for duplicate control IDs.

[Figure 26-5 Dialog editor Dialog menu

Grid Options

Opens the Grid Settings dialog box (see Figure 26-6), used to set grid options.

[Figure 26-6 Grid Settings dialog box

Width
Specifies the grid point horizontal spacing.
Height
Specifies the grid point vertical spacing.
Snap to grid
If checked, controls can only be moved to positions which coincide with grid points. When controls are resized, horizontal and vertical sizes are adjusted to multiples of the grid point spacings.
Display grid
If checked, the grid is displayed.

Grid

Toggles display of the grid.

Snap to Grid

Moves the selected control to the nearest grid point.

Display Tab Stops

Toggles the display of tab stop numbers on controls. Tab order can be adjusted with commands in the Tab Order submenu of the Controls menu.

Test Dialog

Runs the dialog. End testing by clicking on a button with a resource ID of IDOK or IDCANCEL, or by pressing Alt+ F4.

Check Duplicate IDs

Checks the dialog for duplicate control IDs. If any two items have the same ID, the Resolve Duplicate IDs dialog box opens (see Figure 26-7).

[Figure 26-7 Resolve Duplicate IDs dialog box

To resolve duplicate IDs, first click on a number in the Duplicate IDs list. The Used By listbox displays the controls that are using that ID. Click on Resolve One to automatically assign new IDs (with unique values) to the controls.

Note that all static text usually shares the same ID; in general, this is acceptable and does not cause conflicts in the application.

Controls menu commands

The Controls menu (see Figure 26-8) contains commands to align, space, and center controls, and to adjust tab order.

[Figure 26-8 Dialog editor Controls menu

Align

Opens the Align submenu (see Figure 26-9). Before choosing one of these commands, select two or more controls and designate one as the standard by clicking on it while pressing the Control key.

[Figure 26-9 Dialog editor Controls menu Align submenu

Left

Aligns the left edges of the selected controls with the left edge of the standard.

Right

Aligns the right edges of the selected controls with the right edge of the standard.

Top

Aligns the top edges of the selected controls with the top edge of the standard.

Bottom

Aligns the bottom edges of the selected controls with the bottom edge of the standard.

Space Evenly

Opens the Space Evenly submenu (see Figure 26-10). Before choosing one of these commands, select three or more controls.

[Figure 26-10 Dialog editor Controls menu Space Evenly submenu

Vertical

Spaces the selected controls evenly in the vertical direction.

Horizontal

Spaces the selected controls evenly in the horizontal direction.

Center

Opens the Center submenu (see Figure 26-11). Before choosing one of these commands, select one or more controls.

[Figure 26-11 Dialog editor Controls menu Center submenu

Vertical

Centers the selected controls vertically within the dialog box.

Horizontal

Centers the selected controls horizontally within the dialog box.

Make Same Size

Opens the Make Same Size submenu (see Figure 26-12). Before choosing one of these commands, select two or more controls and designate one as the standard by clicking on it while pressing the Control key.

[Figure 26-12 Dialog editor Controls menu Make Same Size submenu

Vertical

Changes the vertical size of the selected controls to that of the standard.

Horizontal

Changes the horizontal size of the selected controls to that of the standard.

Both

Changes both the vertical and horizontal sizes of the selected controls to those of the standard.

Tab Order

Opens the Tab Order submenu (see Figure 26-13). Before choosing one of these commands, select a single control.

[Figure 26-13 Dialog editor Controls menu Tab Order submenu

First

Moves the selected control to the front of the tab sequence.

Forward

Moves the selected control forward in the tab sequence.

Back

Moves the selected control back in the tab sequence.

Last

Moves the selected control to the end of the tab sequence.

Tool menu commands

The Tool menu (see Figure 26-14) lets you select tools used to place controls in the dialog box. After selecting a tool, click and drag in the dialog box to place and size the new control. Once the control is placed, the Select tool is selected automatically.

[Figure 26-14 Dialog editor Tool menu

Select

Selects the Select tool. With the Select tool, you can select individual controls. You can select groups of controls by clicking in the dialog box outside of any control and dragging a box over the controls to be selected.

Picture

Selects the Picture tool, used to place a static image (a box, frame, or icon) in the dialog box.

Text

Selects the Text tool, used to place static text in the dialog box.

Edit Control

Selects the Edit Control tool, used to place an edit control (a textbox) in the dialog box.

Group Box

Selects the Group Box tool, used to place a group box in the dialog box.

Push Button

Selects the Push Button tool, used to place a push button in the dialog box.

Check Box

Selects the Check Box tool, used to place a check box in the dialog box.

Radio Button

Selects the Radio Button tool, used to place a radio button in the dialog box.

List Box

Selects the List Box tool, used to place a listbox in the dialog box.

Combo Box

Selects the Combo Box tool, used to place a combobox in the dialog box.

Vertical Scroll Bar

Selects the Vertical Scroll Bar tool, used to place a vertical scroll bar in the dialog box.

Horizontal Scroll Bar

Selects the Horizontal Scroll Bar tool, used to place a horizontal scroll bar in the dialog box.

Toolbar commands

The Dialog editor toolbar (see Figure 26-15) provides quick access to frequently used menu commands. Left-click on these buttons, except where noted.

[Figure 26-15 Dialog editor toolbar

Undo:
Same as choosing Undo from the Edit menu. You can right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. You can right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
Test Dialog:
Same as choosing Test Dialog from the Dialog menu.
Align Left:
Same as choosing Left from the Align submenu of the Controls menu.
Align Right:
Same as choosing Right from the Align submenu of the Controls menu.
Align Top:
Same as choosing Top from the Align submenu of the Controls menu.
Align Bottom:
Same as choosing Bottom from the Align submenu of the Controls menu.
Center Vertical:
Same as choosing Vertical from the Center submenu of the Controls menu.
Center Horizontal:
Same as choosing Horizontal from the Center submenu of the Controls menu.
Space Evenly Vertical:
Same as choosing Vertical from the Space Evenly submenu of the Controls menu.
Space Evenly Horizontal:
Same as choosing Horizontal from the Space Evenly submenu of the Controls menu.
Same Size Vertical:
Same as choosing Vertical from the Make Same Size submenu of the Controls menu.
Same Size Horizontal:
Same as choosing Horizontal from the Make Same Size submenu of the Controls menu.
Same Size Both:
Same as choosing Both from the Make Same Size submenu of the Controls menu.
Grid:
Same as choosing Grid from the Dialog menu.
Tab Stops:
Same as choosing Display Tab Stops from the Dialog menu.

Toolbox

The Dialog editor toolbox (see Figure 26-16) provides quick access to the tools available in the Tool menu, plus tools for adding custom controls and user controls (not pictured). For more information, see "Tool menu commands," earlier in this chapter.

[Figure 26-16 Dialog editor toolbox

Dialog box properties

The dialog box has three pages of properties (four if the target platform is Windows 95). The General properties are shown in Figure 26-17.

[Figure 26-17 Dialog box General properties

The Text field is used to specify the dialog box title.

Styles properties are shown in Figure 26-18.

[Figure 26-18 Dialog box Styles properties

Look properties are shown in Figure 26-19.

[Figure 26-19 Dialog box Look properties

The dialog box font can be set by clicking on Set Font and selecting a font from the dialog box which opens. The Reset Font button resets the dialog box font to the system default.

If the target platform is Windows 95, the dialog box has an extra page of properties, as shown in Figure 26-20.

[Figure 26-20 Dialog box Win95 properties

See your Windows 95 documentation for more information.

Picture properties

Pictures (static images) have properties as shown in Figure 26-21.

[Figure 26-21 Picture properties

Select a Type from the drop-down list. If you select Icon, you must also select an icon from the Icon drop-down list.

Text properties

Static text properties are shown in Figure 26-22.

[Figure 26-22 Text properties

Type the static text into the Text textbox. Newlines can be entered by typing Ctrl+ Enter.

Edit control properties

Edit controls have two pages of properties. The General properties are shown in Figure 26-23.

[Figure 26-23 Edit control General properties

Edit control Styles properties are shown in Figure 26-24.

[Figure 26-24 Edit control Styles properties

Group box properties

Group box properties are shown in Figure 26-25.

[Figure 26-25 Group box properties

Push button properties

Push button properties are shown in Figure 26-26.

[Figure 26-26 Push button properties

Check box properties

Check box properties are shown in Figure 26-27.

[Figure 26-27 Check box properties

Radio button properties

Radio button properties are shown in Figure 26-28.

[Figure 26-28 Radio button properties

Listbox properties

Listboxes have two pages of properties. The General properties are shown in Figure 26-29.

[Figure 26-29 Listbox General properties

Listbox Styles properties are shown in Figure 26-30.

[Figure 26-30 Listbox Styles properties

Combobox properties

Comboboxes have two pages of properties. The General properties are shown in Figure 26-31.

[Figure 26-31 Combobox General properties

Combobox Styles properties are shown in Figure 26-32.

[Figure 26-32 Combobox Styles properties

Scroll bar properties

Scroll bar properties are shown in Figure 26-33.

[Figure 26-33 Scroll bar properties

Custom control properties

These pages let you work with custom controls. A custom control resides in a DLL that implements the standard functions for manipulating and displaying the control. ResourceStudio can display a custom control as it will appear in your application.

Custom controls have two pages of properties. The General properties are shown in Figure 26-31. Use the ID field to edit a custom control's resource ID. To change its style attributes, click Style; this displays the dialog box that the control DLL implements for that purpose.

[Figure 26-34 Custom Control General properties

Custom control Extra properties are shown in Figure 26-32. You edit the initialization data for custom controls in this page.

[Figure 26-35 Custom Control Extra properties

Working with custom controls

Installed custom control DLLs provide ResourceStudio with the information it needs to display the control as it will appear in the application, and open the DLL's control-specific dialog box, with which you specify the control's attributes.

To place a custom control in a dialog box:

  1. Install its DLL using the Add button on the Controls page of the Preferences dialog box.
  2. Click the button in the Toolbox that corresponds to the control, and drag it into the dialog box. Right-clicking on a custom control's button displays its name.
  3. Use the General property page to specify the control's resource ID and style attributes.
  4. Use the Extra property page to specify any initialization data for the control. At run-time, the control's window procedure receives a pointer to this data in lParam of the WM_CREATE message.

User control properties

These pages let you work with user controls. A user control is any control that either is not implemented in a DLL, or whose implementation is non-standard. ResourceStudio can only display a user control as a box. ResourceStudio treats VBX controls as user controls.

User controls have two pages of properties. The General properties are shown in Figure 26-36. You use this page to edit a user control's resource ID or change its style bits.

[Figure 26-36 User Control General properties

User control Extra properties are shown in Figure 26-32. You edit the initialization data for user controlsin this page.

[Figure 26-37 User Control Extra properties

Working with user controls

To place a user control in a dialog box:
  1. Click the user control button in the Toolbox, and drag it into the dialog box.
  2. Use the General property page to specify the control's resource ID, style bits, and other information.
  3. Use the Extra property page to specify any initialization data for the user control. At run-time, the control's window procedure receives a pointer to this data in lParam of the WM_CREATE message.

Animate control properties

Animate control properties are shown in Figure 26-38.

[Figure 26-38 Animate control properties

Tree view properties

Tree view properties are shown in Figure 26-39.

[Figure 26-39 Tree View properties

Tab control properties

Tab controls have two pages of properties. The General properties are shown in Figure 26-40.

[Figure 26-40 Tab Control General properties

Tab Control properties are shown in Figure 26-41.

[Figure 26-41 Tab Control properties

List view control properties

List view controls have three pages of properties. The General properties are shown in Figure 26-42.

[Figure 26-42 List View Control General properties

List View properties are shown in Figure 26-43.

[Figure 26-43 List View properties

Look properties are shown in Figure 26-44.

[Figure 26-44 List View Look properties

Hotkey properties

Hotkey properties are shown in Figure 26-45.

[Figure 26-45 Hotkey properties

Track Bar properties

Track bars have two pages of properties. The General properties are shown in Figure 26-46.

[Figure 26-46 Track Bar General properties

Track Bar properties are shown in Figure 26-47.

[Figure 26-47 Track Bar properties

Progress control properties

Progress control properties are shown in Figure 26-48.

[Figure 26-48 Progress control properties

Up/Down control properties

Up/Down controls have two pages of properties. The General properties are shown in Figure 26-49.

[Figure 26-49 Up/Down control General properties

Up/Down properties are shown in Figure 26-50.

[Figure 26-50 Up/Down properties

27. Menu, Accelerator and String Table Editors

This ResourceStudio reference chapter contains details about the commands and options found in the Menu editor, the Accelerator Table editor and the String Table editor. For an introduction to ResourceStudio, see Chapter 7, "Adding Look and Feel with Resources."

Menu Editor

The Menu editor (see Figure 27-1) is used to edit menu resources.

[Figure 27-1 The Menu editor

The Menu editor displays the menu as a hierarchy of POPUPs, each of which may contain MENUITEMs, SEPARATORs, and other POPUPs. Items are added to the menu with commands in the Menu menu (or by clicking buttons in the toolbar), and are rearranged with commands in the Outline menu or by dragging with the mouse. The menu may be tested as a pull-down or pop-up menu at any time in the Test menu window, which is opened automatically when the Menu editor is started. For more information about using the Menu editor, see Chapter 7, "Adding Look and Feel with Resources."

File menu commands

The File menu (see Figure 27-2) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 27-2 Menu editor File menu

Save

Saves the resource file. If the file is unnamed, this command executes Save As.

Save As

Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.

Edit Resource IDs

Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."

ClassExpress

Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Menu editor is running in the right pane of the Browser window.

Close Editing

Closes the Menu editor.

Edit menu commands

The Edit menu (see Figure 27-3) contains standard editing commands. You can undo operations, and can cut, copy, paste, and delete individual MENUITEMs or entire POPUPs.

[Figure 27-3 Menu editor Edit menu

Undo

Undoes the last Menu editor operation.

Redo

Redoes the last Menu editor operation that was undone.

Cut

Copies the selected item to the Clipboard, then deletes it from the menu.

Copy

Copies the selected item to the Clipboard.

Paste

Copies the item in the Clipboard into the menu.

Delete

Deletes the selected item from the menu.

Menu menu commands

The Menu menu (see Figure 27-4) contains commands to add items to the menu. You can insert individual MENUITEMs, POPUPs, and SEPARATORs, and you can insert predefined File, Edit, and Help menus. An additional command lets you check for duplicate command IDs.

[Figure 27-4 Menu editor Menu menu

Before adding a new item, select the item after which the new item should be inserted.

New Item

Adds a new MENUITEM after the selected item.

New Popup

Adds a new POPUP after the selected item.

New Separator

Adds a new SEPARATOR after the selected item.

Standard File Menu

Adds a standard File menu after the selected item.

Standard Edit Menu

Adds a standard Edit menu after the selected item.

Standard Help Menu

Adds a standard Help menu after the selected item.

Check Duplicate IDs

Checks the menu for duplicate command IDs. If any two items have the same ID, the Resolve Duplicate IDs dialog box opens (see Figure 27-5).

[Figure 27-5 Resolve Duplicate IDs dialog box

To resolve duplicate IDs, first click on a number in the Duplicate IDs list. The Used By listbox displays the items that are using that ID. Click on Resolve One to automatically assign new IDs (with unique values) to the items.

Outline menu commands

The Outline menu (see Figure 27-6) is used to rearrange the menu. You can move items within their current hierarchical level, or you can promote or demote items from one level to another.

[Figure 27-6 Menu editor Outline menu

Expand/Collapse

Expands or collapses (depending on the present state) the view of the contents of a POPUP item. While a POPUP is collapsed, the items within a POPUP are not shown, and the triangle to the left of the POPUP points rightward. While expanded, the items within the POPUP are shown and the triangle points downward. You can also execute this command by clicking on the triangle next to the POPUP.

Move Up

Exchanges the selected item with the previous item in the same level of the hierarchy.

Move Down

Exchanges the selected item with the next item in the same level of the hierarchy.

Demote

If the previous item in the same level of the hierarchy is a POPUP, moves the selected item into the POPUP.

Promote

If the selected item is within a POPUP, moves the item out of the POPUP to the same hierarchical level as the POPUP.

Toolbar commands

The Menu editor toolbar (see Figure 27-7) provides quick access to frequently used menu commands.

[Figure 27-7 Menu editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
New Item:
Same as choosing New Item from the Menu menu.
New Popup:
Same as choosing New Popup from the Menu menu.
New Separator:
Same as choosing New Separator from the Menu menu.

Popup item properties

POPUP item properties are shown in Figure 27-8.

[Figure 27-8 Popup properties

Menu item properties

MENUITEMs and SEPARATORs have two pages of properties. The General properties are shown in Figure 27-9.

[Figure 27-9 Menu item / separator General properties

A SEPARATOR would have the Separator box checked.

The Connect properties (see Figure 27-10) only apply to MENUITEMs.

[Figure 27-10 Menu item Connect properties

The Prompt textbox is used to set help text for the item. The Hotkey field displays the accelerator key combination associated with the item. For more information about how to create menus with help text and accelerators, see Chapter 7, "Adding Look and Feel with Resources."

Accelerator Table Editor

The Accelerator Table editor (see Figure 27-11) is used to edit accelerator tables.

[Figure 27-11 The Accelerator Table editor

The Accelerator Table editor displays a list of accelerator IDs and associated key combinations. To create and delete accelerators, use the New and Delete commands in the Edit menu. You can set the ID and key combination of an accelerator in the Property Sheet.

Accelerators are usually associated with menu items, and you can create accelerators directly from the Menu editor. For more information, see Chapter 7, "Adding Look and Feel with Resources."

File menu commands

The File menu (see Figure 27-12) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 27-12 Accelerator Table editor File menu

Save

Saves the resource file. If the file is unnamed, this command executes Save As.

Save As

Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.

Edit Resource IDs

Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."

ClassExpress

Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Accelerator Table editor is running in the right pane of the Browser window.

Close Editing

Closes the Accelerator Table editor.

Edit menu commands

The Edit menu (see Figure 27-13) contains standard editing commands. You can undo operations, and can cut, copy, paste, add, and delete accelerators.

[Figure 27-13 Accelerator Table editor Edit menu

Undo

Undoes the last Accelerator Table editor operation.

Redo

Redoes the last Accelerator Table editor operation that was undone.

Cut

Copies the selected accelerator to the Clipboard, then deletes it from the table.

Copy

Copies the selected accelerator to the Clipboard.

Paste

Copies the accelerator in the Clipboard into the table.

New

Adds a new accelerator to the table.

Delete

Deletes the selected accelerator from the table.

Toolbar commands

The Accelerator Table editor toolbar (see Figure 27-14) provides quick access to frequently used menu commands.

[Figure 27-14 Accelerator Table editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
New:
Same as choosing New from the Edit menu.
Delete:
Same as choosing Delete from the Edit menu.

Accelerator properties

Accelerator properties are shown in Figure 27-15.

[Figure 27-15 Accelerator properties

The accelerator key combination can be set by clicking on Next Typed, then pressing the key combination. The Key, Type, and Modifiers options are set automatically.

String Table Editor

The String Table editor (see Figure 27-16) is used to edit string tables.

[Figure 27-16 The String Table editor

The String Table editor displays a list of IDs and associated text. To create and delete strings, use the New and Delete commands in the Edit menu. You can set the ID and text of a string in the Property Sheet.

Although they can be used for any purpose, strings are commonly used to display information about menu commands. You can create strings associated with menu items directly from the Menu editor. For more information, see Chapter 7, "Adding Look and Feel with Resources."

File menu commands

The File menu (see Figure 27-17) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 27-17 String Table editor File menu

Save

Saves the resource file. If the file is unnamed, this command executes Save As.

Save As

Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.

Edit Resource IDs

Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."

ClassExpress

Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the String Table editor is running in the right pane of the Browser window.

Close Editing

Closes the String Table editor.

Edit menu commands

The Edit menu (see Figure 27-18) contains standard editing commands. You can undo operations, and can cut, copy, paste, add, and delete strings. The find commands can help you to locate particular strings in large tables.

[Figure 27-18 String Table editor Edit menu

Undo

Undoes the last String Table editor operation.

Redo

Redoes the last String Table editor operation that was undone.

Cut

Copies the selected string to the Clipboard, then deletes it from the table.

Copy

Copies the selected string to the Clipboard.

Paste

Copies the string in the Clipboard into the table.

New

Adds a new string to the table.

Delete

Deletes the selected string from the table.

Find

Opens the Find String dialog box (see Figure 27-19). This dialog box is used to locate a string containing particular text.

[Figure 27-19 Find String dialog box

Type the search text into the Find What textbox. Select Match Case to make the search case sensitive. When you click OK, the String Table editor locates the first occurrence of the text in the string table.

Find Again

Finds the next occurrence of the search text, starting from the currently selected string.

Toolbar commands

The String Table editor toolbar (see Figure 27-20) provides quick access to frequently used menu commands.

[Figure 27-20 String Table editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
New:
Same as choosing New from the Edit menu.
Delete:
Same as choosing Delete from the Edit menu.
Find:
Same as choosing Find from the Edit menu.

String properties

String properties are shown in Figure 27-21.

[Figure 27-21 String properties

Enter the string in the Text textbox. You can insert tabs and carriage returns by typing Ctrl+Tab and Ctrl+Enter, respectively. You can also use \t to represent a tab and \n for a carriage return.

28. Bitmap, Cursor, Icon, and Font Editors

This ResourceStudio reference chapter contains details about the commands and options found in the Bitmap editor, the Cursor editor, the Icon editor, and the Font editor. For an introduction to ResourceStudio, see Chapter 7, "Adding Look and Feel with Resources."

This chapter shows the editors running in standalone windows. If you edit a binary resource directly (that is, if you open or create it by choosing Open from the Shell window's File menu), the File menu you will see will not match those shown below, and the ID and File fields in the Property sheet will be disabled.


Bitmap Editor

The Bitmap editor (see Figure 28-1) is used to edit bitmaps.

[Figure 28-1 The Bitmap editor

The Bitmap editor displays two views of the bitmap. Each view can be independently zoomed; you may wish to keep one view at normal size for reference, and one at a higher magnification for easier drawing. You can draw in either view, though.

Drawing tools are selected by choosing commands in the Tool menu, or by clicking on the tool in the toolbox. Colors are selected in the palette section of the toolbox. The View menu is used to zoom the views and to turn on the grid. Simple image manipulation functions are available in the Image menu.

For more information about using the Bitmap editor, see Chapter 7, "Adding Look and Feel with Resources."

BitmapExpress

As a new bitmap is created, the BitmapExpress dialog box opens (see Figure 28-2). This dialog box is used to set initial bitmap properties.

[Figure 28-2 BitmapExpress

Select bitmap type

Specifies the number of colors in the bitmap (2, 16, or 256).

Initial size

Specifies the bitmap width and height.

Toolbar bitmap

Select this option if the bitmap will be used as the toolbar in an MFC application. If this option is selected, the number of colors is set to 16 and the initial size is determined by the value of the Buttons across option.

Buttons across

Specifies the number of buttons for toolbar bitmaps. The bitmap's initial size is changed to accommodate the number of buttons you request. Each button is 15 pixels high and 16 pixels across.

File menu commands

The File menu (see Figure 28-3) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 28-3 Bitmap editor File menu

Save
Saves the resource file. If the file is unnamed, this command executes Save As.
Save As
Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.
Export Resource
Opens a dialog box which can be used to save the bitmap in a separate file.
Edit Resource IDs
Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."
ClassExpress
Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Bitmap editor is running in the right pane of the Browser window.
Class Editing
Closes the Bitmap editor.

Edit menu commands

The Edit menu (see Figure 28-4) contains standard editing commands. You can undo operations, and can cut, copy, paste, and clear rectangular regions of the bitmap. To select a region to cut, copy, or clear, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region.

[Figure 28-4 Bitmap editor Edit menu

Undo
Undoes the last Bitmap editor operation.
Redo
Redoes the last undone Bitmap editor operation.
Cut
Copies the selected region to the Clipboard, then clears the region in the bitmap, filling it with the current background color.
Copy
Copies the selected region to the Clipboard.
Paste
Copies the region in the Clipboard to the bitmap. The new region is initially placed in the upper left corner of the bitmap, but may be dragged to a new location.
Clear
Clears the selected region, filling it with the current background color. If no region is selected, the entire bitmap is cleared.

View menu commands

The View menu (see Figure 28-5) contains commands to set view magnification and to set grid options.

[Figure 28-5 Bitmap editor View menu

Zoom 1
Sets the current view's zoom factor to 1 (normal size).
Zoom 2
Sets the current view's zoom factor to 2 (twice normal size).
Zoom 4
Sets the current view's zoom factor to 4 (four times normal size).
Zoom 8
Sets the current view's zoom factor to 8 (eight times normal size).
Grid
Turns on the grid. The grid is only visible in views where the zoom factor is 4 or 8.
Button Grid
Turns on the button grid. The button grid is used to identify the boundaries of toolbar buttons when you are creating a toolbar bitmap.
Grid Settings
Opens the Grid Settings dialog box (see Figure 28-6), used to set grid options.

[Figure 28-6 Grid Settings dialog box

Pixel grid
Turns on display of the pixel grid.
Button grid
Turns on display of the button grid. The spacing of points on the button grid can be specified in the Width and Height fields; defaults for an MFC application toolbar are 16 pixels wide by 15 pixels high.

Tool menu commands

The Tool menu (see Figure 28-7) lets you select drawing tools. While over the drawing area, the cursor changes shape to indicate the currently selected tool. To draw, click or click and drag (as appropriate) in the drawing area. Using the right button rather than the left reverses the roles of foreground and background colors. Drawing tools can also be selected in the toolbox. For more information about drawing operations in the Bitmap editor, see Chapter 7, "Adding Look and Feel with Resources."

[Figure 28-7 Bitmap editor Tool menu

Brush
Selects the brush tool.
Erase
Selects the eraser tool.
Eye Drop
Selects the eye-dropper tool. Use this tool to select foreground and background colors directly from the image.
Line
Selects the straight line tool.
Text
Selects the text tool.
Oval
Selects the hollow oval tool.
Oval (Filled)
Selects the solid oval tool.
Paint
Selects the paint can (flood fill) tool.
Pen
Selects the pen (pencil) tool.
Rect
Selects the hollow rectangle tool.
Rect (Filled)
Selects the solid rectangle tool.
Round Rect
Selects the hollow rounded rectangle tool.
Round Rect (Filled)
Selects the solid rounded rectangle tool.
Select
Selects the Selection tool. Use this tool to select rectangular regions for cut, copy, clear, drag, flip, and invert operations.
Spray
Selects the spray brush (airbrush) tool.

Image menu commands

Commands in the Image menu (see Figure 28-8) perform simple image manipulation functions. To select a region to flip or invert, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region. If no region is selected, these commands operate on the entire bitmap.

[Figure 28-8 Bitmap editor Image menu

Flip Vertically
Flips the selected region vertically.
Flip Horizontally
Flips the selected region horizontally.
Invert Colors
Inverts the colors in the selected region (for example, in a 16 color bitmap, color 0 is replaced with color 15, color 1 is replaced with color 14, and so on).

Toolbar commands

The Bitmap editor toolbar (see Figure 28-9) provides quick access to frequently used menu commands.

[Figure 28-9 Bitmap editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
Flip horizontally:
Same as choosing Flip Horizontally from the Image menu.
Flip vertically:
Same as choosing Flip Vertically from the Image menu.
Invert colors:
Same as choosing Invert Colors from the Image menu.

Toolbox

The Bitmap editor toolbox (see Figure 28-10) provides quick access to the tools available in the Tool menu. The toolbox also lets you select foreground and background colors, brush types, background pattern, and line type.

For more information on the Bitmap editor toolbox, see Chapter 7, "Adding Look and Feel with Resources."

[Figure 28-10 Bitmap editor toolbox

Bitmap properties

Bitmaps have two pages of properties. The General properties are shown in Figure 28-11.

[Figure 28-11 Bitmap General properties

Specify a filename for the bitmap in the File textbox. The Width and Height of the bitmap can be changed here, or the bitmap can be resized in the main display by dragging one of the handles along the bitmap edge.

Palette properties of a bitmap are shown in Figure 28-12.

[Figure 28-12 Bitmap Palette properties

Foreground and background drawing colors can be set by respectively clicking and right-clicking colors in this display. Double-clicking a color opens the Custom Color dialog box, which can be used to change the color's red, green, and blue components.


Cursor Editor

The Cursor editor (see Figure 28-13) is used to edit cursors.

[Figure 28-13 The Cursor editor

Since cursors are much like bitmaps, the Cursor editor behaves much like the Bitmap editor (see "Bitmap Editor," earlier in this chapter). The distinguishing characteristics of cursors are as follows:

The Cursor editor displays two views of the cursor. Each view can be independently zoomed; you may wish to keep one view at normal size for reference, and one at a higher magnification for easier drawing. You can draw in either view, though.

Drawing tools are selected by choosing commands in the Tool menu, or by clicking on the tool in the toolbox. Colors are selected in the palette section of the toolbox. The View menu is used to zoom the views and to turn on the grid. Simple image manipulation functions are available in the Image menu. The cursor hotspot is set by choosing Set Hotspot from the Image menu.

File menu commands

The File menu (see Figure 28-14) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 28-14 Cursor editor File menu

Save
Saves the resource file. If the file is unnamed, this command executes Save As.
Save As
Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.
Export Resource
Opens a dialog box which can be used to save the cursor resource in a separate file.
Export Resource IDs
Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."
ClassExpress
Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Cursor editor is running in the right pane of the Browser window.
Close Editing
Closes the Cursor editor.

Edit menu commands

The Edit menu (see Figure 28-15) contains standard editing commands. You can undo operations, and can cut, copy, paste, and clear rectangular regions of the cursor. To select a region to cut, copy, or clear, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region.

[Figure 28-15 Cursor editor Edit menu

Undo
Undoes the last Cursor editor operation.
Redo
Redoes the last undone Cursor editor operation.
Cut
Copies the selected region to the Clipboard, then clears the region in the cursor, filling it with the current background color.
Copy
Copies the selected region to the Clipboard.
Paste
Copies the region in the Clipboard to the cursor. The new region is initially placed in the upper-left corner of the cursor, but may be dragged to a new location.
Clear
Clears the selected region, filling it with the current background color. If no region is selected, the entire cursor is cleared.
Select All
Select all cursor regions.

View menu commands

The View menu (see Figure 28-16) contains commands to set view magnification and to set grid options.

[Figure 28-16 Cursor editor View menu

Zoom 1
Sets the current view's zoom factor to 1 (normal size).
Zoom 2
Sets the current view's zoom factor to 2 (twice normal size).
Zoom 4
Sets the current view's zoom factor to 4 (four times normal size).
Zoom 8
Sets the current view's zoom factor to 8 (eight times normal size).
Grid
Turns on the grid. The grid is only visible in views where the zoom factor is 4 or 8.
Button Grid
Turns on the button grid.
Grid Settings
Opens the Grid Settings dialog box (see Figure 28-17), used to set grid options.

[Figure 28-17 Grid Settings dialog box

Pixel grid
Turns on display of the pixel grid.
Button grid
Turns on display of the button grid. The spacing of points on the button grid can be specified in the Width and Height fields.

Tool menu commands

The Tool menu (see Figure 28-18) lets you select drawing tools. While over the drawing area, the cursor changes shape to indicate the currently selected tool. To draw, click or click and drag (as appropriate) in the drawing area. Using the right button rather than the left reverses the roles of foreground and background colors. Drawing tools can also be selected in the toolbox. Drawing operations are identical to those in the Bitmap editor.

For more information, see Chapter 7, "Adding Look and Feel with Resources."

[Figure 28-18 Cursor editor Tool menu

Brush
Selects the brush tool.
Erase
Selects the eraser tool.
Eye Drop
Selects the eye-dropper tool. Use this tool to select foreground and background colors directly from the image.
Line
Selects the straight line tool.
Text
Selects the text tool.
Oval
Selects the hollow oval tool.
Oval (Filled)
Selects the solid oval tool.
Paint
Selects the paint can (flood fill) tool.
Pen
Selects the pen (pencil) tool.
Rect
Selects the hollow rectangle tool.
Rect (Filled)
Selects the solid rectangle tool.
Round Rect
Selects the hollow rounded rectangle tool.
Round Rect (Filled)
Selects the solid rounded rectangle tool.
Select
Selects the Selection tool. Use this tool to select rectangular regions for cut, copy, clear, drag, flip, and invert operations.
Spray
Selects the spray brush (airbrush) tool.

Image menu commands

Commands in the Image menu (see Figure 28-19) perform simple image manipulation functions. To select a region to flip or invert, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region. If no region is selected, these commands operate on the entire cursor. This menu also contains a command to set the cursor hotspot.

[Figure 28-19 Cursor editor Image menu

Flip Vertically
Flips the selected region vertically.
Flip Horizontally
Flips the selected region horizontally.
Invert Colors
Inverts the colors in the selected region (for example, in a 16 color cursor, color 0 is replaced with color 15, color 1 is replaced with color 14, and so on).
Set Hotspot
Sets the cursor hotspot. You are prompted to click on the image at the location of the hotspot.

Toolbar commands

The Cursor editor toolbar (see Figure 28-20) provides quick access to frequently used menu commands.

[Figure 28-20 Cursor editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
Flip horizontally:
Same as choosing Flip Horizontally from the Image menu.
Flip vertically:
Same as choosing Flip Vertically from the Image menu.
Invert colors:
Same as choosing Invert Colors from the Image menu.

Toolbox

The Cursor editor toolbox (see Figure 28-21) provides quick access to the tools available in the Tool menu. The toolbox also lets you select foreground and background colors, brush types, background pattern, and line type.

[Figure 28-21 Cursor editor toolbox

The toolbox is slightly different from the toolbox used in the Bitmap editor. In addition to the usual color palette, two extra colors are available: Transparent and Inverted. Transparent is used to draw areas in the cursor where the background screen color shows through. Inverted is used to draw areas in the cursor where the background screen color is bitwise-complemented.

Other than these two additions, the Cursor editor toolbox is identical to the Bitmap editor toolbox. For more information on the Bitmap editor toolbox, see Chapter 7, "Adding Look and Feel with Resources."

Cursor properties

Cursor properties are shown in Figure 28-22.

[Figure 28-22 Cursor properties

Specify a filename for the cursor resource in the File textbox. The cursor hotspot coordinates are displayed below the File textbox. The Image field specifies which of the cursors in the cursor resource is currently displayed. Click on New to create a new cursor in the current resource, or click on Delete to delete the current cursor from the resource. Note that you cannot delete the last cursor from the resource.


Icon Editor

The Icon editor (see Figure 28-23) is used to edit icons.

[Figure 28-23 The Icon editor

Since icons are much like bitmaps, the Icon editor behaves much like the Bitmap editor (see "Bitmap Editor," earlier in this chapter). The distinguishing characteristics of icons are as follows:

The Icon editor displays two views of the icon. Each view can be independently zoomed; you may wish to keep one view at normal size for reference, and one at a higher magnification for easier drawing. You can draw in either view, though.

Drawing tools are selected by choosing commands in the Tool menu, or by clicking on the tool in the toolbox. Colors are selected in the palette section of the toolbox. The View menu is used to zoom the views and to turn on the grid. Simple image manipulation functions are available in the Image menu.

File menu commands

The File menu (see Figure 28-24) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 28-24 Icon editor File menu

Save
Saves the resource file. If the file is unnamed, this command executes Save As.
Save As
Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.
Export Resource
Opens a dialog box which can be used to save the icon resource in a separate file.
Edit Resource IDs
Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."
ClassExpress
Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Icon editor is running in the right pane of the Browser window.
Close Editing
Closes the Icon editor.

Edit menu commands

The Edit menu (see Figure 28-25) contains standard editing commands. You can undo operations, and can cut, copy, paste, and clear rectangular regions of the icon. To select a region to cut, copy, or clear, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region.

[Figure 28-25 Icon editor Edit menu

Undo
Undoes the last Icon editor operation.
Redo
Redoes the last undone Icon editor operation.
Cut
Copies the selected region to the Clipboard, then clears the region in the icon, filling it with the current background color.
Copy
Copies the selected region to the Clipboard.
Paste
Copies the region in the Clipboard to the icon. The new region is initially placed in the upper-left corner of the icon, but may be dragged to a new location.
Clear
Clears the selected region, filling it with the current background color. If no region is selected, the entire icon is cleared.
Select All
Select all icon regions.

View menu commands

The View menu (see Figure 28-26) contains commands to set view magnification and to set grid options.

[Figure 28-26 Cursor editor View menu

Zoom 1
Sets the current view's zoom factor to 1 (normal size).
Zoom 2
Sets the current view's zoom factor to 2 (twice normal size).
Zoom 4
Sets the current view's zoom factor to 4 (four times normal size).
Zoom 8
Sets the current view's zoom factor to 8 (eight times normal size).
Grid
Turns on the grid. The grid is only visible in views where the zoom factor is 4 or 8.
Button Grid
Turns on the button grid.
Grid Settings
Opens the Grid Settings dialog box (see Figure 28-27), used to set grid options.

[Figure 28-27 Grid Settings dialog box

Pixel grid
Turns on display of the pixel grid.
Button grid
Turns on display of the button grid. The spacing of points on the button grid can be specified in the Width and Height fields.

Tool menu commands

The Tool menu (see Figure 28-28) lets you select drawing tools. While over the drawing area, the cursor changes shape to indicate the currently selected tool. To draw, click or click and drag (as appropriate) in the drawing area. Using the right button rather than the left reverses the roles of foreground and background colors. Drawing tools can also be selected in the toolbox. Drawing operations are identical to those in the Bitmap editor.

For more information, see Chapter 7, "Adding Look and Feel with Resources."

[Figure 28-28 Icon editor Tool menu

Brush
Selects the brush tool.
Erase
Selects the eraser tool.
Eye Drop
Selects the eye-dropper tool. Use this tool to select foreground and background colors directly from the image.
Line
Selects the straight line tool.
Text
Selects the text tool.
Oval
Selects the hollow oval tool.
Oval (Filled)
Selects the solid oval tool.
Paint
Selects the paint can (flood fill) tool.
Pen
Selects the pen (pencil) tool.
Rect
Selects the hollow rectangle tool.
Rect (Filled)
Selects the solid rectangle tool.
Round Rect
Selects the hollow rounded rectangle tool.
Round Rect (Filled)
Selects the solid rounded rectangle tool.
Select
Selects the Selection tool. Use this tool to select rectangular regions for cut, copy, clear, drag, flip, and invert operations.
Spray
Selects the spray brush (airbrush) tool.

Image menu commands

Commands in the Image menu (see Figure 28-29) perform simple image manipulation functions. To select a region to flip or invert, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region. If no region is selected, these commands operate on the entire icon.

[Figure 28-29 Icon editor Image menu

Flip Vertically
Flips the selected region vertically.
Flip Horizontally
Flips the selected region horizontally.
Invert Colors
Inverts the colors in the selected region (for example, in a 16 color icon, color 0 is replaced with color 15, color 1 is replaced with color 14, and so on).

Toolbar commands

The Icon editor toolbar (see Figure 28-30) provides quick access to frequently-used menu commands.

[Figure 28-30 Icon editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
Flip horizontally:
Same as choosing Flip Horizontally from the Image menu.
Flip vertically:
Same as choosing Flip Vertically from the Image menu.
Invert colors:
Same as choosing Invert Colors from the Image menu.

Toolbox

The Icon editor toolbox (see Figure 28-31) provides quick access to the tools available in the Tool menu. The toolbox also lets you select foreground and background colors, brush types, background pattern, and line type.

[Figure 28-31 Icon editor toolbox

The toolbox is slightly different from the toolbox used in the Bitmap editor. In addition to the usual color palette, two extra colors are available: Transparent and Inverted. Transparent is used to draw areas in the cursor where the background screen color shows through. Inverted is used to draw areas in the cursor where the background screen color is bitwise-complemented.

Other than these two additions, the Icon editor toolbox is identical to the Bitmap editor toolbox. For more information on the Bitmap editor toolbox, see Chapter 7, "Adding Look and Feel with Resources."

Icon properties

Icon properties are shown in Figure 28-32.

[Figure 28-32 Icon properties

Specify a filename for the icon resource in the File textbox. The Image field specifies which of the icons in the icon resource is currently displayed. Click on New to create a new icon in the current resource, or click on Delete to delete the current icon from the resource. Note that you cannot delete the last icon from the resource.


Font Editor

The Font editor (see Figure 28-33) is used to edit font resources.

[Figure 28-33 The Font editor

Unlike the Bitmap editor, the two views in the Font editor are not equivalent. The left pane displays each of the character bitmaps in the font at normal size. To select a bitmap for editing, click on it in the left pane. The current bitmap is edited in the right pane, which functions in the same way as a pane in the Bitmap editor.

Otherwise, the Font editor functions much like the Bitmap editor. Drawing tools are selected by choosing commands in the Tool menu, or by clicking on the tool in the toolbox. Colors are selected in the palette section of the toolbox (font bitmaps are monochrome, so only two colors are available). The View menu is used to zoom the editing view and to turn on the grid. Simple image manipulation functions are available in the Image menu.

FontExpress

As a new font is created, the FontExpress dialog box opens (see Figure 28-34). This dialog box is used to set initial font properties.

[Figure 28-34 FontExpress

The most important option to specify is the point size. While most of the other options can be easily changed at a later time, a change in the font height may require redrawing any characters you have drawn so far. All of the character bitmaps in the font have the same height.

The Proportional option enables setting the horizontal size of each character independently.

File menu commands

The File menu (see Figure 28-35) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 28-35 Font editor File menu

Save
Saves the resource file. If the file is unnamed, this command executes Save As.
Save As
Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.
Export Resource
Opens a dialog box which can be used to save the font in a separate file.
Export Resource IDs
Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."
Class Express
Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Font editor is running in the right pane of the Browser window.
Close Editing
Closes the Font editor.

Edit menu commands

The Edit menu (see Figure 28-36) contains standard editing commands. You can undo operations, and can cut, copy, paste, and clear rectangular regions of the character bitmap. To select a region to cut, copy, or clear, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region.

[Figure 28-36 Font editor Edit menu

Undo
Undoes the last Font editor operation.
Redo
Redoes the last undone Font editor operation.
Cut
Copies the selected region to the Clipboard, then clears the region in the character bitmap, filling it with the current background color.
Copy
Copies the selected region to the Clipboard.
Paste
Copies the region in the Clipboard to the character bitmap. The new region is initially placed in the upper-left corner of the bitmap, but may be dragged to a new location.
Clear
Clears the selected region, filling it with the current background color. If no region is selected, the entire bitmap is cleared.
Select All
Select all bitmap regions.

View menu commands

The View menu (see Figure 28-37) contains commands to set editing view magnification and to set grid options.

[Figure 28-37 Font editor View menu

Zoom 1
Sets the editing view's zoom factor to 1 (normal size).
Zoom 2
Sets the editing view's zoom factor to 2 (twice normal size).
Zoom 4
Sets the editing view's zoom factor to 4 (four times normal size).
Zoom 8
Sets the editing view's zoom factor to 8 (eight times normal size).
Grid
Turns on the grid. The grid is only visible when the editing view zoom factor is 4 or 8.
Button Grid
Turns on the button grid.
Grid Settings
Opens the Grid Settings dialog box (see Figure 28-38), used to set grid options.

[Figure 28-38 Grid Settings dialog box

Pixel grid
Turns on display of the pixel grid.
Button grid
Turns on display of the button grid. The spacing of points on the button grid can be specified in the Width and Height fields.

Tool menu commands

The Tool menu (see Figure 28-39) lets you select drawing tools. While over the drawing area, the cursor changes shape to indicate the currently selected tool. To draw, click or click and drag (as appropriate) in the drawing area. Using the right button rather than the left reverses the roles of foreground and background colors. Drawing tools can also be selected in the toolbox. Drawing operations are identical to those in the Bitmap editor.

For more information, see Chapter 7, "Adding Look and Feel with Resources."

[Figure 28-39 Font editor Tool menu

Brush
Selects the brush tool.
Erase
Selects the eraser tool.
Eye Drop
Selects the eye-dropper tool. Use this tool to select foreground and background colors directly from the image.
Line
Selects the straight line tool.
Text
Selects the text tool.
Oval
Selects the hollow oval tool.
Oval (Filled)
Selects the solid oval tool.
Paint
Selects the paint can (flood fill) tool.
Pen
Selects the pen (pencil) tool.
Rect
Selects the hollow rectangle tool.
Rect (Filled)
Selects the solid rectangle tool.
Round Rect
Selects the hollow rounded rectangle tool.
Round Rect (Filled)
Selects the solid rounded rectangle tool.
Select
Selects the Selection tool. Use this tool to select rectangular regions for cut, copy, clear, drag, flip, and invert operations.
Spray
Selects the spray brush (airbrush) tool.

Image menu commands

Commands in the Image menu (see Figure 28-40) perform simple image manipulation functions. To select a region to flip or invert, select the Selection tool from the toolbox or from the Tool menu, then drag a box around the region. If no region is selected, these commands operate on the entire character bitmap.

[Figure 28-40 Font editor Image menu

Flip vertically
Flips the selected region vertically.
Flip horizontally
Flips the selected region horizontally.
Invert colors
Inverts the colors in the selected region. Black is changed to white, and white to black.

Toolbar commands

The Font editor toolbar (see Figure 28-41) provides quick access to frequently used menu commands.

[Figure 28-41 Font editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
Flip horizontally:
Same as choosing Flip Horizontally from the Image menu.
Flip vertically:
Same as choosing Flip Vertically from the Image menu.
Invert colors:
Same as choosing Invert Colors from the Image menu.

Toolbox

The Font editor toolbox (see Figure 28-42) provides quick access to the tools available in the Tool menu. The toolbox also lets you select foreground and background colors, brush types, background pattern, and line type.

[Figure 28-42 Font editor toolbox

The only difference between the Font editor toolbox and the Bitmap editor toolbox is that (since font character bitmaps are monochrome) only two colors are ever displayed in the Font editor toolbox palette. For more information on the Bitmap editor toolbox, see Chapter 7, "Adding Look and Feel with Resources."

Font properties

Fonts have four pages of properties. The General properties are shown in Figure 28-43.

[Figure 28-43 Font General properties

Specify a filename for the font in the File textbox.

Header properties of a font are shown in Figure 28-44.

[Figure 28-44 Font Header properties

Sizes properties of a font are shown in Figure 28-45.

[Figure 28-45 Font Sizes properties

Styles properties of a font are shown in Figure 28-46.

[Figure 28-46 Font Styles properties

29. Version Information and Custom Resource Editors

This ResourceStudio reference chapter contains details about the commands and options found in the Version Information editor and the Custom Resource editor. For an introduction to ResourceStudio, see Chapter 7, "Adding Look and Feel with Resources."

Version Information Editor

The Version Information editor (see Figure 29-1) is used to edit version information resources.

[Figure 29-1 The Version Information editor

A version information resource consists of a header and one or more blocks of variable information. The Version Information editor displays the resource as a scrolling list of information, with the header information at the top of the list and the blocks of variable information below. Most data can be edited directly in the list; click on an item, and the data appears in a textbox, ready for editing.

File menu commands

The File menu (see Figure 29-2) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 29-2 Version Information editor File menu

Save

Saves the resource file. If the file is unnamed, this command executes Save As.

Save As

Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.

Edit Resource IDs

Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."

ClassExpress

Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Version Information editor is running in the right pane of the Browser window.

Close Editing

Closes the Version Information editor.

Edit menu commands

The Edit menu (see Figure 29-3) contains standard editing commands. You can undo operations, and can cut, copy, paste, delete, and add variable information blocks.

[Figure 29-3 Version Information editor Edit menu

Undo

Undoes the last Version Information editor operation.

Redo

Redoes the last undone Version Information editor operation.

Cut

Copies the current variable information block to the Clipboard, then deletes the variable information block from the version information resource. Note that a version information resource must contain at least one variable information block, so the last one cannot be cut.

Copy

Copies the current variable information block to the Clipboard.

Paste

Copies the variable information block in the Clipboard to the version information resource.

Delete Block

Deletes the current variable information block from the version information resource. Note that a version information resource must contain at least one variable information block, so the last one cannot be deleted.

New Block

Adds a new variable information block to the version information resource.

Toolbar commands

The Version Information editor toolbar (see Figure 29-4) provides quick access to frequently used menu commands.

[Figure 29-4 Version Information editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.
Cut:
Same as choosing Cut from the Edit menu.
Copy:
Same as choosing Copy from the Edit menu.
Paste:
Same as choosing Paste from the Edit menu.
New:
Same as choosing New Block from the Edit menu.
Delete:
Same as choosing Delete Block from the Edit menu.

Header properties

Properties of the version information resource header are shown in Figure 29-5.

[Figure 29-5 Header properties

Block properties

Properties of the version information variable information block are shown in Figure 29-6.

[Figure 29-6 Block properties


Custom Resource Editor

The Custom Resource editor (or Hex editor) is shown in Figure 29-7.

[Figure 29-7 The Custom Resource editor

Custom resources are created by choosing New Other from the Browser window's Resource menu. Custom resources are edited as hexadecimal data. The size of the custom resource is set in the Property Sheet.

File menu commands

The File menu (see Figure 29-8) contains commands to save the resource file, to edit resource IDs, and to perform other miscellaneous functions.

[Figure 29-8 Custom Resource editor File menu

Save

Saves the resource file. If the file is unnamed, this command executes Save As.

Save As

Opens a Windows File Save As dialog box, which can be used to save the resource file under a new name.

Edit Resource IDs

Opens the Resource ID Browser dialog box, used to browse and modify resource IDs. For more information about managing resource IDs and using the Resource ID Browser dialog box, see "Managing Resource IDs," in Chapter 7, "Adding Look and Feel with Resources."

ClassExpress

Runs ClassExpress, passing the filename of the resource file as the project that ClassExpress should open. This command is only enabled if the Custom Resource editor is running in the right pane of the Browser window.

Close Editing

Closes the Custom Resource editor.

Edit menu commands

The Edit menu (see Figure 29-9) contains commands to undo data changes and to redo undone changes.

[Figure 29-9 Custom Resource editor Edit menu

Undo

Undoes the last data change in the Custom Resource editor.

Redo

Redoes the last undone data change in the Custom Resource editor.

Toolbar commands

The Custom Resource editor toolbar (see Figure 29-10) provides quick access to the undo and redo commands.

[Figure 29-10 Custom Resource editor toolbar

Undo:
Same as choosing Undo from the Edit menu. Right-click on this button to undo multiple operations at once.
Redo:
Same as choosing Redo from the Edit menu. Right-click on this button to redo multiple operations at once.

Custom resource properties

Custom resource properties are shown in Figure 29-11.

[Figure 29-11 Custom resource properties

ID

Specifies the resource ID.

Size

Specifies the size of the custom resource in bytes.

A. Expression Evaluation

An expression comprises operands and operators, such as constants, variables, and functions. You can specify variables and functions using their symbolic names defined in your program. Digital Mars C++ supports standard language operators. This manual does not provide a complete discussion of language expressions.

Entering Expressions

The following IDDE operations prompt you to enter an expression: When one of these operations is executed, the debugger displays the Expression dialog box, shown in Figure A-1. For example, to modify a variable in the Data/Object window, you can input a new value by entering an expression. The debugger evaluates this expression and assigns the result to the variable.

Figure A-1 Expression dialog box

Symbols and Their Scope

A symbol is the name of a variable, procedure, module, or enumerated symbol in your program. You declare symbols in the scope of a procedure or module. When you use a symbol in an expression, the debugger determines its scope based on the module, procedure, and line where the current instruction is located.

The IDDE expression evaluator tries to match an entered symbol against:

If you want the debugger to search for a symbol in other procedures or modules, you must qualify the symbol by using a scope override (described below).

Scope override

You can override the current scope where the debugger looks for a symbol by qualifying the symbol with a module or a procedure name. To override the current scope, use the syntax:
	[ModuleName.][ProcName.] SymbolName 
	
The debugger looks for the symbol SymbolName in the procedure ProcName declared in the module ModuleName. For example, if you enter:
	InOut.WriteString.i
	
the debugger tries to find the symbol i in the scope of the procedure WriteString declared in the module InOut.

If you do not include the module name, the debugger uses the current module (the module containing the current instruction).

For example, if you enter:

	WriteString.i 
	
the debugger tries to find the symbol i in the scope of the procedure WriteString declared in the module displayed in the Source window.

If you specify a module name but not a procedure name, the debugger uses the global scope of the module specified. For example, if you enter:

	InOut.i
	
the debugger tries to find the symbol i in the global scope of the module InOut.

Register symbols

To evaluate processor register values, use the symbols listed in the following tables:
	Table A-1 Processor registers, 16-bit 

	Symbol		Register 

	AX or ax	AX 
	BX or bx	BX 
	CX or cx	CX 
	DX or dx	DX 
	SI or si	SI 
	DI or di	DI 
	SS or ss	SS 
	DS or ds	DS 
	CS or cs	CS 
	ES or es	ES 
	SP or sp	SP 
	BP or bp	BP 
	IP or ip	IP 
	_F or _f	Flags 
	FS		FS available only when debugging in 32-bit mode 
	GS		GS available only when debugging in 32-bit mode 


	Table A-2 Processor registers, 32-bit (available only when debugging 
	in 32-bit mode) 


	Symbol		Register 

	EAX or eax	EAX 
	EBX or ebx	EBX 
	ECX or ecx	ECX 
	EDX or edx	EDX 
	ESI or esi	ESI 
	EDI or edi	EDI 
	ESP or esp	ESP 
	EBP or ebp	EBP 
	EIP or eip	EIP 


	Table A-3 Floating point stack registers 

	Symbol		Floating point stack 

	FP0 or fp0	ST(0) 
	FP1 or fp1	ST(1) 
	FP2 or fp2	ST(2) 
	FP3 or fp3	ST(3) 
	FP4 or fp4	ST(4) 
	FP5 or fp5	ST(5) 
	FP6 or fp6	ST(6) 
	FP7 or fp7	ST(7) 
	

Operators

The IDDE supports standard C and C++ operators in expressions. These operators, described in the following sections, have the same precedence within the debugger's expression evaluator as they do in C and C++.

In addition to the standard operators in C and C++, the IDDE supports the colon operator (:). The colon operator joins a segment:offset pair of unsigned integers to specify an address value. This operator has the same priority as the unary operators.

The IDDE supports the standard C and C++ operators listed below, in descending order of precedence:

Primary

	() [] -> . this :: 
	

Unary

	* & -! ~ ++ --sizeof 
	

Binary

	.* ->* 
	* / % + -
	>> << > < >= <= 
	== != & 
	^ | 
	&& || 
	

Assignment

	 = += -= *= /= %= >>= <<= 
	&= ^= |= 
	
C expressions in the IDDE also may include typecasts of the form:
	(type-name) expression 
	
For C++, the above typecast is valid only for built-in types. Because the debugging information does not associate line numbers with local scopes, the IDDE cannot distinguish variables declared in a local scope. For example, in line 7 of the following source code:
	1 int i; 
	2 proc() 
	3 { 
	4     int i; 
	5     if (i){ 
	6         int i; 
	7         i= 5; 
	8     } 
	9 } 
	
The intent is for the variable i in i = 5 to refer to the i in line 6, but the IDDE will associate it with the i in line 4.

Considerations When Using C++ Expressions

This section describes considerations for working with the IDDE expression evaluator and C++ expressions.

The expression evaluator generally expects the same syntax as the compiler.

Access to class members

All members of a class object are accessible, no matter which type of access control is imposed (public, protected, or private), or if the object is a member of a base class (embedded object).

For example, if class Customer has a private member name, enter the following into the IDDE expression evaluator:

	Customer::name 
	
The expression evaluator provides the value of name in an output dialog box. You also can access members of an object using a pointer to the object.

For example, if the Salesperson class defines a virtual function named totalSales, redefined in the class inherited from Salesperson, totalSales can be called using a pointer to Salesperson:

	salePtr->totalSales() 
	

Ambiguous references

When an expression makes an ambiguous reference to a member name, qualify it with the class name. For example, the class Resistor is defined as follows:
	1 class Parts 
	2 { 
	3   unsigned int specs; 
	4 } resistorParts; 
	5 
	6 class Components 
	7 { 
	8   unsigned int specs; 
	9 } resistorComponents; 
	10 
	11 class Resistor: 
	12 public Parts, public Components; 
	13 { 
	14   int name; 
	15 } resistor; 
	16 ... 
	
Assume that class Resistor inherits from the Parts and Components classes. Both Parts and Components define a member item called specs. If largeResistor is an instance of class Resistor, the following expression is ambiguous:
	largeResistor.specs 
	
To resolve this problem, use either of the following expressions:

Constructors and destructors

The IDDE expression evaluator calls constructor or destructor functions just as it calls normal functions. Functions that declare or return local objects are valid expressions, and they return the address of the resulting object.

Note: The IDDE expression evaluator does not let you call the new and delete operators.

Overloaded functions

The IDDE expression evaluator supports calling overloaded functions only if an exact match exists or if the match does not need a conversion involving the construction of an object. For example, the overloaded function Print is defined as below:
	1 Print( int x) 
	2 { 
	3   ... 
	4 } 
	5 
	6 Print( float y) 
	7 { 
	8   ... 
	9 }
	
In this case, both of the following expressions for the IDDE expression evaluator are valid:

Overloaded operators

IDDE's expression evaluator lets you call an overloaded operator for user-defined types. For example, suppose you define a class that represents arrays as follows:
	class Array array1, array2, array3, array4 
	
If this class has a member function that overloads the + operator, then you can evaluate the following:
	array1 = array2 + array3 + array4 
	
Make sure that no variables overflow during evaluation. The expression evaluator automatically creates temporary objects as needed to store the intermediate values and discards them after it performs the evaluation.

Function and Procedure Calls

The IDDE lets you execute function and procedure calls defined in your program when evaluating an expression. Use this feature to: To include a function call in an expression, use the syntax:
	procedureName([param1[, param2]...]) 
	
You can specify the procedure parameters as expressions. The IDDE passes all parameters by value.

Evaluating expressions with function calls

The IDDE evaluates expressions, except for function and procedure calls, by interpretation. When the interpreter encounters a function call, it saves the application's registers and pushes its own evaluation stack onto the application program's stack. Next, the debugger orders the application to begin executing at the function's entry point. If the Flip Screen command is on, the application's screen comes to the foreground. When the application's procedure returns, the debugger takes control and restores the application's register state. During the evaluation of a procedure or a function, the debugger ignores breakpoints and watchpoints. It takes the return value and continues evaluating the expression, if necessary.

Side effects of expression evaluation

When including function or procedure calls in the IDDE expressions, beware of possible side effects caused when you evaluate a function that results in changes to your program's data. Such changes could alter the behavior of your program after it resumes execution.

Expression Evaluation Errors

The IDDE normally evaluates an expression and displays the result after you press Enter. However, with the Set Conditional Breakpoint command, the IDDE does not evaluate an expression until it reaches the breakpoint. If a run-time error occurs during the evaluation of a conditional breakpoint expression, the IDDE assumes that the expression is false and does not display an error message.

When the IDDE finds a syntax or semantic error in an expression, it displays the error message in the title bar of the debugger's main window.

B. IDDE Settings and Command-Line Options

This appendix provides a series of figures that show the relationship between the settings on the Build page of the IDDE Project Settings dialog box and the command line options that you pass to the command line utilities. To opens the Project Settings dialog box, select Project Settings from the IDDE Project menu. Then click on the Build tab to select the Build page.

The Build page comprises different subpages, each one containing specific options for the compiler, linker, .def file, resource compiler, and librarian utility. Chapter 16, More about Project Build Settings, describes in detail each of the subpages of the Build page.

For detailed information on how these options affect the compilation and linking of your code, refer to the Digital Mars C++ Compiler and Tools Guide.

This chapter consists of a series of figures showing subpages of the Build page. Each figure has callouts to each option that has a command-line equivalent.

Mapping IDDE Options to Command-Line Parameters

Options in the callouts to the Compiler pages are passed to the dmc.exe compiler. Options in the callouts to the Linker subpage are passed to the optlink.exe linker. Definition file options (shown in the Definition subpages callouts) are placed in your project's .def file. Options for the resource compiler (Resource Compiler subpage) are passed to the Digital Mars resource compiler and linker utility, rcc.exe. Options for the librarian utility are passed to lib.exe.

















C. Using NetBuild

NetBuild is a feature of Digital Mars C++ that lets you distribute the task of building a project across the network. Using NetBuild, you can employ any idle PCs on the network to compile your files.

Before you can use NetBuild you must install the NetBuild Administrator software on your network server and the NetBuild Server software on any PCs that will participate in the distributed build. For information on how to install the NetBuild feature of Digital Mars C++, see the Getting Started Guide.

The following sections detail how to use the Digital Mars C++ NetBuild feature.

Using the Build Client

Your PC (the one controlling the build) is called the build client. Functioning as a client, it must request a server to perform a task. The PCs that compile your project are called build servers.

Configuring the build client

The options for controlling the NetBuild on the build client are located in the Project Settings dialog box. To access these options, select Settings from the IDDE's Project menu, then click on the Build tab to bring up the Build page of the Project Options dialog box. In the list of subpages on the left, choose Make.

The Make subpage is shown in Figure C-1.

[Figure C-1 The Make subpage

To turn on the NetBuild feature, make sure that the Use NetBuild check box has a check mark.

If you enable the Use Remote Headers option, the client PC instructs the build servers to use the header files on their local drives (as opposed to getting the header files from the build client). This option can be overridden on the build server side by disabling the Use Local Headers option in the Build Server Configuration window. See "Configuring a build server," later in this chapter.

When you enable the Use NetBuild option, you must specify the pathname of the build server control directory in the Working Directory textbox. This is the directory in which the NetBuild Administrator is installed on the network server. You specify this pathname in the Working Directory textbox. All the PCs participating in the distributed build must have access to this directory.

If your network administrator has set up a network password, you must enter it in the Remote Password textbox. If sources are shared through Microsoft Network on a local hard disk, and a sharing password is used for access protection, it must be specified in the Remote Password textbox.

Starting a distributed build

Once you have configured the build client, every time you rebuild or update your project, the NetBuild system identifies the build server( s) that can participate in the distributed build. If there is at least one build server available, the distributed build can occur; otherwise the build client builds the project locally. For information on starting and configuring build servers, see the following section.

When the distributed build process begins, the Build Client window opens on the client PC's screen (see Figure C-2). This window allows you to monitor the progress of the distributed build.

When the build is done, a message specifying successful completion or an error condition is displayed in the output window on the build client.

Monitoring a distributed build

You can monitor a distributed build from the build client PC by viewing the messages displayed in the Build Client window.

[Figure C-2 The Build Client window This window displays an icon each for the build client and each of the build servers participating in the distributed build. Each icon shows a list of the programs and header files being handled by that particular PC. The name of the build server is shown at the top of its icon.

Stopping a distributed build

You can cancel a build from the build client PC by: Depending on the options that have been specified for the project being compiled, there may be a short delay before the distributed build stops.

Using a Build Server

A build server is a PC that is helping the build client PC compile a project. A build server normally is idle until a client requests it to perform a task. There must be at least one build server in the distributed build environment.

Starting a build server

You start the NetBuild Server application by double-clicking on its icon, or as you start any other Windows program. Once started, the server application is minimized into an icon. It then runs in the background, waiting to receive a task from a build client.

Configuring a build server

When the build server compiles files, the build server application name changes to the name of the file it is compiling.

Double-click on the NetBuild Server application icon to display a Build Server Configuration window (see Figure C-3).

[Figure C-3 The Build Server Configuration window

This window displays the build server name, the pathname of the working directory, and the pathname of the directory containing the header files used in the compilation. (If the pathname of the working directory is changed, then the pathname must be identical in the client working directory.) This window also contains a message area; this is where messages, such as the name of the file being compiled, the file being read, and error messages, are displayed.

If Use Local Header Files option is enabled, the build server looks for the header files in the "Directory for Header Files" specified in the build server window. If the Use Local Header Files option is not enabled, the build server gets the header files from the build client PC. This option is enabled if the Use Remote Headers option is enabled on the client PC; however, you can still force the build client to retrieve the headers from the build client by disabling the Use Local Header Files option in the Build Server Configuration window.

Note: If Use Local Header Files is selected and the build server needs a header file and cannot find it, the build server sends the job back to the build client for processing.

If the Status Bar option is selected, the status bar is displayed at the bottom of the Build Server Configuration window.

Stopping a build server

You can close the NetBuild Server application by: If the server is participating in a distributed build when you try to stop it, the dialog box shown in Figure C-4 is displayed.

[Figure C-4 Abort Compile dialog box

If you click on Cancel in the dialog box, the build server resumes processing. If you click on Close, the build server finishes processing any files that are in the queue (that is, files currently being compiled and files already read), then stops. If you click on Abort, the build server halts the current compilation and returns the uncompleted job to the build client. If you selected Close or Abort, the NetBuild Server application closes and you must restart it if you want the PC to be able to participate in a distributed build again. (See "Starting a build server," earlier in this chapter.)

Troubleshooting

If the build client or build server seems to hang (because no messages are being displayed), wait for a few minutes. NetBuild tries to establish a connection several times before giving up.

If both the build client and build server start, but the build server does not compile your program, then:

  1. Make sure you selected the NetBuild option on the Make Subpage.
  2. Make sure the NetBuild Working Directory has the correct pathname for the build server control directory.
  3. Make sure the build client and build server have the same drive mapping.
  4. Make sure the build servers have access tot he include directories. The include files can be installed on the build server, or in a fully-sharable directory on the build client.
If the build client does not receive messages from the build server( s):
  1. Make sure the network is not down.
  2. Make sure the build server is still running. If the build server is still displaying messages, the network connection may be broken. If not, Windows may be hung. If the build server is in iconized form, it may have finished the compile, but was not able to communicate with the build client.
If files do not compile or the build server can't find header files:
  1. Make sure all relevant files have been moved to the network drive.
  2. Make sure the environment variables that indicate where to find the header files are set properly.

NetBuild Messages

This section describes the NetBuild error and information messages.

Build client messages

Build being done on build_server
This informational message is repeated for each command line. build_server is the name of the build server compiling the module.
Compile has been aborted, Rescheduling to another server
The build server was shut down abruptly. The job has been sent to another server to be compiled. This message is displayed when someone cancels the build and selects the abort option.
NetBuild has lost contact with build_server
The netbuild has lost contact with the specified server. The build server PC is hung, the network is down, or the netbios protocol is not set correctly.
There is not enough memory to do distributed builds
The system does not have enough memory to run.
Unable to access build_server. client_server will compile this build locally
The build server was not able to access the specified file. The more likely problems are that the drive on the client side is not shared or the file is not in the shared directory.
Unable to Load network connection Dlls (WNET32, WNET16)
The system was not able to load the following DLLs: wnet32.dll, wnet16.dll. They may be missing or corrupted.
Unable to Load network share Dlls (WSHR32, WSHR16)
The system was not able to load the following DLLs: wshr32.dll, wshr16.dll. They may be missing or corrupted.

Build server messages

Another Station has the control file locked
The control file has been locked by another station. It is probable that station is also hung.
Error checking for Control file, Error xx
An unexpected error has occurred. Record the error number (xx) and contact technical support, providing as much information as possible.
Error checking for Control Path Error xx
An unexpected error has occurred. Record the number (xx) and contact technical support, providing as much information as possible.
Error in packet
The build server and build client software are not the same version.
Problems reading ini file.
There is a problem reading the .ini file. This message should not occur if the .ini file is missing.
Problem with initializing build server name
There is a problem reading the .ini file. This message should not occur if the .ini file is missing.
Problem with initializing control file
There is a problem reading the .ini file. This message should not occur if the .ini file is missing.
Problem with initializing header path
There is a problem reading the .ini file. This message should not occur if the .ini file is missing.
The control file path is invalid
The specified build server control file pathname specified in the NetBuild Working Directory dialog box is not valid.

Network errors

Network Dlls Failed to initialize Correctly, Cannot initialize
Netbios on lana xx Unable to initialize netbios. It may not be installed correctly. The lana xx refers to the netbios protocol that has failed (there can be several on a machine).
Network Dlls Failed to initialize Correctly, Listens Failed To Establish
System was able to initialize netbios but unable to set up communication.
Network Dlls Failed to initialize Correctly, Netbios command xx error code yy lana zz
A call to netbios has failed. This message lists the command, the error code, and the lana number (all in hexadecimal).
Network Dlls Failed to initialize Correctly, Netbios is not installed.
This message refers to the netbios name table. The system probably has crashed. The best solution is to restart your computer.
Network Dlls Failed to initialize Correctly, Netbios name already exists.
This message refers to the netbios name table. The system probably has crashed. The best solution is to restart your computer.
Network Dlls Failed to initialize Correctly, Netbios name table full.
This message refers to the netbios name table. The system probably has crashed. The best solution is to restart your computer.
Network Dlls Failed to initialize Correctly, No Error
Information Available Unknown error. No error information is available. This is a catch-all error that the system uses.
Network Dlls Failed to initialize Correctly, Out Of Memory
System is low on memory.
Network Dlls Failed to initialize Correctly, Reset Timed out on lana xx
Unable to reset the netbios settings. It probably is not installed correctly. The lana xx refers to the netbios protocol that has failed. (There can be several on a machine.)
Network Dlls Failed to initialize Correctly, Unable To Get Network Address
Unable to get the address of the network card. The card or netbios probably is not installed correctly.
Network Dlls Failed to initialize Correctly, Unknown Error
Unknown error. No error information is available. This is a catch-all error that the system uses.
Unable to Load network Dll because could not find entry point in network DLL
The DLL, which was able to load, is not a valid DLL.
Unable to Load network Dll because could not load NB32.DLL
The system could not load the nb32.dll file. This is a Windows NT or Windows 95 message.
Unable to Load network Dll because could not load NBND.DLL
The system could not load the nbnd.dll or nbd.dll files. This is a Windows NT or Windows 95 message.