Visual-C PDF
Visual-C PDF
Visual-C PDF
Certification Objectives. 1
Introduction to Visual Studio. 4
Introduction to Visual C++. 6
Installation Requirements. 13
Installing Visual C++ 6.0 Using Visual Studio. 18
Installing the MSDN Library and InstallShield. 26
Server Tools. 30
Service Packs. 34
From the Classroom.. 37
Certification Summary. 38
Two-Minute Drill 39
Certification Objectives
Using Microsoft Visual C++ and Visual Studio
Installing Visual C++ Development Tools
Welcome to your first steps toward achieving success with the Visual C++ 6.0 Desktop exam. Whether youre a long-time C++ programmer
or new to Visual C++, youre bound to be impressed by whats included in Visual C++ 6.0 and the sheer power and performance of this
development platform. We will build your knowledge of Visual C++ 6.0 throughout this book. This chapter will start you off with an
overview of the development tools included in the various editions of Visual C++ 6.0 and Visual Studio.
As well see, Visual C++ 6.0 can be purchased by itself, or as part of the Visual Studio suite of products. Although Visual C++ 6.0 is available
in each package, the products and tools available in each are quite different. To give you even more decisions on acquiring Visual C++ 6.0,
you also have a choice of three editions: Standard, Professional, and Enterprise.
From here, well discuss how to install Visual C++ 6.0, and the minimal system requirements for different editions. This will ensure that
Visual C++ 6.0 is properly installed and ready for use. Finally, well delve into how to acquire and install service packs which resolve known
issues with your installation of Visual C++ 6.0 and other products in the Visual Studio suite.
Using Microsoft Visual C++ and Visual Studio
The first steps to using Visual C++ 6.0 are acquiring it, knowing what tools are available, and knowing what those tools are for. The first of
these steps may seem simple at face value, until you realize that Visual C++ 6.0 is available for purchase as its own package or as part of the
Visual Studio suite of products. Beyond this, Visual C++ 6.0 is also available in three different editions:
StandardThe Standard edition includes the basic products and tools for creating applications. This edition also includes tutorials and
samples, and is often the best choice for programmers who are just learning how to program with Visual C++.
ProfessionalThe Professional edition includes products and tools for creating applications, and is geared toward developers of desktop
applications.
EnterpriseThe Enterprise edition includes products and tools for creating applications, but has additional features geared toward
enterprise development.
Although Visual C++ 6.0 is available in each of these editions, Visual Studio is only available in the Professional and Enterprise editions.
Which package and edition of Visual C++ 6.0 or Visual Studio you use largely depends on individual needs and resources.
Exam Watch: Knowing the individual components of Visual Studio or Visual C++ is not a direct objective of the exam. However, knowing
this information can be useful in understanding whats being asked in a question. The Visual Studio and Visual C++ introduction sections of
this chapter serve to introduce you to what will be discussed for exam objectives in future chapters, and to aid you in understanding the
software as a whole.
Although its cheaper to purchase Visual C++ 6.0 on its own, Visual Studio comes with significantly more development tools. Although well
discuss each of these tools later, purchasing Visual Studio costs less than if you purchased each development tool separately. In other words,
you get more for your dollar, if more is what youre actually looking for.
This also can be said of the individual editions of Visual C++ 6.0 and Visual Studio. Each edition includes a variety of features, with Standard
having the smallest number and Enterprise having the most. As mentioned, Standard is particularly useful if youre just learning Visual C++
6.0, or using it as a secondary development platform. The Professional edition contains more tools, and is particularly useful for developers of
desktop and Internet applications. Finally, the high end of the editions is the Enterprise edition, which is often acquired for enterprise
development of network applications. This edition contains the most tools, and is subsequently more expensive.
On the Job: Many new developers tend make the mistake of getting more than they really need when purchasing these packages. Most
developers purchase the Professional edition for desktop, and the Enterprise edition for distributed applications. However, dont fall into the
trap of buying what you dont use. If youre only going to program with Visual C++ 6.0, then theres probably no need in buying it as part of
Visual Studio (which includes other development products).
As for the individual features of each edition and package, well discuss those in each of the sections that immediately follow. Both Visual
Cha 01:
Studio and Visual C++ 6.0 include a number of different tools that help reduce the time spent on developing applications. In addition, there
are tools that can aid in analyzing and improving the performance of your applications, as well as those that make distributing your solution
easier.
Introduction to Visual Studio
Visual Studio is a suite of products used for developing and managing applications, components, and data access. It provides you with a wider
scope of options than Visual C++ alone, because it contains more than just Visual C++ 6.0. Regardless of whether you use the Professional or
Enterprise edition of Visual Studio, you receive the following:
Visual Basic 6.0Development system based on the BASIC programming language
Visual C++ 6.0Development system based on the C++ programming language
Visual J++ 6.0Development system based on the Java programming language
Visual FoxPro 6.0Development system used for creating databases and database applications
Visual InterDev 6.0Development system used for creating Web applications
Although each of these are available for purchase separately, you can get them in one package with Visual Studio. If you purchase the
Professional edition of Visual Studio (VS), then each of the development systems included are Professional edition as well. Similarly, the
Enterprise edition also includes the Enterprise editions of these systems. Therefore, if you have VS Professional edition, then you get the
Professional edition of Visual C++ 6.0. If you have the Enterprise edition of VS, then you would be using the Enterprise edition of Visual
C++ 6.0.
In addition to these development systems, you also receive the Microsoft Developer Network (MSDN) Library, Single Edition. This is an
information resource that can help you when you need answers fast. It includes a knowledge base of information, sample code, product
documentation, software developers kit (SDK) documentation, technical documents, and examples.
The Windows NT Option Pack is also included with both the Professional and Enterprise editions of VS. If youre installing the Windows NT
Option Pack on Windows NT systems (that is, Windows NT Server or Windows NT Workstation), the option pack includes Component
Services 2.0 and Internet Information Services 4.0. On Windows 9x systems, the options in the Windows NT Option Pack are more limited.
Installing the option pack on Windows 95 or Windows 98 will install the Personal Web Server.
The Enterprise edition of Visual Studio also includes Visual SourceSafe. Visual SourceSafe (VSS) is used for version control of source code.
As well see in Chapter 2, this allows you to store your source code to a database, enabling you to restore and use previous versions of your
source code. This is useful for organizing the source code of multiple developers as well as that of the individual developer. If an improper or
incorrect change is made to source code, or you simply want to revert to the code you used earlier, you can restore that code from the VSS
database that it was saved to.
The Enterprise edition also includes the Microsoft BackOffice Server 4.5, Developer Edition. This is made up of several pieces of server
software, including, Microsoft SQL Server, Microsoft SNA Server, Microsoft Exchange Server, Microsoft Site Server, and Microsoft System
Management Server. However, if youre thinking of using this version of BackOffice Server for anything other than development, you may
want to think twice. The Developer Edition of BackOffice Server is only licensed to support ten concurrent connections. This means only ten
people can use this software at any given time.
As Table 1-1 shows, Visual Studio also includes a number of additional tools for application design, performance analysis, component
management, and designing SQL Server and Oracle databases. Most of these are only available with the Enterprise edition, but some are also
included in the Professional edition. Application Performance Explorer is a tool used for testing SQL Server queries and data connections.
Visual Modeler is used for the design of three-tier distributed applications. Visual Component Manager (which is also available with the
Professional edition) allows you to manage components by enabling you to organize, find, and insert components into development projects.
Visual Studio Analyzer is a tool used in analyzing distributed applications created with Visual Studio. Each of these tools can enhance
development of distributed and desktop applications.
Visual Studio Feature Professional
Edition
Enterprise
Edition
Visual Basic 6.0 X X
Visual C++ 6.0 X X
Visual J++ 6.0 X X
Visual FoxPro 6.0 X X
Visual InterDev 6.0 X X
Visual SourceSafe 6.0 X
Microsoft Developer Network (MSDN) Library, Single Edition X X
Windows NT Option Pack X X
Microsoft BackOffice Server 4.5, Developer Edition X
Visual Component Manager X X
Microsoft Repository X
Visual Modeler X
Application Performance Explorer X
Visual Studio Analyzer X
Table 1-1: Visual Studio 6.0 Features by Edition
Introduction to Visual C++
As part of Visual Studio, or on its own, Visual C++ 6.0 includes a number of features that can be used for creating desktop and distributed
applications. You dont get all of the development systems, such as Visual Basic or Visual J++, when acquiring Visual C++ 6.0 on its own,
but you do get the Visual C++ 6.0 development system and a considerable number of the tools included with Visual Studio. As well see, the
components included in the Visual C++ package are beneficial to the creation of robust applications.
Cha 01:
Although Visual C++ 6.0 is available in Professional and Enterprise editions through Visual Studio, it is also available as a Standard edition
when Visual C++ 6.0 is purchased on its own. The Standard edition includes the bare bones tools for developing applications, and is useful for
new programmers who wish to learn Visual C++. For this reason, previous versions of the Standard edition were called learning editions.
New to this edition are tutorials that arent available with any of the other editions. These step-by-step instructions teach you how to program
applications using Visual C++ 6.0, and are set up so that no previous knowledge of C++ is required.
Aside from these tutorials, all of the features included in the Standard version are also available in the Professional and Enterprise editions of
Visual C++ 6.0. As Table 1-2 shows, the Standard edition has many of the features included in the Professional Edition, and the Enterprise
edition has all of the features of the Professional edition plus a few more. This allows you to pick the edition that best suits your needs as a
developer.
Feature Description Standard Professional Enterprise
Tutorials New tutorials to learn Visual C++ 6.0 X
Samples Samples of source code, used for
assistance in creating applications
X X X
Microsoft Foundation
Classes (MFC) Library
The classes, global functions, global
variables, and macros used in
programming Visual C++ 6.0
applications
X X X
C\C++ Runtime
Libraries
Routines used in creating Visual C++
6.0 applications
X X X
Active Template Library
(ATL)
Used in creating server-side
components and ActiveX Controls
X X X
Internet Support Controls, APIs, and classes used for
integrating applications with the
Internet. This includes Internet
Explorer 4.0 common controls, Internet
Server Application Program Interface
(ISAPI) extensions, Dynamic
Hypertext Markup Language
(DHTML), Chttp* MFC classes
X X X
ActiveX Controls and
Document support
Ready to use, prebuilt ActiveX
Controls that can be added to your
project. In addition, there is the new
ability to create composite controls,
and you can have your applications act
as active document containers
X X X
Component and Object
Gallery
Storehouse of code that can be prebuilt
components, ActiveX controls, or user
defined components
X X X
Component Object
Model (COM) support
Support for the Component Object
Model, inclusive to compiler COM
support
X X X
Visual Database Tools Full versions of these tools are only
available in the Enterprise version.
Read-only version available in the
Professional and Standard versions
X X X
Static linkage to MFC Enables you to resolve MFC references
at link time rather than runtime
X X
Code Optimization Enables smaller, faster executables
(EXEs) and dynamic-link libraries
(DLLs)
X X
Source Code Profiler Enables you to analyze code to
determine which parts could use
performance modifications
X X
Data-bound controls RemoteData, DBGrid, DBCombo, and
DBList controls for data access
X X
Custom AppWizard Enables you to create an AppWizard to
create projects and custom starter files
X X
InstallShield Packages applications you create for
easy installation
X X
Cluster Resource Wizard Used to generate projects for
implementation of a Clustering Service
resource type
X X
Visual SourceSafe Used for version control of source code X
MFC Data binding Ability to do simple and complex data
binding to any ActiveX data control
X
Remote Automation Used for creating and running
Automation programs
X
Component Services Transaction processing server
application
X
Microsoft SQL Server
6.5, Developer Edition
Database server application X
SQL Editor and
Debugger
Integrated SQL Editor (for writing and
editing SQL statements) and debugger
(for finding bugs in SQL statements)
X
Cha 01:
Internet Information
Services
Web Server Application X
Table 1-2: Visual C++ 6.0 Features by Edition
Visual C++ 6.0 supports the Component Object Model (COM). This is an object model that enables various software
componentsapplications, controls, data objects, services, and so forthto interact as objects. These objects contain data, and provide a
method through which other components can access that data. In other words, there is an interface in which one component can interact with
another. The provider of these services or data is called the server, whereas the user is called a client. The client interacts with the server
through the servers interface, which consists of functions available for accessing necessary data.
ActiveX is built upon COM, so its no wonder that Visual C++ 6.0 supports ActiveX. Visual C++ 6.0 includes a large number of prebuilt,
ready to use ActiveX controls. New to Visual C++ 6.0 are composite controls. These are new controls that you can create by combining your
existing ActiveX and Windows controls. These are then added to the Active Template Library, and can be used in your application projects.
Each of the editions include Internet Support features, which allow you to integrate your applications with the Internet. Internet Explorer
Common Controls can be added to an application, allowing users of your application to use the Internet through your solution. Internet Server
Application Programming Interface (ISAPI) extensions are included, so you can write programs for Internet Information Services. You can
use Dynamic Hypertext Markup Language (HTML) support in Visual C++ 6.0 to manipulate data, and make interactive Web applications. In
addition to these, there are a number of CHttp* classes that can be used by your solution. These classes are as follows:
CHttpInternetConnectionManages connections to the Internet, and is the base class for the CHttp* classes that follow.
CHttpConnectionManages Internet connections to an Hypertext Transfer Protocol (HTTP) server
CFtpConnectionManages Internet connections to a File Transfer Protocol (FTP) server
CGopherConnectionManages Internet connections to a Gopher server
Each of these can be used in your application to manage connections to servers that deal with certain areas of the Internet, and to manage your
connection to the Internet itself. In addition to these classes, there are numerous objects available for use in your solution.
InstallShield is only available with the Professional and Enterprise editions. It packages applications that you create. This allows users who
wish to install your application to easily setup the application, by following step-by-step instructions. This allows your applications to benefit
from the same type of setup as products from Microsoft.
A number of server tools are included in the Enterprise edition of Visual C++ 6.0. These tools include the following:
Microsoft SQL Server 6.5, Developer Edition (with Service Pack 3)
Internet Information Services 4.0
Component Services
Microsoft SQL Server 6.5, Developer Edition allows you to test applications that you create for this database server. Because it is a developer
edition, youre limited to ten concurrent connections. Internet Information Services (IIS) is a Web server. You can use this server application
for publishing Web pages and testing any of the Web applications you create with Visual C++ 6.0. Component Services is a transaction
processing system. A transaction is a group of tasks that are executed as a single action. Together, these server applications allow you to
create, deploy, and manage applications for enterprise, Internet, and intranet servers.
Installing Visual C++ Development Tools
In many ways, there is little difference between installing Visual C++ 6.0 on Windows 95, Windows 98, Windows NT Workstation, and
Windows NT Server. There are no separate installation programs for the different platforms, and screens that appear during the installation
process are the same. The difference is that certain tools cant be installed on every platform, and certain additional measures must be taken
when installing on or from Windows NT systems.
Windows NT has higher security than Windows 9x, and Windows NT networks use permissions to dictate what applications can be used by
users, and which folders on a Windows NT systems hard disk can be accessed. On Windows NT Workstations, these permissions are set with
the User Manager program. On Windows NT Server, these permissions are set with User Manager for Domains. These programs are used to
administer accounts on Windows NT systems and networks. A major difference between these two programs is that User Manager for
Windows NT Workstation cant administer and set permissions for domain user and administrator accounts. It can, however, set permissions
for local users and groups. Which of these programs you use has a great deal to do with how your network is set up, and should generally be
discussed with your network administrator.
The reason that permissions are so important is because they control access to files and folders. This means that if your account doesnt have
access to a CD-ROM from which you want to install Visual C++ 6.0, you wont be able to access the installation files. If youre installing
from a distribution server, which has all the installation files stored on that servers hard disk, you will also need adequate permissions to
install from that servers folder. In addition, youll need proper permissions to use the files once theyve been installed. Otherwise, you wont
be able to start and use Visual C++ 6.0 after installation is complete.
Although many of the details regarding these issues go beyond the scope of this book, you should consult with your network administrator to
ensure that you have adequate access to install Visual C++ 6.0. If you do not, then you wont get far in installing and using this development
system and its tools.
In addition to having proper permissions, youll also need to ensure that the computer youre installing to meets the minimal requirements for
Visual C++ 6.0. As well see in the section that follows, this means that your computer is new and powerful enough to run Visual C++ 6.0,
that there is enough hard disk space to install, and that the Microsoft operating system currently installed is able to handle running Visual C++
6.0.
Following this, well go into the details of how to install Visual C++ 6.0 onto your computer. As well see, this can be a time consuming task
which may appear confusing at first. However, once youve gone through the process once or twice, youll find that this is relatively
straightforward, and not as complicated as it might appear.
Cha 01:
Installation Requirements
Before actually installing Visual C++ 6.0or any software for that matteryou should determine if the computer meets the minimal system
requirements. System requirements are the minimal software and hardware needed by the program to work properly. This includes such
elements of your system as the operating system used, free hard disk space, processor, RAM, and so forth. If your computer doesnt meet the
requirements of the Visual C++ 6.0 edition being installed, then the installation will fail or Visual C++ 6.0 wont function as expected.
Exam Watch: Although minimum installation requirements arent a specific objective of the exam, it is an important part of installing Visual
C++ 6.0 Development Tools, which subsequently is an objective. Many installation problems are due to the fact that the system fails to meet
the minimal requirements of the software youre attempting to install. This results in the installation failing completely, or the components
that are installed failing to function as they should. Before taking the exam, make sure you understand the minimal requirements for each
edition of Visual C++ 6.0, on both Windows 9x and Windows NT. This will help you analyze problems being discussed in exam questions,
and determine why a certain installation is failing.
As we learned earlier in this chapter, Visual C++ 6.0 comes in different editions, which include different features. The Professional edition
includes more tools than the Standard edition, and the Enterprise edition includes more than the other editions. As such, with each higher
edition used, more hard disk space needs to be used, and in most cases, a faster processor is needed. As seen in Table 1-3, different amounts of
free disk space are required in each edition to accommodate the installation of different features. Without checking the minimal requirements
before installing, you may waste time and money on an edition of Visual C++ that doesnt work on your system.
Requirement Standard Edition Professional Edition Enterprise Edition
Operating System Windows 95 or later, or
Windows NT 4.0 or
higher (with Service Pack
3 installed)
Windows 95 or later, or
Windows NT 4.0 or
higher (with Service Pack
3 installed)
Windows 95 or later, or
Windows NT 4.0 or
higher (with Service Pack
3 installed)
Processor 486/66 MHz or higher,
with Pentium 90 or higher
processor recommended
Pentium class processor,
with Pentium 90 or higher
recommended
Pentium class processor,
with Pentium 90 or higher
recommended
Random Access Memory
(RAM)
24MB with 32MB
recommended
24MB with 32MB
recommended
24MB with 32MB
recommended
Free Disk Space Typical: 225MB
Full: 305MB
Typical: 290MB
Full: 375MB
Typical: 305MB
Full: 405MB
Other Requirements CD-ROM, mouse, VGA
Monitor (SVGA
recommended), Microsoft
Internet Explorer 4.01
Service Pack 1
CD-ROM, mouse, VGA
Monitor (SVGA
recommended), Microsoft
Internet Explorer 4.01
Service Pack 1
CD-ROM, mouse, VGA
Monitor (SVGA
recommended), Microsoft
Internet Explorer 4.01
Service Pack 1
Table 1-3: System Requirements for Visual C++ 6.0 by Edition
For each edition of Visual C++, the operating system requirements are the same. You need to be running Microsoft Windows 9x or Windows
NT version 4.0 or higher. However, if youre using Windows NT, youll need to install Service Pack 3 (SP3), which is included on the Visual
C++ installation CD-ROM. Service Pack 4 and Service Pack 5 have been released, and are available on Microsofts Web site, but Visual
Studio only requires SP3 to be installed. Service packs contain upgraded files, which contain changes in code and bug fixes to known issues.
As well see later, there are also service packs available for Visual Studio. If Service Pack 3 isnt installed on your Windows NT system, then
Visual C++ may not function as expected.
The operating system requirements arent the only common requirements among the different editions. Each edition requires a minimum of
24MB of RAM, but the recommended amount of memory your computer should have is 32MB. Having this extra memory will increase
Visual C++ 6.0s performance, enabling you to do your work faster. The same can be said for the processor power of your computer.
Although Visual C++ 6.0 Standard edition only requires a 486/66 processor, its highly recommended that you use a processor that meets the
requirements of the two higher editions. This means using a Pentium class processor (Pentium 90 or higher being recommended). Although
you can get away with the bare minimum of the system requirements, often more means more. As you put more RAM, processor power, and
free disk space into your system, youll notice enhanced performance when using larger software packages like Visual C++.
Youll also need Microsoft Internet Explorer (IE) version 4.01 or later installed on your computer. This is used to display online user
assistance and any browser applications you create. If youre using IE 4.01, youll need to install the Microsoft Internet Explorer 4.01 Service
Pack 1, which is included on Visual C++ 6.0s installation CD-ROM. If you have a later version of IE, such as Internet Explorer 5, installed
on your computer, this service pack is unnecessary. The bug fixes and benefits that the service pack provides are part of the newer versions.
Some of the other requirements for Visual C++ 6.0 are common to almost any software you install in the Windows environment. Because
point-and-click navigation is the foundation of the Windows Graphical User Interface (GUI), youll need a mouse or some other pointing
device. Youll also need a Video Graphics Adapter (VGA) monitor, although Super VGA is recommended.
Finally, youll need a CD-ROM drive to install Visual C++ 6.0 from the installation CD-ROM. This may, however, not be necessary if youre
connected to a network. Rather than inserting the CD-ROM into the CD-ROM drive of your local computer, you may be able to install Visual
C++ 6.0 over the network. If you have proper permissions to access the CD-ROM drive of a network server or workstation, you can insert the
CD-ROM into the CD-ROM drive of that computer. You then access the CD-ROM drive from the workstation you wish to install to, and
Visual C++ 6.0 will be accessed over the network. If your network server doesnt have a CD-ROM drive, or that CD-ROM drive is regularly
used for other CD-ROMs, you can copy the installation files to a servers hard disk. You would then access the installation files located in the
folder ( directory) on that server, and install over the network. In using either of these approaches however, you should ensure you have
proper permissions to do so. For more information on this, consult with your network administrator.
In addition to Visual C++ 6.0 itself, the different editions include various products. As Table 1-4 shows, each edition comes with extra
software that can be used when developing Visual C++ 6.0 applications. Because each of these products take up their own space on your hard
disk, its important that you take these requirements into account when determining whether your system meets the minimal requirements for
installing a particular edition.
Product Standard Edition Professional Edition Enterprise Edition
Cha 01:
Internet Explorer Hard disk space:
Typical: 43MB
Full: 59MB
Hard disk space:
Typical: 43MB
Full: 59MB
Hard disk space:
Typical: 43MB
Full: 59MB
MSDN Hard disk space:
Typical: 57MB
Full: 493MB
Hard disk space:
Typical: 57MB
Full: 493MB
Hard disk space:
Typical: 57MB
Full: 493MB
Windows NT Option
Pack
Not Included with
this Edition
Hard disk space:
Windows 9x: 20MB
Windows NT: 200MB
Hard disk space:
Windows 9x: 20MB
Windows NT: 200MB
Microsoft SQL Server 6.5 Not Included with
this Edition
Not Included with this Edition Windows NT (wont run
on Windows 9x)
Hard disk space:
Typical: 80MB
Full: 95MB
Microsoft SNA Server 4.0 Not Included with
this Edition
Not Included with this Edition Windows NT (wont run
on Windows 9x)
Hard disk space:
Typical: 50MB
Full: 100+MB
Table 1-4: Additional Requirements for Products Included with Visual C++ 6.0
Of the different products included with editions of Visual C++ 6.0, its important to remember that not all are included with each edition, and
that some dont work on all operating systems. As seen in the preceding table, SQL Server 6.5 and SNA Server 4.0 come with the Enterprise
edition of Visual C++ 6.0. These arent included with either the Standard edition or the Professional edition. If you want to install either of
these products, you must do so on a Windows NT system. This means that your local computer must be running Windows NT 4.0 or later, or
that youll need to install these on a separate Windows NT computer. After setting the proper permissions to install, and then access, these
products on the Windows NT machine, you would then be able to use them over the network.
On the Job: Remember that just because a product or feature comes with a package, it doesnt necessarily mean that you need to install it. If
you dont need certain features or products included with an edition of Visual C++, then youre generally better off not installing them. This
will leave you free hard disk space to install software that you do need.
Installing Visual C++ 6.0 Using Visual Studio
Once youve ensured that your computer meets the minimal requirements for installing Visual C++ 6.0, youre ready to begin the installation
process. Like many of the products available from Microsoft, a wizard is used to aid you through this procedure. A wizard is a program that
takes you step-by-step through a task, with each screen showing a step in completing that task. In the case of the setup wizard on the Visual
C++ or Visual Studio installation CD-ROM, this would be the task of installing Visual C++ 6.0.
Exam Watch: If youve been running Visual C++ 6.0 on your system for awhile, you may have forgotten or become unfamiliar with installing
this software. As this is an objective of the exam, it may be wise to either uninstall Visual C++ 6.0 from your system and then reinstall, or try
installing Visual C++ 6.0 on another computer. Although reading about how to install Visual C++ 6.0 will give you the knowledge of how the
installation process works, you should reinforce this knowledge by actually going through the steps hands-on.
The setup wizard can be started in one of two ways. When you insert your installation CD-ROM into your computers CD-ROM drive, the
wizard will start automatically. If for some reason it doesnt, or if youre installing over the network, you can start the wizard by opening the
SETUP.EXE file. From the Windows Start menu, select Run and then type the path to the SETUP.EXE file. You can also use Windows
Explorer (on Windows 9x systems) or Windows NT Explorer (on Windows NT machines) to browse your local machine or network for the
folder or CD-ROM drive containing the installation files. After you double-click this file, the setup wizard will start, and a welcome screen
will appear.
The welcome screen outlines the purpose of the wizard, and how it will walk you through the process of installing Visual Studio. On this
screen, youll also notice a View Readme button, which is used to load an HTML file into your Internet browser. HTML files are documents
used on the Internet as Web pages, and may contain graphics, and hyperlinks. By clicking on the underlined text or a graphic serving as a
hyperlink, you can view other information. This document contains the latest information on your particular version of Visual Studio or
Visual C++, inclusive to installation, known issues, and so forth. If you dont wish to read this file, simply click the Next button on this screen
of the wizard to continue with the installation.
The next screen that appears is the End User License Agreement screen, which outlines the agreement between you and Microsoft on how the
product(s) youre installing can be used. You have two options on this screen: I accept the agreement and I dont accept the agreement.
Until you accept the agreement, you cant proceed with the installation. The Next button on the screen is disabled. It appears grayed out, and
nothing will happen when you click it. If you choose not to accept the agreement, then the Back button will also be disabled, allowing you to
either choose to accept or Exit the installation. Once you accept the agreement, all the buttons become enabled, and you can continue with the
installation by clicking Next.
The screen that follows is where you prove that you have a legal copy of Visual Studio. As shown in Figure 1-1, the Product Number and
User ID screen has several fields that require input. The first of these is the products ID number, which is also referred to as a CD Key. The
number you enter here can be found on the back of your installation CD-ROMs jewel case (the case the CD-ROM came in), or in your
product documentation. The number must be entered exactly, or installation will fail. The other two fields are where you enter your name and
companys name. This will be filled out for you with information that the wizard acquires from the Windows Registry. Ensure that this
information is correct, then click Next to continue.
Cha 01:
Figure 1-1: Enter the product number, your name, and your companys name to continue with the installation
What appears next depends on whether or not you have previous versions of the products installed on your computer. If you have previous
versions of products that are included with Visual Studio (inclusive to Visual C++ 5.0, Visual Basic, and so forth), the Uninstall Visual Studio
97 screen will appear. Each of the previous versions currently installed on your system will have check boxes beside them that are selected.
This indicates that you want to uninstall the previous version, and replace it with the new version of the product. However, you are able to
have previous versions of Visual C++ running on the same machine as the new version youre installing. If you wish to keep a previous
version, simply clear the check box beside that products name. Following this, click Next to continue with the installation process. If you
dont have previous versions on your system, this screen wont appear.
The next screen that youll see offers you three choices for installing Visual Studio products. These options are:
CustomAllows you to define which products and server tools youd like to install on the workstation
ProductsAllows you install preconfigured versions of Visual C++, Visual Basic, Visual FoxPro, Visual InterDev, and Visual
SourceSafe
Server ToolsAllows you to skip over installing the workstation products of the Products option, and only install server applications
The first of these options is used if you want to install both server tools and Visual Studio products. The second option installs only the
products, while the third installs just the server tools. While well discuss each of these options individually, you should realize that you can
go back and add additional products and tools later. This is something well see in the next chapter, when we install Visual SourceSafe.
Regardless of the type of installation that you choose, the next screen will ask you to specify where files used by multiple programs in Visual
Studio should be stored. A default path is entered in the field on this screen, but you can change the path to the common folder youd like to
use by typing in a new path or clicking the Browse button. When you click the Browse button, a dialog box will appear that allows you to
browse your local hard drives and the network. This enables you to specify an existing folder in which you store common files. After selecting
a folder and clicking OK on this dialog, the new path will appear in the previously mentioned field. Regardless of how or where you want to
store these files, you should be aware that Visual Studio requires a minimum of 50MB for the common folder. You should ensure that any
local hard disk or network drive that you designate as the common folder meets this requirement. You should also keep in mind that if you
choose a network drive for the common folder, and the network goes down, that Visual C++ and other products in the Visual Studio suite
wont function properly (if at all). Although each workstation will have more free disk space if you use a common folder on a server, this
shouldnt be done if network failures are common in your organization.
If you select Product as your installation type, the next screen youll see is the one shown in Figure 1-2. This lists each of the workstation
products discussed earlier in this chapter, which you can install by selecting the check box beside the products name. If a check box is
selected, the product beside it will be installed. Otherwise, it wont be installed at this time, and if you wish to install additional products later,
youll have to re-run the setup wizard. After selecting the products you wish to install, click the Next button to continue with the installation
process.
Cha 01:
Figure 1-2: Select the products that you wish to install from the Visual Studio Individual Tools Setup screen
Whether youve chosen Products or Custom as your installation type, the screens that follow from this point on are the same. The only
difference is the order in which they appear. When you select Custom as your installation type, clicking Next brings you to a Welcome screen
for installing Visual Studio. If you choose Products, then this screen appears after clicking Next from the Individual Tools Setup screen
discussed in the previous paragraph. Clicking the Continue button on this screen moves you to the next step in installing Visual C++ 6.0.
The next screen is provides you with a product ID number. This number is made up of digits added by the setup wizard to the product
registration number (CD Key) that you entered earlier in the installation process. Its important that you write this number down, and keep it
in a safe place, as it may be requested by Microsoft if you call their technical support team for assistance. After installation, you can read this
number by clicking About under the Help menu of Visual C++ and other Visual Studio products. However, even though you can access this
number from the Help menu after installation, this will be worthless if the installation doesnt complete or if you cant open Visual C++ once
its installed. Once youve documented the product ID number, click the OK button to continue.
When you first see the Custom screen after choosing the Products installation type, you may think that youve done something wrong. This
screenshown in Figure 1-3is the same one that appears when choosing the Custom installation type. However, there is a difference in
whats selected on this screen, depending on the type of installation youve chosen. When the Custom installation type is selected, most of the
options shown in the listing at the left of this screen are selected. You can then cancel the selected products and tools by clicking a check box,
and removing the check mark. If there is no check mark, the product or tool to the right of the check box wont install. If you reach this screen
by choosing the Products installation type, then only the options for the individual tools youve selected will be selected. For example, if you
select only Visual C++ 6.0 to be installed, then the Custom screen will have the options associated with that product selected. This not only
includes Visual C++ 6.0, but ActiveX and Data Access components, various tools, and Visual SourceSafe. These are preconfigured to be
selected, as they all relate to that specific product.
Cha 01:
Figure 1-3: You can install all or part of a component using the Custom installation
On the Job: It can be confusing when the Custom screen appears after selecting the Products installation type, which sets you on the track of
doing preconfigured installations of products. Remember that the Products installation type sets up the necessary options on the Custom
screen, and in this way is different from the Custom installation type.
To the right of the Options listing, youll see two buttons. The first of these is the Change Option button. When an option is selected (as
shown by the highlight in the Options listing), the Change Option button becomes enabled. This lets you know that there are options within
this particular option that you can add or remove. Clicking Change Option opens that particular option, allowing you to view these other
options. You can almost think of it as opening a folder on your hard disk to view the files within. The second button is Select All. When this is
clicked, each of the options shown in the Options listing will be selected (i.e. their check boxes will be checked) automatically. This is useful
if there are a number of items you want to install, but dont want to click each check box individually. In other words, its a bit of a time saver
for you.
Below these buttons and the Options listing, youll see the default folder where a particular option will be installed. You can change where
each product will be installed by clicking the Change Folder button, which displays a dialog box. This dialog box allows you to type the path
to another folder on your local or network drive. You can also browse your computer or network for an existing folder. If you type the path of
a folder that doesnt exist, and click OK on the dialog box, the wizard will prompt you that the folder doesnt exist and ask if it should be
created.
The Change Folder button is often used in conjunction with the information thats displayed below it on the Custom screen. There are two
lines below this button that show the space available on a particular drive, and how much is required. If the amount required exceeds the
amount available, you should specify a new folder on a drive with adequate space. If you dont do this, when you click Next, the wizard will
check to ensure enough space is available to install, and display a screen indicating which drives dont have enough free space. This screen
will allow you to return to the Custom screen, and then pick a new folder and different drive to install to.
After using the Custom screen to select or accept options to install, clicking the Continue button will cause the setup wizard to check available
space and determine any components that are already installed. For example, if it finds a previous or current version of Visual SourceSafe on
your computer, it will prompt you to decide whether the new installation of Visual SourceSafe should replace it. The setup wizard will then
begin copying files from the installation CD-ROM to your hard disk. As Visual C++ 6.0 is an enormous program, and there are a number of
other tools and components to install, this may take a few minutes to complete. It will then proceed to modify system settings and
environment variables necessary to run Visual C++ 6.0 and the other options selected earlier. When this is finished, youll be prompted to
restart your computer.
Installing the MSDN Library and InstallShield
The Microsoft Developer Network (MSDN) Library is a collection of documentation and samples for the Visual Studio suite of products. If
youre installing from Visual Studio, MSDN is included. Although this was the most recent version of MSDN when Visual Studio was
released, you can also order a subscription to MSDN through Microsofts Web site (msdn.microsoft.com). You can install MSDN by
double-clicking the SETUP.EXE file on the MSDN CD-ROM. You can also install MSDN after going through the previously mentioned steps
of installing Visual Studio.
After the computer has restarted and reloaded Windows, a screen will automatically appear and offer you the chance to install the MSDN
Cha 01:
Library. To install MSDN, ensure that the Install MSDN check box on this screen is checked, insert the MSDN CD-ROM and then click Next.
A welcome screen will appear for installing MSDN on your hard disk. Clicking Continue will show the screen we saw earlier, which
displayed the product ID. Although it appears to be identical, this is a different product ID number. For reasons discussed earlier, you should
write this number down before clicking OK to continue.
A dialog box will appear with two buttons used to show your agreement to using the MSDN library. Clicking I decline will cancel
installation of MSDN. Clicking I agree will allow you to proceed with installation of the MSDN Library.
This will bring you to the screen shown in Figure 1-4, where you select the type of installation preferred for MSDN. There are three different
types of installation, which are:
TypicalInstalls commonly used components of MSDN
CustomAllows you to install only the components that you select
FullInstalls the entire MSDN Library to your hard disk
In most cases, Typical installation is what youd choose. This installation takes up a maximum of 60MB of hard disk space, as opposed to the
800MB used by Full installation. As you choose only the components that you want installed with Custom, the amount of disk space required
depends on the components youve decided to install. If you have significant disk space available, it may be worthwhile to perform a full
install of MSDN. This will provide you with better search capabilities when using the library.
Figure 1-4: Choose the type of installation that you want for the MSDN Library
After clicking Typical or Full, the setup wizard will check the hard disk where MSDN will be installed to ensure there is enough hard disk
space. It will then begin copying the necessary files onto your hard disk, until finally displaying a message box that informs you whether the
installation succeeded or failed.
If you decide to perform a Custom installation of MSDN, the next screen you see will be a listing of documentation and samples that can be
installed onto your hard disk. This includes information on Visual C++ 6.0, as well as items related to other products in the Visual Studio
suite. Its advisable that you install items related to the programs youre using, as these will provide you with important information and
online assistance. Once youve selected the items to install, clicking Next will begin the transfer of files from the CD-ROM to your hard disk.
A message box will then display whether the installation succeeded or failed, and indicate the end of this portion of the installation process.
Once youve installed MSDN, youre ready for the final step in the installation process. This is deciding whether to install InstallShield. As
we saw earlier in this chapter, InstallShield is a program used when setting up installation packages for programs created with Visual C++ 6.0.
It appears in a Client Tools listing on the Other Client Tools screen that appears next. By selecting InstallShield from this listing, the Install
button on this screen then becomes enabled. You can click this button, and InstallShield will be begin its own installation process on your
computer.
A welcome screen will appear for the InstallShield installation wizard, and by clicking Next youre brought to the InstallShield Software
License Agreement screen. By clicking the Yes button on this screen, you can proceed with the installation. Otherwise, your only other
choices are to click Back to move to the previous screen, or No to cancel the installation.
The following screen will display your name and company name, which is filled in already from information in the Windows Registry. Ensure
Cha 01:
that this information is correct, as you wont be able to change it later. Following this, click Next to continue.
The Choose Destination Location screen allows you to specify where InstallShield will be installed. You can either accept the default
installation folder, or click Browse to open a new dialog box. This dialog box enables you to specify a different directory to install to. As with
the Browse dialog box we saw earlier, you can type a path where InstallShield will be installed, or use the dialog box to browse your local
computer or network drive. If you type a path to a folder that doesnt exist, youll be prompted as to whether the wizard should create this
directory.
Click Next from the Choose Destination Location screen and you will then be asked to specify how InstallShield should be installed. There
are three setup types to choose from:
TypicalInstalls the most commonly used options. This is the option used by most users of InstallShield
CompactInstalls the minimal options for using InstallShield. This should be used if you have limited disk space
CustomEnables you to specify which options youd like to install
Selecting either Typical or Compact will take you to a screen informing you that youre ready to begin installing, and tells you what the
Installation Wizard will do next. Well discuss this in the paragraphs that follow. Clicking Next will begin copying the necessary files to your
hard disk. However, if you select Custom, you will have a few more choices to make.
Exam Watch: Although most installations will involve choosing the Typical installation type, you should be aware of what can be installed on
your system. This can be seen through the Custom installation, which can show you the individual components available to install.
Clicking Custom from the Setup Type screen brings up a new screen where you can choose which options will be installed on your computer.
There are three options on this screen:
Program FilesThe application files necessary to use InstallShield
Help FilesDocumentation files that provide online assistance
TemplatesSamples that can be used with InstallShield
A check box appears before each of these options, and clearing a check box will mean that that particular option wont be installed. If a check
box is selected, then that option will be installed.
Clicking Next brings up the previously mentioned screen that informs you that installation is ready to begin, and tells you what will take place
next. This screen informs you that a shortcut to InstallShield will be added to the Start menu, and that it will also be accessible from the Tools
menu of Visual C++. Clicking Next will begin installation of files from the installation CD-ROM, based on the options you choose earlier.
The final screen in the installation process includes an option to view a README file associated with InstallShield. To view this file, leave
the check box selected. Otherwise, click the check box to clear the check mark. Click Finish.
Server Tools
Once installation of InstallShield has completed, the installation process shifts from client tools to server tools. It is here that you can select
individual server tools from a listing of server components. This is the same screenshown in Figure 1-5that appears if you selected Server
Tools as the installation type mentioned early in the installation process. Once youve selected a component from the Server Components
listing (by clicking the name of the component to install), the Install button becomes enabled. Clicking the Install button invokes an
installation wizard for the component selected.
Figure 1-5: Choose the server tools to install from the Server Setups screen
If youre installing these server tools on Windows NT, Microsoft recommends that all of the tools be installed. Each of these tools can be used
Cha 01:
for developing applications with Visual C++ 6.0. If youre installing these programs on a Windows NT system, then the order in which you
install these products is up to you.
This is a little different from installing the server tools on a Windows 9x system. Windows 95 and Windows 98 require some of these server
applications to be installed before others, if your installation is to succeed. The order is as follows:
1. NT Option Pack (for Windows 9x)
2. FrontPage 98 Server Extensions
3. Data Access Components 2.0
4. Visual InterDev Server Components
5. Application Performance Explorer
6. Visual Studio Analyzer
The remaining two components, Visual SourceSafe Server and Visual FoxPro Server Samples, can be installed in any order. This is because
they dont rely on any of the other components to be installed beforehand.
Exam Watch: An easy way to remember the order in which server tools should be installed on a Windows 9x system is with the following
sentence: On Fun Days, I Am Awesome. The first letter of each word represents one of the tools: Option pack, FrontPage extensions, Data
access, InterDev components, Application performance explorer, and (Visual Studio) Analyzer. At the very least, this will help you remember
the order until you get into the exam, and can jot it down on paper.
Once youve installed the individual server tools, by following the on-screen instructions of each individual setup wizard, you can then click
the Next button and go to the final screen of the installation process. A check box appears on this screen indicating whether you would next
like to register Visual Studio online. If you have a modem and Internet access, clicking the Finish button will take you to a Web site where
you can register Visual Studio. If you dont have these requirements, then click the check box to clear the check mark. Finally, click Finish to
complete the installation.
Exercise 1-1 Installing Visual C++ Development Tools
1. Insert your Visual Studio installation CD-ROM into your CD-ROM drive. The setup wizard should start immediately. If it doesnt
appear after a minute or more, open Windows Explorer (or NT Explorer if youre using Windows NT), and select your CD-ROM drive to
browse. Double-click on the SETUP.EXE file in the root directory.
2. When the welcome screen appears, click the Next button.
3. The End User License Agreement screen will appear next. Select the I accept the agreement option, if you wish to continue with the
setup. Click Next.
4. When the Product Number and User ID screen appears, enter your product ID number (CD Key). Ensure that your name and companys
name is correct, then click Next.
5. If you have previous versions of Visual C++ or other Visual Studio products installed on your computer, a screen will appear asking if
you want these previous versions removed and replaced with new versions that youre installing. If you clear the check boxes beside the
products that you wish to keep, those products wont be uninstalled. Click Next to continue.
6. Select the Products option, then click Next.
7. The screen that appears asks you to specify a folder that will be used for files commonly used by multiple products. Accept the path
entered in the field provided, or enter the path to where youd like common files to be stored. Click Next.
8. When the installation welcome screen appears, click Continue.
9. Write down the product ID number on a piece of paper, and keep it in a safe place for future use. Click OK to continue.
10. The next screen that will appear is the Custom screen. Here you can specify which products and tools will be installed. Click the Visual
SourceSafe check box to clear the check mark. We will be installing Visual SourceSafe in the next chapter. Accept the remaining
preconfigured options selected in the listing, and click the Continue button.
11. After the setup wizard finishes copying files and making modifications to your system settings, youll be prompted to restart the
computer. Click the Restart Computer button on this message box to continue.
12. When your computer restarts and reloads Windows, a new screen will appear asking if you want to install MSDN. Insert the MSDN
CD-ROM into your CD-ROM drive. Ensure that the Install MSDN check box is selected, and then click Next.
13. When the MSDN welcome screen appears, click Continue.
14. Another product ID screen will appear, displaying the product ID number for MSDN. Document this number, then click OK.
15. When the End User License Agreement for MSDN appears, click the button labeled I agree to continue with the installation.
16. When the MSDN Installation screen appears, click Typical. MSDN will then proceed installing its files onto your hard disk. When it has
finished this, click OK on the message box that appears, telling you whether your installation was successful or not.
17. Select InstallShield from the listing of Client Tools shown on the Other Client Tools screen that appears, then click the Install button.
18. When the InstallShield welcome screen appears, click Next.
19. To continue with the installation process of InstallShield, click the Yes button on the InstallShield Software License Agreement screen
that appears.
20. Accept the default folder where InstallShield will be installed, or click Browse to specify a new target directory. Click Next to continue.
21. Click Typical to install InstallShield with the most commonly used features.
22. Click Next to begin the installation. Files will then begin to be transferred to your hard disk, and InstallShield will be installed.
Cha 01:
23. When the files have been copied to your hard disk, a final screen for this portion of the installation will appear. If you wish to read the
README file associated with InstallShield, leave the check box selected that is beside Yes, I want to view the Readme file. Otherwise,
click the check box beside this option to clear the check mark. Click Finish to complete the InstallShields installation.
24. From the Server Setups screen, select the components you wish to install. If youre installing onto a Windows NT computer, install each
of these components (as Microsoft recommends). If youre installing onto a Windows 9x computer, install the server tools in the order given
in the Server Tools section of this chapter. Follow the on-screen instructions for any server tools installed, then click Next from the Server
Setups screen to continue.
25. The final screen of the installation process appears. This screen has a check box to indicate whether you would like to register Visual
Studio online. If you have a modem and Internet access, clicking the Finish button will connect you to a Web site. If you dont have a modem
and Internet access, click the check box to clear the check mark. Click Finish to complete the installation.
Service Packs
As mentioned earlier, service packs can be installed to resolve issues associated with a particular product. These issues may be legal (as was
the case with Visual J++), bug fixes, or other problems that werent realized or couldnt be fixed when the product was initially released. After
software has been installed, you can install the service pack. This will install updated files that deal with those problems.
Exam Watch: Dont expect to see much, if anything, regarding the service packs on your exam. The vast majority of questions that could
appear on your exam were written before the service packs became available. Despite this, you should be aware of service packs, and install
them to avoid problems that could result after installation. The reason the service packs exist are to upgrade problematic files
In the case of Visual Studios Service Pack 3, numerous issues are dealt with. One in particular is a bug in Visual C++ that can cause memory
problems and crash third-party software. This bug appears in all editions of Visual C++ and Visual Studio. To deal with this problem, Service
Pack 3 replaces a file associated with the heap manager (MSVCRT.DLL). Other upgraded files dealing with Visual C++ and other products
are also included in the service pack.
Because the service pack upgrades files on your system that may be used by applications you create with Visual C++, its important to install
the service pack as soon as possible. This will ensure that any programs you create with Visual C++ 6.0 will have the latest files included with
them, and keep users of your applications from encountering problems. As well see later in this book, such files may be included with
applications you create and distribute.
Although there are three Visual Studio service packs at the time of this writing (that is Service Pack 1, Service Pack 2, and Service Pack 3),
you dont need to install all of them. Not only does Service Pack 3 resolve all of the issues taken care of in Service Pack 1 and 2, but it
addresses additional problems that were solved after the initial release of Visual Studio and the first two service packs. As they deal with
known issues that have been resolved since your installation CD-ROMs release onto the market, you wont find the service pack on this
CD-ROM. You need to obtain it from Microsoft. This can be done by contacting them directly, or by visiting the Visual Studio Web site at
msdn.microsoft.com. As well see in the exercise that follows, it is from here that youll be able to download the latest service pack.
When installing Service Pack 3, you should first shut down any Visual Studio products youre using. If, for example, Visual C++ were open,
problems could arise when the service pack overwrites files associated with that program. Once the service pack has finished installing, you
can then restart any of the Visual Studio products you were using.
Unfortunately, because the service pack overwrites files associated with Visual Studio products, there is no way to uninstall just the service
pack. If there was, files would then be missing for products in the Visual Studio suite, and those products would be unable to function
properly. As such, you would need to uninstall the actual product to get rid of the changes made by the service pack. For example, to get rid of
the MSVCRT.DLL upgrade for Visual C++, you would need to uninstall Visual C++. Upon reinstalling Visual C++, any changes made by the
service pack for Visual C++ would be gone.
Exercise 1-2 Obtaining and Installing the Visual C++ Studio Service Pack
1. Open Microsoft Internet Explorer by double-clicking the shortcut on your desktop. After connecting to the Internet, type the URL
http://msdn.microsoft.com/vstudio/sp/default.asp in the address bar. If you have trouble connecting, go to the MSDN Web site
(http://msdn.microsoft.com), then click the link on this page for the latest service pack.
2. Click the hyperlink for the Full install of the service pack.
3. Click each link for a service pack file from one download site. For example, at the time of this writing, the latest service pack is Service
Pack 3. This means you would download each of the following from one location: VS6SP3_1.EXE, VS6SP3_2.EXE, VS6SP3_3.EXE, and
VS6SP3_4.EXE. For each files hyperlink that you click, select Save this program to disk when prompted to download the software, then
click OK. Following this, select a directory on your hard disk to which you will download the files.
4. After download has completed, run each of the files you downloaded. This can be done by either entering the path and filename of each
downloaded file, or by using Windows Explorer. You can start Windows Explorer (or NT Explorer if youre using a Windows NT system)
from the Programs folder of the Start menu. Use the browser to go to the directory in which you saved these files, and double-click each of the
downloaded files. The contents of each of these files will expand upon being opened.
5. Run the SETUP.EXE program that has been expanded from the downloaded files.
6. When the End User License Agreement screen appears, click I Accept to install the service pack.
From the Classroom
VC++ just keeps getting better!
For the Visual C++ developer seeking to obtain the C-enriched track of the new Microsoft Certified Solution Developer (MCSD) credential,
the process will most likely begin with Exam 70-016, Designing and Implementing Desktop Applications with Microsoft Visual C++ 6.0.
Don't be fooled by the desktop spin, this exam will cover many general aspects of C++ coding and will require a definite comfort level with
the Visual C++ 6.0 environment. Although this may seem basic, it is absolutely recommended that trivial issues such as familiarity with the
integrated development environment (IDE) be eliminated in the beginning, prior to focusing on the technical specifics of the coding, the
syntax, and the tool usage. Once IDE familiarity is obtained, you can focus on the more complex utilities such as the Source Code Profiler,
Cha 01:
Visual Database tools, or the Component and Object Gallery.
The process should begin with selecting the appropriate version of Visual C++ 6.0 (Standard, Professional, or Enterprise). After installing it
on your machine, it is time to make yourself at home in the Visual C++ IDE. There are many options available that allow the developer to
customize the user interface for Visual C++. One easy way that you can become more comfortable with the development environment is to
change the appearance and placement of toolbars to meet your personal tastes.
Toolbars in Visual C++ contain buttons and menus that give you access to the wide array of commands that you will use to build and deploy
your applications. Microsoft has gone to great lengths to provide a uniform look and feel to all of the members of the Visual Studio suite of
development tools. Factors that influence how you arrange toolbars include screen size, what commands you most commonly utilize, as well
as personal preferences. To make a toolbar docked or floating, just right-click the toolbar and toggle the docked property. While the toolbar is
floating, make note of its name in the title bar. You can use this name to display or suppress the toolbar by selecting it or canceling its
selection from the pop-up menu that appears when you right-click any toolbar. The Customize menu option provides a convenient way to turn
a number of toolbars on and off at the same time. After selecting Customize from the toolbar pop-up menu, select the Toolbars tab of the
dialog box that is displayed; here you can select or cancel the selection of as many toolbars as you like. Sometimes when you are dragging
toolbars around, they will unexpectedly dock as you drag over certain areas. To avoid this behavior, just hold down the ctrl key while you
drag the toolbar to its desired location.
There are numerous ways to customize the Visual C++ environment. Other examples include creating custom-highlighted keywords,
customizing the debugging interface, assigning commands to shortcut keys, and customizing the text editor by emulating another editor. After
getting acquainted with the basic features of Visual C++, you should spend a little time modifying the user interface to suit your specific
development needs and style. Customizing the user interface will lead to a greater level of comfort and a better understanding of the Visual
C++ environment.
Michael Lane Thomas, MCSE+I, MCSD, MCT, MCP+SB, MSS, A+
Certification Summary
Visual C++ 6.0 can be acquired on its own or as part of the Visual Studio suite of products. Visual Studio not only includes Visual C++, but
also Visual Basic, Visual J++, Visual InterDev, Visual FoxPro, and various tools helpful in creating robust applications rapidly. On its own or
as part of Visual Studio, different editions are available. Visual Studio is available in Professional and Enterprise editions, while Visual C++ is
available in Standard, Professional, and Enterprise editions.
Before attempting to install Visual C++ 6.0 (or any other software for that matter) onto your computer, you should ensure that the minimum
system requirements are met. These are the bare minimumin terms of RAM, processor, disk space, and so forththat your computer will
need to install and run Visual C++ 6.0. These may vary from edition to edition of Visual C++ 6.0. If your system meets these requirements,
then you can be sure that no problems will result from unsatisfied requirements. If these arent met, Visual C++ 6.0 may not install and run
properly.
Installing Visual C++ through Visual Studio is a multipart process. It starts by starting the setup wizard, which gathers information about your
computer and asks for input from the installer. It is highly interactive, enabling you to choose the type of installation you wish to do, the
products to install, and where to install them. It then moves into installing the MSDN Library and InstallShield, and allows you to install
various server tools.
Once installation is complete, you should check the MSDN Visual Studio Web site to obtain and install the service pack. This will upgrade
your installation with files that resolve known issues about Visual Studio products, inclusive to Visual C++ 6.0. By not installing the service
pack, you may encounter bugs or problems, and wont be redistributing the latest files with applications that you create.
Two-Minute Drill
Visual C++ 6.0 can be purchased by itself, or as part of the Visual Studio suite of products.
Visual Studio not only includes Visual C++, but also Visual Basic, Visual J++, Visual InterDev, Visual FoxPro, and various tools
helpful in creating robust applications rapidly.
Visual C++ 6.0 is also available in three different editions: Standard, Professional, and Enterprise
Knowing the individual components of Visual Studio or Visual C++ is not a direct objective of the exam. However, knowing this
information can be useful in understanding whats being asked in a question.
Although its cheaper to purchase Visual C++ 6.0 on its own, Visual Studio comes with significantly more development tools.
Visual Studio is a suite of products used for developing and managing applications, components, and data access. It provides you with a
wider scope of options than Visual C++ alone, because it contains more than just Visual C++ 6.0.
As part of Visual Studio, or on its own, Visual C++ 6.0 includes a number of features that can be used for creating desktop and
distributed applications
Visual C++ 6.0 supports the Component Object Model (COM). This is an object model that enables various software
componentsapplications, controls, data objects, services, and so forthto interact as objects. These objects contain data, and provide a
method through which other components can access that data.
Visual C++ 6.0 includes a large number of prebuilt, ready to use ActiveX controls. New to Visual C++ 6.0 are composite controls. These
are new controls that you can create by combining your existing ActiveX and Windows controls.
Although minimum installation requirements arent a specific objective of the exam, it is an important part of installing Visual C++ 6.0
Development Tools, which subsequently is an objective. Many installation problems are due to the fact that the system fails to meet the
minimal requirements of the software youre attempting to install.
Before taking the exam, make sure you understand the minimal requirements for each edition of Visual C++ 6.0, on both Windows 9x
and Windows NT. This will help you analyze problems being discussed in exam questions, and determine why a certain installation is failing.
For each edition of Visual C++, the operating system requirements are the same. You need to be running Microsoft Windows 9x or
Windows NT version 4.0 or higher. However, if youre using Windows NT, youll need to install Service Pack 3 (SP3), which is included on
the Visual C++ installation CD-ROM.
Cha 01:
Remember that just because a product or feature comes with a package, it doesnt necessarily mean that you need to install it. If you
dont need certain features or products included with an edition of Visual C++, then youre generally better off not installing them. This will
leave you free hard disk space to install software that you do need.
Although reading about how to install Visual C++ 6.0 will give you the knowledge of how the installation process works, you should
reinforce this knowledge by actually going through the steps hands-on.
It can be confusing when the Custom screen appears after selecting the Products installation type, which sets you on the track of doing
preconfigured installations of products. Remember that the Products installation type sets up the necessary options on the Custom screen, and
in this way is different from the Custom installation type.
The Microsoft Developer Network (MSDN) Library is a collection of documentation and samples for the Visual Studio suite of
products. If youre installing from Visual Studio, MSDN is included.
Although most installations will involve choosing the Typical installation type, you should be aware of what can be installed on your
system. This can be seen through the Custom installation, which can show you the individual components available to install.
Once installation of InstallShield has completed, the installation process shifts from client tools to server tools. It is here that you can
select individual server tools from a listing of server components.
An easy way to remember the order in which server tools should be installed on a Windows 9x system is with the following sentence:
On Fun Days, I Am Awesome. The first letter of each word represents one of the tools: Option pack, FrontPage extensions, Data access,
InterDev components, Application performance explorer, and (Visual Studio) Analyzer.
Service packs can be installed to resolve issues associated with a particular product. These issues may be legal (as was the case with
Visual J++), bug fixes, or other problems that werent realized or couldnt be fixed when the product was initially released.
Dont expect to see much, if anything, regarding the service packs on your exam. The vast majority of questions that could appear on
your exam were written before the service packs became available. Despite this, you should be aware of service packs, and install them to
avoid problems that could result after installation.
Not only does Service Pack 3 resolve all of the issues taken care of in Service Pack 1 and 2, but it addresses additional problems that
were solved after the initial release of Visual Studio and the first two service packs.
By not installing the service pack, you may encounter bugs or problems, and wont be redistributing the latest files with applications that
you create.
After getting acquainted with the basic features of Visual C++, you should spend a little time modifying the user interface to suit your
specific development needs and style.
Cha 01:
Chapter 2: The Development Environment
Certification Objectives. 1
Visual SourceSafe Installations. 6
Configuring Visual SourceSafe. 17
Using Visual SourceSafe. 27
Multiple User/Multiple Location Development 33
Versioning of the Source Code. 34
From the Classroom.. 46
Certification Summary. 48
Two-Minute Drill 50
Certification Objectives
Source Code Control
Using Microsoft Visual SourceSafe
MFC Wizards
Resource Editors
Using the Gallery
Information Resources
In this chapter well discuss a number of issues relating to the development environment. Specifically, well talk about using source code
control in Visual C++ 6.0, and how you can use Microsoft Visual SourceSafe (VSS) to keep your source code safe and accessible. Well also
talk about using resource editors and wizards to create and manipulate source code created with Visual C++ 6.0.
Visual C++ 6.0 comes with a number of elements that aid you in creating robust applications. In addition to wizardswhich take you
step-by-step through the process of tasks like creating specific files for your applicationswell talk about the Gallery and information
resources available through Visual C++. The Gallery contains prepackaged components and registered ActiveX controls that can be added to
your projects. A project is a collection of files that make up your application. Information resources aid you in finding answers to problems
quickly and efficiently.
Source Code Control
Controlling source code is an issue regardless of whether youre programming by yourself, or with a team of programmers. Source code is the
programming code you write, which makes your program actually do things (that is, make calculations, open and close files, display data, and
various other operations). As you or others make changes to source code, there may be times when youll need to track those changes. You or
another programmer may modify the code, only to find that these changes adversely effect your application. You may want to refer to a
previous version of your application to see how it was originally written, or to see if you should revert to previously used code. Tracking
changes to source code during software development enables you to see what work has been done and who has done it. Tracking changes
helps you analyze how those changes have affected the project as a whole. Although there are many reasons why you may wish to do this,
source code control is required for you to track changes and restore previous versions of code.
On the Job: Some people may get the wrong idea about the benefits of VSSs ability to track changes, and may think it akin to Big Brother
watching. The fact is that if youre modifying code that someone else has worked on, you may have questions. Through this feature in source
code control, youll be able to find who last worked on it to get the answers you need. This will keep you from adversely changing aspects of
code, thinking its no longer needed. If youre working on a component that works with others in a project, youll be able to find who last
worked on a particular component and consult them. This is particularly beneficial on large projects, where there may be a number of
developers working on a single project.
To facilitate source code control, Visual C++ 6.0 uses the Microsoft Source Code Control Interface. This interface provides a method for
source code control systems such as Visual SourceSafe (which well discuss later in this chapter) to integrate with the Visual C++
environment. This means that although the source code control system is a separate application, you can access aspects of its functionality.
Through menu items in Visual C++ 6.0, youre able to invoke operations performed by the control system. This includes saving your projects
and source code files to the control system (such as a Visual SourceSafe database), removing them, examining their history, determining the
status, and so on.
After installing Visual C++ 6.0, you may have looked for commands or dialog boxes dealing with source code control. If you did, you may
have been surprised to see that nothing was there. This is because the commands associated with source code control dont appear until a
source code control system is installed. As Figure 2-1 shows, these menu items only appear after the control system is installed. In addition,
the installed control system must conform to the Microsoft Common Source Code Control Interface. If the control system is installed and it
has been designed to conform to this interface, a number of menu commands will appear, as will a new tab in the Options dialog box. If it
doesnt conform, then the menu items and the tab in the Options dialog box wont appear at all, and it will seem as if no control system has
ever been installed.
New Page 6
Figure 1: Source code control commands appear in the menus after the control system is installed
As well see when we discuss Visual SourceSafe, the menu items and the Options dialog box in Visual C++ 6.0 dont provide complete
control over the source code control system. Each and every feature provided by the source code control system isnt available through the
menu items in Visual C++ 6.0. Certain administrative tasks are done through the source code control systems administrative program. In
addition, there are some tasks that need to be done with tools associated with your operating system. An example of this is assigning
permissions for drives and directories. On a Windows NT Server, this is done through User Manager for Domains. Such permissions prevent
developers from accessing directories or drives containing code that doesnt apply to their individual projects. This gives you an additional
level of control, beyond the functionality of whats included in Visual C++ 6.0 with source code control installed. By designating one or more
people to administer source code control for other developers on your team, you can keep them from having the access to do more than they
should.
Using Microsoft Visual SourceSafe
Visual SourceSafe (VSS) is a source code control system, which allows developers to save copies of their source code to a database. When a
file is added to VSS, that file is stored in the VSS database. The database supports many different file types, including binary files, graphics,
text files, audio, and video. If the original file becomes corrupt, or modifications that dont work are made to the source code, it doesnt
necessarily mean that your previous, functional source code is lost. You can use VSS to restore old versions of files by retrieving them from
the database. You can also view information on each version that is stored in the database. This gives developers the ability to track any
changes made to their source code files.
As with any software, the first step toward using Visual SourceSafe 6.0 is installing it. The Visual Studio installation CD-ROM comes with
two setup options for VSS:
Visual SourceSafe Client installation
Visual SourceSafe Server installation
In installing these, you may think that the client and server installations of VSS are identical. As well see, they are not. For development
teams to use and get the full benefits of VSS, both of these installations must be performed.
The VSS Client installation is done on machines where users wish to save their source code to the database. Because it is a Microsoft product,
VSS conforms to the Microsoft Source Code Control Interface. This means that when the VSS Client is installed, the commands dealing with
source code control will be added to the Visual C++ 6.0 environment, as will a new tab under Visual C++ 6.0s Options dialog box. It is
through these that youll be able to interact with VSS. Any workstation that will use the VSS database will need to have this client portion
installed.
The client installation can be installed at the same time you install Visual C++ 6.0. In referring back to the installation of Visual C++ 6.0 in
Chapter 1, youll remember that this appears on the Custom screen during setup, and is available for installation by selecting Visual
SourceSafe 6.0 during the Products installation type. When this is selected (by clicking to check the check box beside this entry), the VSS
client installation will be performed. As well see later in this chapter, you can also install VSS after Visual C++ 6.0 has been installed.
The Visual SourceSafe server installation is used to install a source code control database that stores versions of source code. It also installs an
administration application that will enable you to control who can access the source code files stored in the database and control who can
perform administration tasks.
The client portion works with the server portion of VSS. Through the client portion of VSS, developers can save and retrieve their source code
from this database. As all members of the development team can use this database, the server installation only needs to be performed once on
a network. The client portion, however, needs to be installed on each and every computer that will access this database. This includes the
server itself if it will be used for development work. Despite the fact that you have the server portion installed on a server machine, youll still
need to install the client portion on that machine if youre going to develop applications on that machine. Remember that the client portion is
used for all developers accessing the source code control database, whereas the Server portion provides a centralized database and
administration. To use VSS on the computer thats acting as the VSS server, youll also need the VSS client installed.
Like the client portion, you can install the VSS server when Visual C++ 6.0 is installed through Visual Studio. If Visual C++ 6.0 has already
been installed, you can still install VSS Server. In both cases, this is done through the Server Setups screen of the Visual Studio installation.
As well see later in this chapter, when you select Visual SourceSafe Server from the listing of available client tools on this screen, a new
wizard will start that directs you through the installation process.
New Page 6
Visual SourceSafe Installations
As mentioned, there are two installations that are performed when installing VSS. Unlike some other development systems, however, you can
perform these installations either before or after installing Visual C++ 6.0. Regardless of the order, source code control features will be
integrated with the Visual C++ 6.0 development environment. This is different from Visual Basic, for example, where the development
system needs to be installed before VSS.
Installing Visual SourceSafe is a two-part process. The first step is installing the VSS server, which will provide developers with a centralized,
source code control database. This is generally installed by the person who is the designated VSS administrator, and who will be responsible
for the administration tasks well discuss later in this chapter. The second part of the process is installing the client portion on each
workstation that will access this database. As well see later in this section, the administrator or individual users may be responsible for
installing the VSS client software.
Regardless of whether you perform a client or server setup of VSS, new folders will be added to your hard disk during the installation. Many
of these folders and the files contained within them are similar for each installation. As well see in the paragraphs that follow, you are given
an opportunity during the installation to choose the name and location of the folder that VSS will install to. However, the subdirectories within
this directory will vary, depending on whether a server or client installation is chosen.
On the Job: Its important that you understand what resides in each of the folders created by VSS during installation. This will allow you to
quickly find applications and files needed when administrating VSS.
Only the \Win32 and \Setup folders are installed during the client installation. The \Setup folder contains installation files, which can be used
to install additional components or uninstall VSS. The \Win32 folder contains Administration and other 32-bit Intel programs that can be used
on Windows 9x or Windows NT machines. Well discuss these applications in greater detail later in this chapter.
The server installation installs a large number of folders and files. These include a User folder that stores initialization files for various VSS
users, a \Data folder for the database, a Temp folder used to store temporary files, and an \NetSetup folder for the NetSetup installation
discussed in this section. A Template folder will also be installed containing templates of initialization files used by VSS. In addition, folders
installed in the client installation are also added. These include \Setup and \Win32. The \Setup folder contains installation files, which can be
used to install additional components or uninstall VSS. The \Win32 folder contains Administration and other 32-bit Intel programs that can be
used on Windows 9x or Windows NT machines.
Exam Watch: Remember that of the folders created in client and server installations of VSS, the \Win32 and \Setup folders are common to
each. The \Win32 directory contains tools needed to use VSS effectively, while \Setup is used for installing additional components or
removing VSS from a system.
Visual SourceSafe Server is installed through the Visual Studio installation CD-ROM, which we used in the previous chapter. To start the
Installation Wizard, you must insert your installation CD-ROM into your CD-ROM drive, and then use Windows Explorer to double-click the
SETUP.EXE file on this CD-ROM. Although this is the same procedure used in Chapter 1 to start the Installation Wizard, the first screen that
appears will be different. As Figure 2-2 shows, the first screen explains that the wizard recognizes that other Visual Studio products have been
installed. It also gives several options of installation types.
Figure 2: The Installation Wizard recognizes that other Visual Studio products have been installed
The Workstation tools and components option is chosen when you want to install additional products that come with Visual Studio. This not
only includes Visual C++ 6.0 and other development systems, butas well see later in this sectionit is also the option chosen when
performing a Visual SourceSafe Client installation. In addition to products, you can also select the Other Microsoft tools option to install
InstallShield, or MSDN to install the Microsoft Developer Network Library.
The Server applications and tools (add-only) option is selected when you wish to install various server applications. When installing VSS
Server, you select this option and then click the Next button. This will take you to the Server setups screen, where you will begin installing
VSS Server.
New Page 6
The Server setups screen provides a listing of server applications to install. Although theyre called server applications, this doesnt
necessarily mean that you cant install them on a workstation. The Visual SourceSafe Server can be installed on any Windows 9x or Windows
NT machine. Once installed, other workstations on the network can access the source code database available through this installation.
Select Visual SourceSafe Server from this screen, then click the Install button. This starts the VSS Server Installation Wizard. Youll be asked
to switch the current CD-ROM inserted in your CD-ROM drive with the second installation disk. Clicking the OK button on this prompt will
begin the installation process, and display a welcome screen.
Clicking the Continue button on the welcome screen will cause a second screen to appear. This screen displays a product ID number. You
should document this number, as it may be requested if you contact Microsoft for assistance. After installing VSS Server, youll be able to
access this number from the dialog that appears upon clicking About Administrator from the Help menu of the Visual SourceSafe Admin tool.
Well discuss the Admin tool later in this chapter, but its important that you document this product ID number during the installation. If the
Admin tool doesnt run, this will be your only chance to document it. Once youve written this number down, click the OK button to continue.
At this point, a small dialog box will appear. This is your last chance to back out of installing VSS Server by clicking Cancel. By clicking the
button labeled Server on this dialog, youre indicating that you want to install VSS Server to your computer.
When you click Server, a small message box will appear. This box asks whether all clients will be using this database with version 6.0 of the
client software. This is the client portion of VSS that comes with Visual Studio 6.0 and Visual C++ 6.0. If they are, you click the Yes button
on this message box, and a database compatible with version 6.0 will be used. If some users will be using previous versions of the VSS client,
click the No button. This indicates that version 5.0 client software will be used. This may decrease the performance of VSS Server, as the
database and components for version 6.0 client software is faster. If this is the first time youll be using Visual SourceSafe with development
systems, then you should click Yes, as well be installing the client software next.
Once youve answered the yes or no question of this screen, the wizard will begin transferring files to your computer. It will also make the
necessary changes to your system settings, and add entries related to VSS Server to your Windows Registry. When this is complete, a small
message box will appear stating whether the installation was successful or not. After clicking OK on this message box, you should be ready to
begin installing client software and configuring Visual SourceSafe.
Exercise 2-1 Installing Visual SourceSafe Server
1. Insert your Visual Studio installation CD-ROM into your CD-ROM drive. Using Windows Explorer, double-click the SETUP.EXE file
on this CD-ROM.
2. Select the Server applications and tools (add only) option, then click Next.
3. From the listing of Server components appearing on the Server setups screen, select Visual SourceSafe Server. Click the Install button
4. When prompted, insert the second Visual Studio installation CD-ROM, then click OK.
5. When the Visual SourceSafe Server welcome screen appears, click the Continue button.
6. When the Visual Source Safe Server setup screen appears, showing a product ID number, document the product ID number, then click
OK.
7. Click the Server button that appears on the screen that follows.
8. Click the Yes button if everyone using this VSS database will be using version 6.0 client software. If you have previous versions of
Visual C++ installed that use version 5.0 client software, click No.
9. The wizard will then begin transferring files. When it has completed, click OK. When prompted to restart Windows, click Yes.
10. You will return to the Server setups screen. Click Finish to complete the installation process.
After Visual Studio has been installed, you can still perform a Visual SourceSafe Client installation by using the Visual Studio Installation
Wizard. In doing so, Visual C++ 6.0 and other development systems previously installed through Visual Studio will become integrated with
the source code control system. As stated previously, this means that youll be able to access the source code control database of VSS through
commands in Visual C++ 6.0.
There are three ways of starting the VSS Client installation after Visual Studio and Visual SourceSafe Server have been installed. These are as
follows:
Using the Add/Remove Programs applet in the Windows Control Panel
Starting SETUP.EXE from the Visual Studio installation CD-ROM
Using the NetSetup program thats located in the folder that you installed from Visual SourceSafe Server
In the paragraphs that follow, well discuss each of these methods. This will provide you with clear insight of how each of the client
installations can be performed.
As we saw when installing Visual SourceSafe Server, you can start installing Visual SourceSafe Client by inserting your Visual Studio
CD-ROM into the CD-ROM drive, and running the SETUP.EXE program. This displays a screen with various installation options, which was
shown earlier in Figure 2-2. By clicking the Workstation tools and components option and clicking Next, youll be brought to the
Maintenance screen shown in Figure 2-3. From here, youll be able to select additional products and tools to install.
New Page 6
Figure 3: From the Maintenance screen, you can select the products and tools that you want to install
This isnt the only way to start the Installation Wizard and get to this screen. After Visual C++ 6.0 has been installed onto a computer, you can
add and remove different Visual Studio products with the Add/Remove Programs applet found in the Windows Control Panel. This applet is
accessed by selecting Settings from the Windows Start menu, clicking Control Panel, then double-clicking the Add/Remove Programs icon.
Add/Remove Programs will then open, and display a listing of previously installed applications. You then select Visual Studio from the listing
of installed programs, and click the Add/Remove button. This will open the Visual Studio Installation Wizard, and bring you to the
Maintenance screen shown in Figure 2-3.
The Maintenance screen of the Installation Wizard appears identical to the Custom screen we saw in Chapter 1. It enables you to add and
remove any of the client products and components in Visual Studio. This not only includes development and database applications, but also
the client portion of Visual SourceSafe. In the listing of options to add or remove, you simply click the check box beside the Visual
SourceSafe entry. If a check mark appears in the check box, then that indicates that the option has either been previously installed, orif you
just selected itthat the option is to be installed after you click the Continue button.
The wizard will check your system, and after its satisfied that there is enough disk space, the files related to this installation will be
transferred to your hard disk. Upon the completion of this transfer, a message box will appear, showing whether installation was successful or
not. If successful, youre ready to configure VSS for use. If not, you may need to rerun the Installation Wizard.
Although installing the Visual SourceSafe Client from a CD-ROM is effective, it is not the only way of performing an installation. There is
also the NetSetup method of installing the client portion. This is generally the recommended method of installing the VSS Client software, as
it allows users to install NetSetup over the network themselves. Whoever acts as VSS administrator doesnt need to be present with an
installation CD-ROM in hand. No installation CD-ROM is required when performing the installation because it uses the files in the Setup
folder residing in the folder that VSS Server was installed to. This is a benefit because the VSS administrator doesnt need to spend time
installing the client portion on every machine.
On the Job: The benefit of installing off the server applies not only to VSS administrators, but to most developers as well. If the VSS
administrator isnt given the task of installing the VSS Client to each developers workstation, individual developers (who have proper
permissions to the VSS Server directory on a server) will find it fast and simple to install over the network. Although many development
teams allow access to development toolsand would have access to the VSS installation CD-ROMthey would still require the proper
permissions and an account to access the VSS database.
As clients will be using the master database that was created when VSS Server was installed, NetSetup doesnt install a VSS database or
support files. It doesnt install an Admin tool, nor does it install a database, as the client portion is designed to use the services provided by the
VSS Server.
Although the CD-ROM installation can be performed either before or after Visual SourceSafe Server, NetSetup needs to be run after installing
VSS Server. A primary reason for this is because NetSetup is installed into the directory where you installed VSS Server. If you havent
installed VSS Server, then the NetSetup program hasnt been put onto your servers hard disk, and thereby cant be run.
Exam Watch: Since NetSetup is the recommended method of installing Visual SourceSafe Client software, you should be especially familiar
with this client installation type. Key points to remember are that NetSetup only installs the client portion, its run from the folder containing
VSS Server, no installation CD-ROM is required, and that users themselves can install VSS Client without administrator assistance. However,
because it uses the installation files in VSS Server, and NetSetup is installed with VSS Server, this means that you must first install VSS
Server before you can run NetSetup.
An exception to using NetSetup is when your network is experiencing heavy traffic. When NetSetup is used, the files transferred to the users
hard disk are sent over the network. If there is significant traffic, and numerous users are installing NetSetup, the network can become
seriously bogged down. When this is the case, you would want to perform a CD-ROM installation, or restrict the hours that users can install
through NetSetup.
You can begin installing the client portion of Visual SourceSafe over the network by using Windows Explorer (or NT Explorer if youre using
a Windows NT machine). By going to the folder in which you installed VSS Server, youll find a file called NETSETUP.EXE.
New Page 6
Double-clicking this file will start the NetSetup Installation Wizard.
As with most setup wizards, the first screen that youll see welcomes you to the Installation Wizard. Clicking the Continue button on this
screen will take you to the Name and organization screen. Here, youre required to enter your name, and the name of the company that you
belong to. The two fields on this screen will already have information entered in them, as the Installation Wizard retrieves the name and
company name from your Windows Registry. If this information is correct, click OK. Otherwise, correct the information, and then click OK
to continue. A message box will appear after this, confirming that the information you entered or accepted is correct. Clicking OK in this
message box will take you to the next step in the installation process, whereas clicking Change will take you back to the preceding screen.
The next screen shows the product ID number, which weve discussed when talking about other installations. Document this number, then
click OK to continue. This will cause the Installation Wizard to check your system for previous installations of Visual SourceSafe. If it finds a
copy, a dialog box will appear. It will state that an older copy has been found, but this necessarily doesnt mean that it is a previous version
of Visual SourceSafe. This same dialog appears if a current version is found. If you wish to overwrite the currently installed version, you can
click OK to continue. If youd like to keep this previous installation, you can click the Change folder button, and browse your local or network
drives for another folder to install to.
The next screen that appears gives you a final chance to change where Visual SourceSafe will be installed. Again, clicking the Change folder
button will enable you to browse your local or network drives for another folder to install to. To install the client portion, which allows you to
access a remote database, click the button that appears on this screen. Doing so will begin the transfer of files, and will install Visual
SourceSafe.
Exercise 2-2 Visual SourceSafe Client Installation
1. From the Windows Start menu, select Programs, and then click Windows Explorer (if youre using a Windows 9x system) or NT
Explorer (if your operating system is Windows NT). When Windows or NT Explorer starts, navigate your hard disk to the folder where VSS
Server has been installed. Double-click NETSETUP.EXE.
2. When the NetSetup welcome screen appears, click Continue.
3. Ensure that your name and company name are correct. If they arent correct, enter the correct information. Click OK to continue.
4. Click OK when NetSetup verifies that your name and company name are correct.
5. Document the product ID number, then click OK to continue
6. If the setup wizard detects that a previous version of Visual SourceSafe has been installed on your machine, and youre certain that this
is the VSS Server installation that we performed earlier, click the Change folder button. Enter a new path for the client installation to install to,
then click OK to continue.
7. When the screen appears with the licensing agreement, click Agree.
8. Click the Install button that appears on the next screen.
9. Wait as the Installation Wizard checks the availability of hard disk space, begins transferring files, and modifies your system settings.
When complete, click OK. This will bring up a prompt to restart Windows. Agree to this to finish the installation.
Configuring Visual SourceSafe
Once youve installed Visual SourceSafe, your work isnt quite over yet. You will still need to configure VSS, and create a list of users who
will be able to use the source code control system. This is done through the Admin program, which is formally called Visual SourceSafe
Administrator. This program (SSADMIN.EXE) is part of the VSS Server installation, and can be found in the Win32 folder in the folder
containing VSS. In addition to double-clicking this file, you can access it through the Windows Start menu. This is done by clicking Start,
selecting Programs | Microsoft Visual Studio 6.0 | Microsoft Visual SourceSafe, and then clicking Microsoft Visual SourceSafe Admin.
Starting the program will display the screen shown in Figure 2-4.
Figure 4: The Microsoft Visual SourceSafe Admin program lists the user information for the source code control system
New Page 6
A user list determines who has access to the source code control systems database. Through a user list, an administrator can add and delete
user accounts, assign rights, and change passwords. If a user doesnt have an account set up in this way, he or she wont be able to save or
retrieve files from the VSS database.
The Users menu of the VSS Administrator program contains various items that allow you to maintain the accounts of users. When you first
start this program, youll notice that two default accounts are already added to the user list. The person acting as VSS administrator uses the
Admin account, whereas users who dont have an account currently setup use the Guest account. When you first start the Admin program,
neither one of these accounts have passwords associated with them. You will be required to enter a password for the Admin account when you
first start the VSS Administration program. The Guest account doesnt have a password associated with it for good reason: because users who
dont have an account use it, numerous users may access VSS through this visitor account. As well see later though, you can
password-protect this account to limit accessibility. If youd like, you can also delete this account. The Admin account, however, cannot be
deleted.
The first step to setting up a user list is defining which VSS database your user list is for. Some users may have access to one database, but not
to another. As such, the Open SourceSafe database command on the Users menu is used to select and open a specific database. When this item
is selected, a dialog box opens that displays a list of current VSS databases. After selecting one of these databases, you can then click the
Open button to open that database. If you dont see the database that you wish to use, you can click the Browse button to browse local and
network drives for a specific database.
Once youve specified which database you want to use, you can use most of the other commands on the Users menu to control the user list
associated with that database. The Add user command on this menu adds a new user to the user list. The menu item displays a small dialog
box where you enter a user name and password. This will be used to identify the user when he or she logs in to VSS to use source code
control. If you dont want that user to be able to make changes to files and projects stored in the database, click the Read only check box. This
will allow the user to read information, but not to change it. Upon clicking OK, the user will be added to the user list.
When a new user is added, Visual SourceSafe creates a folder under /Users with that users name, containing a new SS.INI file for that new
user. This new file is based on the SS.INI file located in the /Users folder where VSS resides. This file is similar to the SRCSAFE.INI that
contains global variables that affect the VSS database. Although you can modify these files with any text editor, its not advised that you do so
unless youre familiar with what each entry in initialization file represents. User accounts should be modified through the commands available
in Visual SourceSafe.
Except for the Exit command (which closes the VSS Admin tool), each of the other commands in the Users menu can be used to modify or
remove a users account. These commands are:
Delete UserRemoves the selected users account from the user list
Edit UserDisplays a dialog box enabling you to change the user name of a selected user
Change PasswordDisplays a dialog box enabling you to change a selected users password
Each of these commands is used to modify the basic elements of the users account, which determine whether a user can use a specific
database. For more elaborate restrictions and modifications on a users account, you can use commands found in the Tools menu.
The Tools menu contains a number of commands that control both users and databases. First on this menu, are three commands determining
rights to data stored in the VSS database. These commands are as follows:
Rights by ProjectUsed to set rights on a particular project saved in the database
Rights Assignments for UserUsed to set a users rights
Copy User RightsUsed to copy another users rights to a selected users account
By default, these commands are disabled when you first use a new database. They appear shaded, and nothing happens when you click them.
This is because project security for the database hasnt been enabled.
Enabling project security is done through the Options dialog box, which appears when you select Options from the Tools menu. This dialog
box has a number of tabs, which are used to set the default behavior of VSS Administrator, as well as the databases and users maintained
through this tool. The Project Security tab has particular importance, as it determines what rights users have when new accounts are created.
Until the Enable project security check box has been selected on this tab, by clicking it, security is disabled. When selected, other options on
this tab become enabled, as do the three previously mentioned commands in the Tools menu.
When you Enable project security, the check boxes that become enabled on this tab are used to define the default rights of new accounts.
These rights consist of the following:
ReadAllows a user to view read-only copies of files
Check Out/Check InAllows the user to use the Check In and Check Out commands. These are used to store files and projects in the
database (check in), or retrieve them to make modifications (check out). Having this permission, however, doesnt enable the user to add,
rename, or delete files from a project thats been checked out.
Add/Rename/DeleteAllows the user to add, rename, delete, check in, and check out files. However, the user cannot destroy projects
and files.
DestroyAllows a user to use all commands associated with VSS. This gives the user the ability to permanently delete projects and files
from the VSS database. The users rights are equivalent to the default Read-Write access that is assigned to users before project security is
enabled and the default rights of users are modified.
By selecting or clearing these check boxes, you are defining the default rights of new users. Its also important to note that these rights are
progressive. For example, to have Check Out/Check In as a right, you also need Read. If you want to assign Add/Rename/Delete to a user,
then the previous two rights are automatically assigned as well. Finally, by assigning Destroy, you give the user each of the other previously
mentioned rights as well. Also, as well see next, these rights can be modified for users on a project-by-project or a user-by-user basis.
Once project security has been enabled, the Rights by project, Rights assignments for user, and Copy user rights commands become enabled
in the Tools menu. These allow you to control security by determining what rights a user has to specific projects or in general. As well see in
the paragraphs that follow, each of these commands allow you to control security in different ways.
New Page 6
Clicking Rights by project from the Tools menu brings up the dialog box shown in Figure 2-5. The left side of this dialog displays a tree of
projects that you can navigate through. Upon selecting a project, you can then select one of the user accounts associated with this database,
and assign user rights to each account. After selecting an account, click a check box beside a particular right to assign or remove that right. If
you would like to delete a user from having rights to a project, simply select the user, and then click the Delete user button. If you would like
to add a previously deleted user to the listing, you can click the Add user button.
Figure 5: Use the Rights by project dialog box to assign rights to user accounts for a selected project
The Rights assignments for user command is used to specify project rights to a VSS database. Upon selecting a user from the listing in the
VSS Administrator tool, you then click this command to bring up the dialog box shown in Figure 2-6. The top of this dialog has a section
called User rights, which lists each of the four rights weve discussed. Beside each right is a check box, which is used to add or remove rights
for that user from a project. Below this section is a listi of projects to which you can add or remove assignments. If youd like to add a project,
and specify the users rights to that project, you can click the Add assignments button. This will display a dialog box with a list of projects.
You can click a project in this tree, and then specify rights for that project by selecting the check boxes for rights on this dialog. Clicking OK
will add a selected project to the list of projects. Once added to the Assignments for user dialog, you can further modify the users rights by
selecting or clearing the check boxes of specific rights from this screen. Upon clicking OK, those rights are then assigned to the user.
Figure 6: Use the Assignments for user dialog box to assign rights and projects to a user
Select a user from the listing in VSS Administrator and then select the Copy user rights command to open a small dialog displaying a list of
users. Select a user from this list and click the Copy button, and the rights of that user are copied to the account that you selected before
clicking Copy user rights. This saves you the time of having to determine which group of rights a user should have. If you know that you want
to give a user called Darren the same rights as a user called Julie, you can copy Julies rights to Darrens account. Rather than having to
determine which rights to give and then select each right for the users account, you assign the rights in one easy action.
Its important to note that these rights can only be applied if an account has the default Read-Write rights. If youve selected Edit account
from the File menu, and then selected the Read only check box, only the Read right is assigned. This disables any additional rights that can be
given. The only right that can be effected through the commands in the Tools menu for this user would be the Read right. Although you can
remove or add the Read right on this users account, no other rights can be added.
The Lock SourceSafe database command in the Tools menu is used to lock users out of an open database. This is used when youre planning
to archive or back up the database, or upgrade or run certain executable programs, such as utilities. This command is only available to
administrators, and when used, it displays a dialog box showing which users are currently logged on to the database. By selecting the Lock all
users out of Visual SourceSafe check box and clicking OK, you keep any additional users from logging on and using that database. However,
the users who are currently logged on to the database are unaffected by this, and must be notified to log off.
New Page 6
The way the database is archived after Lock SourceSafe database has been selected is through the Archive projects command on the Archive
menu. When this is selected, the Archive Wizard appears, and the three-step process of archiving the database begins.
The first screen of the wizard has you select a project to archive. Upon clicking OK, you can either click the Add button to add additional
projects to archive, remove the project (by selecting it from the list and clicking Remove), or click Next to continue.
The second screen of the Archive Wizard is where you determine what you want to do with the selected projects. You have three options here:
Save data to file
Save data to file, then delete from database to save space
Delete data permanently
If you select either of the first two options, you need to specify where the data will be archived to, as well as a filename for that archive. The
last option purges the data from your database without saving it first.
The last screen of the wizard appears if youve chosen to save data to a file. Here, you can choose to either archive all of the data, or archive
the latest version in addition to older versions. If you choose the Archive this version and older option, a field becomes enabled in which you
specify a version. Any versions between this and the latest version will then be archived. If youd like to make a comment on what this
archive contains, you can enter it in the field below it. Clicking Finish closes the wizard, and archives the data.
The Archive Wizard is similar to the Restore Wizard, which is used to restore archived data to the VSS database. Selecting Restore projects
from the Archive menu starts this wizard. The first screen is where you specify which archive file you want to restore. Click Next, and you
will see a list of projects stored in the archive. You can select which files you want restored by either clicking a specific file in the tree, or by
clicking the Select all button. Just as the Select all button selects all files in the tree, Deselect all clears everything. When youve selected the
files to restore, clicking Next will bring you to the final step. Here, you choose whether to restore the files to the project they were archived
from, or to restore the files to a new location. If you choose the first option, it will overwrite existing files. Upon selecting one of these
options, clicking Finish will restore the files based on the criteria given through the wizard.
In addition to the previously mentioned commands in the Tools menu, there are also the following commands:
Clean up Temp DirectoryDeletes all temporary files in the VSS Temp directory
Create DatabaseAllows you to create new VSS databases
FontAllows you to choose a new font in which the VSS Admin tool should display information
Whereas the Font command is purely superficial, and the Clean up temp directory command is used for maintenance, the Create database
command is particularly important if you wish to create other databases that developers can save to. When this menu item is selected, a dialog
box appears that allows you to enter a location for the new database. You can select the check box on this dialog to indicate that all users of
this database use version 6.0 client software. If they use previous versions of VSS client software, then this check box should be cleared.
Exercise 2-3 Creating and Maintaining a User List with VSS Administrator
1. From the Windows Start menu, select Programs, | Microsoft Visual Studio 6.0 | Microsoft Visual SourceSafe. Click the Visual
SourceSafe 6.0 Admin shortcut in this folder to start the VSS Administrator tool.
2. From the Users menu, click Open SourceSafe database. Select the Common database from the listing of available databases, then click
OK.
3. From the Tools menu, click Options. Select the Project security tab, then click Enable project security. This will enable the previously
disabled commands in the Tools menu.
4. From the Users menu, click Add user. This will display a dialog box. Enter the user name you wish to use, followed by a password.
Click OK to save this new account to the list.
5. From the list of users, select the Admin user, and then click the Rights assignments for user command from the Tools menu. Notice that
the Admin users rights cannot be changed.
6. From the list of users, select the Guest user. Click Edit user from the Files menu, and then click the Read only check box. Click OK.
Notice that the Guest user now has Read-Only access to this database now.
7. From the Tools menu, click Rights assignments for user. Notice when the dialog box appears that no additional rights can be assigned,
as the user has Read-Only access.
8. From the list of users, select the account you created in Step 4. Click Rights assignments for user. Click the check box for the Read right.
Notice that all subsequent rights are automatically removed.
9. Click each check box for the rights on this dialog, so that every check box is selected. This will give your account full rights to VSS
commands. Click Close.
Using Visual SourceSafe
As mentioned previously, when a source code control system has been installed, new menu items and dialog boxes will appear in Visual C++
6.0. A submenu called Source control will appear in the Project menu, and a new tab will appear in the Options dialog. Through these new
additions, you can interact with Visual SourceSafe.
Until you actually open or create a project in Visual C++ 6.0, the only menu item in the Source control submenu is the one called SourceSafe.
Clicking this menu item opens the Visual SourceSafe Explorer. This application is similar to Windows or NT Explorer, except that you use
the VSS Explorer to browse and work with projects and files saved to the VSS database. As well see, many of the commands found on the
Project menu are also available through the VSS Explorer.
When you open the VSS Explorer, you see an interface similar to that shown in Figure 2-7. The difference between what you see in your copy
of VSS Explorer and whats shown in Figure 2-7 will be that you currently have no projects saved to VSS. As such, most of the panes or
windows in this program will appear empty. Regardless, what you can see is that the Visual SourceSafe Explorers interface is made up of
New Page 6
several panes. The left pane lists projects currently stored in the database youre using. By clicking a project in this tree, the right pane
displays files contained within the selected project. Below this is the Results pane. This shows you the results of operations performed through
Visual SourceSafe. For example, lets say you tried to check out (i.e. retrieve) a project that you currently have checked out. When you
attempt this, the Results pane will inform you, for each file checked out, that a particular file is already checked out by you.
Figure 7: The Visual SourceSafe Explorer allows you to browse through projects saved to the VSS database
The File menu of Visual SourceSafe Explorer contains a number of commands that affect the database that is being used, the projects in that
database, and VSS Explorer itself. The commands in this menu consist of the following:
Open SourceSafe DatabaseEnables you to open a new VSS database
Add FilesDisplays a dialog box that enables you to browse your hard disk for files to add to a project that youve selected in the Project
pane. These files are added to the VSS database with the currently selected project.
Create ProjectAllows you to create a new project, to which you can add groups of files
DeleteDisplays a dialog box that enables you to specify projects and files to delete. When the check box entitled Destroy permanently is
selected, these items are permanently deleted, and cannot be retrieved again.
RenameAllows you to rename a project or filename
PropertiesDisplays the properties of a selected project or file
Set Working FolderAllows you to change the folder in which your project resides. When you edit or compile projects and files, this is
done in the working folder that the project was originally saved to. It is not done in the VSS database.
Create ShortcutAdds a shortcut to the currently selected project or file on your Windows desktop
LabelDisplays a dialog box that enables you to add a label to the currently selected project or file
MoveDisplays a dialog box that enables you to move a selected project or file to another project thats saved in the VSS database
ExitCloses VSS Explorer
The Edit menu contains fewer commands, all of which are related to selecting and editing files. The View file command displays a dialog box
that allows you to choose whether to view a SourceSafe copy of the file, or to check out the working copy of this file for editing. The Edit file
command displays the same dialog. However, whereas the first option is selected for View file, the second option of checking out the file for
editing is selected for Edit file. The Select command is used to select a specific file, whereas Select all selects all files in the File pane. Finally,
if you have one file selected, and wish to now select everything but the currently selected file, you can use the Inverse selection command.
The View menu is used for sorting and searching for files. The Sort submenu is used to specify how files in the File pane are to be sorted (for
example, by name, user, etc.). This results in the same action as if you clicked a column header in the File pane. The Search submenu contains
commands for finding and filtering whats displayed in the File pane. You can use this to view files by their checked out status, or find
specific files by doing a wildcard search. Finally, you can use Cancel search to cancel any search youve done, and Refresh file list to refresh
the display of information in the File pane.
New Page 6
The SourceSafe menu is where we begin to see menu commands that appear in the Source control submenu of Visual C++ 6.0s Project menu.
The commands common to both menus consist of the following:
Get Latest VersionUsed to retrieve the most current read-only version of a file from the VSS database to the working directory
Check OutUsed to place a working copy of a file in your working folder
Check InUsed to update the project or file thats been saved to the VSS database
Undo Check OutCancels any changes made to a file in your working folder, so that current changes arent saved to the VSS database
ShareUsed to share files from other projects with the one currently in use. (This command is called Share from SourceSafe under the
Source Control submenu.)
In addition to these commands, there are commands in the SourceSafe menu in VSS Explorer that dont appear in the Source Control
submenu in Visual C++6.0. By selecting a shared file, and then clicking the Branch menu item, you can branch a file in two directions. From
the point where the branch has been set, developers in each project can now modify the file without their work overlapping. Each project has a
copy of the shared file. In the Project pane of VSS Explorer, a line will appear between these two projects, showing that they are connected.
By selecting Merge branch from the SourceSafe menu, you can then merge the branched files together.
The Tools menu also contains a number of commands found in the Source Control submenu in Visual C++6.0. Show history is used to show
the history of a project or file. In Visual C++ 6.0, select a file you wish to view the history of, and then choose this command from the Source
Control submenu. This will show what, if any, changes have been made to the selected file or files. When used through VSS Explorer
however, you also have the option of viewing the history of files as well as entire projects. As Figure 2-8 shows, different dialog boxes appear
depending on whether youve chosen View history for a file or a project.
Figure 8: The History options dialog box for projects is slightly different from the dialog box for files
Many of the options are identical on the History options dialog box, whether youve chosen View history for a file or a project. Common to
each of these are the Include labels and Labels only check boxes. When Include labels is selected, the user-defined name that a developer has
labeled the project or file is shown. If you select the Labels only check box, then the files and the projects with labels are shown in the history.
The From, To, and User fields allow you to specify a range of versions to show, or those versions worked on by a specific user. You use the
From and To fields together to specify a range, based on the time, date, version, or label of files or projects. When entering dates, they can be
in the format of 08.09.65, 08-09-65, or 08/09/65, but not as September 08, 1965. Also, you cant search for file labels when viewing the
history of a project. Once youve selected the options you wish to use, you can then click OK to view the history of versions of a file.
If youve selected View history for a project, there are still two additional check boxes to consider before clicking OK. The Recursive
checkbox is used when you want to include subfolders and the files within those folders. This will allow you to view the history of each
subfolder and its contents when viewing history by project. The Include file histories check box is used to indicate whether you want to
include files when viewing the history of a project.
Once youve clicked OK, the History of project or the History of file dialog box will appear. The one that appears depends on whether youve
selected to view the history of a project, or selected a specific file before using View history. This dialog contains a list of various files, and by
double-clicking a file, you can display the history information on that file. You can also display the history by selecting a file and clicking
Details. By clicking the Next or Previous buttons in the History details dialog that appears, you can move up or down the listing of files in the
history display. You can also check out and share files, or print or save a report on the various items in the History of project or History of file
dialog box.
In addition to View history, the Show differences command in VSS Explorer and the Source Control submenu of Visual C++ 6.0 can be used
to view information. This command is used to view changes to a file. When selected, it will compare changes made in the working copy to
that of the copy in the VSS database. This allows you to view differences between different checked-in versions of a file. This command is
only used to view differences in copies. In addition, it cannot be used to compare two files in a working project, and is only used to compare a
file in the working folder to whats been saved in the master copy in the VSS database.
In addition to the commands weve discussed, there are several other menu items that appear in the Tools menu of VSS Explorer that dont
appear in the Source control submenu of the Project menu in Visual C++6.0. These include:
Find in FilesEnables you to enter part or all of a string used in a specific file or project. Clicking OK starts a search for that particular
line of code
Files ReportDisplays a dialog box that enables you to create a report on files and the people who have modified them
OptionsEnables you to change aspects of VSS Explorer
FontChanges the font used to display files and information through VSS Explorer
Customize ToolbarEnables you to change buttons on the toolbar
New Page 6
Change PasswordUsed to change your Visual SourceSafe password
Just as VSS Explorer has some commands that dont appear in Visual C++ 6.0, the reverse also applies. There are some menu items appearing
in the Source Control submenu, found in the Project menu of Visual C++ 6.0, which dont appear in VSS Explorer. These consist of the
following:
Add to Source ControlUsed to add a projects files to the source code control systems database
Remove from Source ControlRemoves a projects files from the source code control database
SourceSafe PropertiesDisplays a specific file or projects source code control properties
Refresh StatusUsed to update the status of a file in the source code control system
Multiple User/Multiple Location Development
With Visual SourceSafe, developers working from different locations on the network can work on individual files, and on files stored in
projects, in the VSS database. Multiple developers can work on individual files stored in the database, and there is no limitation on the number
of copies of that file that users can check out. If more than one user checks out the same file, then the first user gets a read-write copy, while
each additional user who checks out this file gets a read-only copy of the file.
If a project has been saved to the VSS database, the default behavior of Visual SourceSafe is that only one user at a time is allowed to check
out files stored within a project. This means that only one developer at a time can work on projects or files that have been saved to the VSS
database. However, you can change this setting so that more than one user has the ability to check out a particular project.
To do this, you need to open the VSS Admin tool. Once open, use the Open SourceSafe database menu item on the Tool menu, and select a
database you want to change. After doing this, select Options from the Tools menu. This brings up the Options dialog box, where you can
change settings for VSS. The General tab of Options contains a check box entitled Allow multiple check outs. When this is selected, more
than one user can check out a file.
Exam Watch: Until the Allow multiple check outs check box is selected, only one user at a time can check out a file from the VSS database.
Allow multiple check outs is found under the General tab of Options in the VSS Administrator.
When this has been set, and more than one user checks out a particular file, the first time a file is saved to the VSS database, it is updated.
After this, each time users check in a file, those subsequent changes are merged. This enables multiple users from multiple locations to work
on a single project, using source code control.
Generally, when more than one user is working on a single file, they are modifying different lines of code. There may be times, however,
when two users modify the same line of code. As VSS checks changes before merging them into a master file, it can detect when two or more
users have made such conflicting changes. When it does detect this, it refuses to allow the check in of that file. It then sends a message to the
user checking in the file that the conflicting line of code needs to be changed before the file can be checked in. The user can then change his or
her local copy of the file to resolve the problem.
Versioning of the Source Code
As we saw earlier in this chapter, you can view the history of different versions of files and projects that have been saved to the VSS database.
This allows us to see changes to files, as Visual SourceSafe maintains multiple versions of a file. This means that each time changes are made
to a file, a new version of the source code is stored in the VSS database.
The version control in Visual SourceSafe helps to ensure that only one person at a time is modifying a file. Unless Allow multiple check outs
has been selected, only one developer has the ability to check out and modify a file. As we saw in the previous section, when multiple check
outs are allowed, Visual SourceSafe still protects one version of source code from overwriting another.
In previous sections we also saw that you can view the history of a file or project, and track the different versions of code that have been
checked in. You can then retrieve these previous versions, should you wish to reuse code from older versions in your current project. From
this, the versioning of source code also gives you the ability to track which programs use certain object-orientated code, then reuse that code
in other projects.
The way that Visual SourceSafe tracks different versions of files and projects is with version numbers, labels, and date/time stamps. In
discussing each of these methods, well see that these methods are either internally maintained by Visual SourceSafe, or applied by the user.
Each method keeps VSS from accidentally overwriting one version of a file with another.
As mentioned, labels are user-defined strings that are applied to a project or file. They can contain up to 31 characters, and allow the user to
give files and projects meaningful names or comments. By using labels, you can provide version information for Visual SourceSafe to use.
For example, by giving the label 3.1, 2B or NOT2B, you indicate a version number that is different from other versions of a product. You can
even use sentences to indicated what a particular version represents or has achieved in the development process. For example, Bug Fix 3 or
Approved by Testing are both valid labels to use.
Date/Time stamps are applied to files, indicating when they were modified or the last time the file was checked into the VSS database. This
allows VSS to look at when changes were last made, or when a version was last saved to the database. By looking at this date and time
information, VSS can determine which versions came before and after one another.
The version numbers used by Visual SourceSafe are different from the version numbers applied to a project in Visual C++ 6.0. Unlike those
in Visual C++ 6.0, you have no control over what version number is applied to a file or project. These are controlled exclusively by the source
code control system. Each time a project or file is updated and saved to the VSS database, Visual SourceSafe automatically increments the
version number. This number is always a whole number, and is never decremented.
This is different from the version numbers applied to projects in Visual C++ 6.0. A project in Visual C++ 6.0 includes a resource file that
defines the version of a project. There is only one of these files in each project and it can be accessed by clicking the ResourceView in Visual
C++ 6.0, which displays resource files included in the project. As shown in Figure 2-9, ResourceView shows the resources associated with a
particular project. Each resource type is contained in its own subfolder, including that of Version. Within the Version resource type is a file
called VS_VERSION_INFO, and by clicking it, you can bring up the Version Information Editor.
New Page 6
Figure 9: Use ResourceView in Visual C++ 6.0 to display the resources for a project
As shown in Figure 2-10, the Version Information Editor displays a considerable amount of information on a project. This information is
added to the compiled program, and much of it is available to an applications user by viewing the programs properties. The FILEVERSION
string indicates the version of a file, whereas the PRODUCTVERSION string indicates the version of the project as a whole. You can change
the version of a product or file by respectively double-clicking either the PRODUCTVERSION or FILEVERSION strings, which are
displayed through the Version Information Editor.
Figure 10: The Version Information Editor displays important project information
The format of the version information in these strings is read from left to right. Each number indicates a level of change to the application,
with the leftmost number indicating a major change. Each number to the right of this first number denotes smaller changes. For example,
when Microsoft made major changes to Windows 3.1, it introduced Windows 95. Windows 95 was actually version 4.0. This means the
version would have changed from 3, 1, 0, 0 to 4, 0, 0, 0. When Windows 98 was released, the changes to the operating systems code were
less drastic, so it was version 4, 1, 0, 0. As patches and updates to the operating system were made, the numbers to the right of 4.1 were
incremented. This same type of versioning should be applied when setting version information on applications that you create.
MFC Wizards
MFC is an acronym for the Microsoft Foundation Class Library. Like the foundation that you build a house upon, MFC provides the
foundation for building a good application. It provides you with commonly used code for such things as dialog boxes, menus, basic
input/output, and many other things. Rather than having to focus on creating the same objects or programming the same functionality over and
over again, MFC supplies the common code so that all you need to focus on is programming the application-specific code. It provides you
with a framework on which you build your application.
One of the powerful elements of MFC is the set of wizards included in Visual C++ 6.0. These wizards take you step-by-step through the task
of creating executable applications, controls, classes, and so forth. These wizards include the following:
MFC AppWizardHelps you create executable and dynamic link library (DLL) programs
MFC ActiveX ControlWizardHelps you create ActiveX controls
Custom AppWizardUsed to create custom program types
ClassWizardHelps you create new classes, define message handlers, and perform other routine tasks
WizardBarA toolbar that provides you with access to elements associated with the ClassWizard
When used, these wizards provide you with the ability to be walked through the tasks of creating classes, controls, applications, and
performing other tasks. Rather than having to perform actions and write necessary source code, these wizards do the work for you. This leaves
you with only having to write code that specifically deals with the program youre creating.
The MFC AppWizard actually comes in two forms. One creates an executable program with the extension of .EXE, while the other is used to
New Page 6
create dynamic link libraries with the extension of .DLL. When either of these versions of the AppWizard are run, source code files and
resource files are created, based on classes in the MFC library.
The Custom AppWizard is a wizard used to create your own custom AppWizards. When this is used, you can create a wizard that creates
project types that you define. Other developers can then use the AppWizard that you create to walk them through the task of creating an
application.
MFC ActiveX ControlWizard is used to create the files necessary to build your very own ActiveX control. This wizard takes you through the
steps, allowing you to specify run-time licensing agreements, how many controls the project will have, how many Help files should be created
for the project, how it activates, and so on. Once you have completed the steps of this wizard, Visual C++ 6.0 generates all the files needed to
create your control based on the criteria youve provided.
Except for the ClassWizard and the WizardBar, you can start any of these wizards by starting a new project. By selecting New from the File
menu in Visual C++ 6.0, you are met with a tabbed dialog box. By clicking the Projects tab of this dialog, youll see a list of various project
types that can be created. In this list, youll see Custom AppWizard, MFC ActiveX ControlWizard, MFC AppWizard (.EXE), and MFC
AppWizard (.DLL). Youll also see a field in which you enter the name of your project. Once the project name has been entered, you
double-click any of these wizards, or select a particular wizard and then click OK. This starts the wizard that youve selected.
Unlike the previously mentioned wizards, the ClassWizard works with projects that you currently have open in Visual C++ 6.0. It works with
the current project to create new classes, define message handlers, gather data, and so forth. It can also be used to define the events, properties,
and methods of controls created with other wizards, such as the ActiveX ControlWizard.
The WizardBar works with the ClassWizard. Through this toolbar, you can access the functionality of the ClassWizard and the ClassView of
Visual C++ 6.0. Using the toolbar, you can navigate through classes, and perform actions that are accessed through the ClassWizard.
On the Job: Until you name your project, the OK button on the New project dialog box will be disabled. You must name your project before
you can start any of the wizards or project types listed. This often throws off some new users to Visual C++ 6.0, as they try double-clicking a
project type, only to find that nothing happens.
The ClassWizard and WizardBar are started from within Visual C++ 6.0. The ClassWizard is started through the View menu, by selecting the
ClassWizard menu item. By clicking on this command, the ClassWizard will automatically appear. Because the WizardBar is a toolbar, it is
accessed the same way that any other toolbar is accessed. By right-clicking an empty section of the toolbar, a listing of available toolbars
appears. Upon selecting WizardBar from this listing, it will appear in your toolbar.
Once youve started a wizard, you then follow each of the steps, screen-by-screen until you reach the end. How many steps you go through
depends on the wizard being used, and the options selected on various screens of the wizard. Also, you dont have to complete all of the steps
in the wizard prior to clicking Finish. As soon as the wizard has gathered the required information, the Finish button becomes active, and the
developer can complete the wizard without visiting each of the steps. You then click Finish and the files required for your project are created.
Resource Editors
A resource editor is an interface that allows you to view and modify information contained in resource files of your project. They can be used
to create new resources, and modify or delete existing ones. Resource editors in Visual C++ 6.0 include the following:
Accelerator Editor
Binary Editor
Dialog Editor
Graphics Editor
Toolbar Editor
Menu Editor
String Editor
Version Information Editor
Earlier in this chapter we discussed one such resource editor, the Version Information Editor. Basically, each of the editors appear the same.
They provide information on a specific resource, and allow data to be modified by double-clicking an entry listed in the editor.
As we saw when discussing the Version Information Editor, you can start a resource editor by clicking the ResourceView in Visual C++ 6.0.
You then open the subfolder of a resource that you wish to view, and double-click a file contained within that subfolder. Upon doing so, the
related resource editor automatically opens. You can also create new resources and automatically go to the associated resource editor by
selecting Resource from the Insert menu, and then choosing the type of resource to insert into your project.
The Accelerator Editor is used to view and modify accelerator key assignments in your project. Accelerator keys are also known as shortcut
keys, and allow users to quickly access a command in your application by pressing a combination of keys. For example, ctrl-z is a common
shortcut key in Windows applications, and is used to undo a previous action. When you start a new project, such common accelerator keys are
automatically added. You shouldnt change predefined keys, as they are standard keys common to all Windows applications. To add a new
key, or change keys youve previously created, you begin by opening the Accelerator Editor, and then double-clicking the key you want to
modify. This brings up the Accel properties dialog box. Through this dialog, you can choose the keys used to invoke an action. You can
choose to use ctrl, alt, shift, or a combination of these, which are used in conjunction with a character that you select. You can also specify
whether an ASCII or virtual key identifier is used. A virtual key identifier is an identifier thats selected from the drop-down list on this dialog
box. By clicking the Next key typed button, you can simply press a key on your keyboard, and it is assigned as an accelerator key.
The Binary Editor allows you to view and edit resources at a binary level. To open this editor, you right-click a resource in ResourceView,
and then select Open binary data from the menu that appears. Upon doing this, the editor will open, and you can then edit the resource using
binary or hexadecimal format. Obviously, to do this, you will need an understanding of these formats, which is beyond the scope of this book.
The Dialog Editor is used to create and edit dialog boxes. Upon opening this editor, you will see a dialog box and a toolbar of various controls
that can be added to it. This enables you to view, add, and remove controls and code from an existing or new dialog box.
The Graphics Editor is used to view, draw, and modify images in various formats. This editor includes a number of tools, which are similar to
those included in the Paint program that comes with Microsoft Windows. Using this tool, you can create custom images to use in your
New Page 6
application. This editor allows you to create and modify icons and cursors used in your applications.
The Toolbar Editor is similar to the Graphics Editor. It too contains graphic tools, which allow you to create and edit images used on toolbars.
In doing so, the Toolbar Editor enables you to create, edit, and move toolbar buttons, create new toolbars, and convert bitmapped images into
toolbar buttons.
The Menu Editor is used to view, add, and modify menus included in your project. When this is started, it shows a menu system. You can
click the various menus on this system to expand them. In doing so, youll notice there are blank boxes appearing beneath menu items and in
the menu itself. By clicking these boxes, you can enter captions for new menu items. When entering a caption, you can type an ampersand (&)
in front of a letter in the caption to define an access or mnemonic key. This allows the user to press the alt key with the character following the
ampersand to access that particular menu item. For example, pressing alt and the f key would open a File menu. When it appears to the
end-user, the mnemonic key appears underlined on the menu. This allows the user to see what combination of keys (for example, alt and the
underlined key) should be used to access a top-level menu item. Once accessed, the end user can then navigate through the menu to access
items and submenus under that menu item.
When you add a new menu item, or double-click an existing one, a small dialog appears with two tabs. The Extended styles tab allows you to
select a check box indicating that the item should be ordered and aligned from right-to-left. This feature is usually for internationalization,
where languages read from right-to-left are to be supported. The General tab is the more commonly used tab, and contains considerably more
options, which are as follows:
IDUsed to specify a symbol thats defined in a header file
CaptionText that appears on the menu
SeparatorCheck box indicating that the menu item is a separator, which is a line used to separate different items on a menu
CheckedCheck box used to specify that the menu item is to appear checked
PopupCheck box used to indicate that the menu item is a pop-up menu
GrayedCheck box used to indicate that the menu item is inactive and appears grayed out
InactiveCheck box used to determine that a menu item is inactive. This is always checked if the Grayed option is checked.
HelpCheck box indicating that the menu item should be rightmost on the menu. In Windows, Help menus are always rightmost on a
menu
BreakDrop-down list to which you can set one of three values: None, Column or Bar. Column places the menu item on a new line in
static menus, and in a new column in pop-up menus. Bar also separates columns, but does so with a vertical line. None indicates that there is
no break.
PromptField where you can enter a string. This will appear in the status bar of your application when this menu item is highlighted.
Together, these options are used to control the appearance and behavior of specific menus and menu items. Once youve completed creating
your menu system, you can then use the ClassWizard to attach code to specific menu items.
The String Editor is used to edit strings that are used in your applications. These are stored in a string table, which contains a list of all IDs,
values, and captions used in the application. The string table is a facility for storing such information, when you dont want it hard-coded in
the application. When you open the String Editor, the string table is loaded into it, allowing you to view, add, modify, and delete any strings
contained in this table. To add a new string, simply right-click the String Editor, and then enter the new string.
Using the Gallery
The Gallery is a folder on the hard disk where you installed Visual C++ 6.0 that contains source code. Basically, the Gallery is a storehouse of
reusable code. When you install Visual C++ 6.0, a folder is added to the location where you specified Common files should reside. By default,
this would be \Program Files\Microsoft Visual Studio\Common\MSDEV98\Gallery. Contained in this folder are two default folders. One is
called Visual C++ components, and the other is called Registered ActiveX controls. The contents of these folders are exactly what their names
state.
The way you access the Gallery from within Visual C++ 6.0 is through the Project menu. By selecting Add to project from this menu, and
then clicking Components and controls, a dialog box opens, showing the contents of the Gallery. When the dialog box appears, you can enter
either of these two default folders and select components and controls to add to your project. Upon selecting a control or component, you then
click the Insert button on the dialog box to have that item added to your project.
Because the Gallery is a folder on your hard disk, you can use Windows Explorer to add additional folders to the Gallery folder. You can also
use it to copy additional components, controls, and source code to the Gallery for future use. Using Visual C++ 6.0, you can also use the Save
As command on the File menu to save source code files, components, controls, and so forth to the Gallery folder. Other developers with
access to this folder can then reuse your code in their own projects.
Subfolders are added to the Gallery when you use the Add components and controls option in Visual C++ 6.0. In using this command, you
can select components and controls that will be used in projects. After you add a new component or control, subfolders containing these
components or controls are created in the Gallery, keeping them available for other developers and future use.
Information Resources
At times, you may require information resources that can assist you with using Visual SourceSafe or developing with Visual C++ 6.0.
Fortunately, Microsoft provides a variety of ways to assist you. Some of these are available through Visual Studio and Visual C++ 6.0,
whereas others require additional software, a subscription, or a purchase.
Each product discussed so far includes a Help menu, which is used to access files containing reference materials. This may consist of tutorials,
examples, or other pieces of information. By using the Help menu, you can search online user assistance for specific areas youd like further
information on, or areas that you need assistance with.
MSDN is the Microsoft Developer Network, and as we saw in the previous chapter, serves as a comprehensive source of information. It
includes a knowledge base of information, product and software development kit (SDK) documentation, technical documents, examples,
sample code, and more. Although MSDN does come with versions of Visual C++ and Visual Studio, you may also be interested in obtaining
New Page 6
newer editions. MSDN is published every three months or so, and is available through subscription. This allows you to get the most current
information available delivered to your door.
TechNet is a technical reference source that is available through paid subscription from Microsoft. Each month or so you receive a set of
CD-ROMs that contain updates, technical papers, a knowledge base, and other information. You can subscribe to TechNet through the Web
site mentioned later.
In addition to these information resources, there are also a number of Web sites available that provide information on Visual C++ 6.0 and
other products available with Visual Studio. In using information on the Internet, remember that some information may not be reliable. After
all, any kid with a Web page editor and Internet access can slap a page on the Internet. As such, its best to stick with sites that have proven
that they have accurate information.
Microsofts Web site has a number of areas that deal with topics covered in this book. Some of these include:
Visual Studio Web site, http://msdn.microsoft.com/vstudio/
Visual C++ 6.0 Web site, http://msdn.microsoft.com/visualc/
Visual SourceSafe Web site, http://msdn.microsoft.com/ssafe/
MSDN Online, http://msdn.microsoft.com
TechNet, http://technet.microsoft.com
Each of these Microsoft sites contain up-to-date information, updates, and more on various Visual Studio products, inclusive to Microsoft
Visual C++ 6.0. To use any of these sites, youll need a modem (or network access to the Internet), Internet access, and a browser that is set to
accept cookies.
From the Classroom
Explore the Research Options in the MSDN Universe
For a developer and trainer, one of the most crucial factors for success is the ability to locate and digest information. Whether locating an
answer to a student's question, or understanding how to correctly utilize a class in the MFC Library, MSDN Library is one of the first resource
to turn to. There are several other features and options available with the Microsoft Developer's Network that merit further attention and
explanation.
MSDN Library can be installed on the developer's machine along with Visual Studio. However, there are other features of MSDN that can be
very useful. Similar to the MSDN Library, MSDN Online is an Internet gateway to all kinds of up-to-date product news, specifications,
upcoming events and product releases, training, and much more. The on-line version of the MSDN Library also contains product
documentation, sample applications, and sample code. MSDN Online Memberships are free and allow developers the ability to interact with
other Microsoft professionals using Online Special-Interest Groups (OSIGs) and the Members Helping Members program. MSDN Online
members are also able to download free trials and beta products.
MSDN Subscriptions are another useful service. With an MSDN Subscription, a developer will receive the latest updates to technical
information and product releases. MSDN Subscriptions are an annual membership product and come in three levels. The MSDN Library
Subscription is the basic subscription, providing sample code, access to current knowledge base articles and bug lists, specifications, product
documentations, books and periodicals, and conference and seminar papers. The MSDN Library Subscription also integrates with the Internet
so the user can navigate smoothly between the subscription-provided information and the information on MSDN Online. The second level is
the MSDN Professional Subscription. The Professional level includes all of the services of the Library Subscription as well as the latest
releases and pre-releases of the Windows operating systems, all of the available Software Development Kits (SDKs) and Device Driver Kits
(DDKs), International versions of Windows operating systems, and automatic updates are delivered when new releases or service packs are
available. The most comprehensive subscription available is the Universal Subscription. The Universal Subscription includes all of the
services available to the Professional and Library Subscription members, plus a full year of Microsoft's current and upcoming development
products, and the Microsoft BackOffice Test Platform.
Additional MSDN services include the MSDN Flash program, ISV Program, User Groups and Events. The MSDN Flash Program sends a
twice-monthly newsletter containing technical news, new or upcoming release information, and events. The MSDN ISV Program addresses
the needs of Independent Software Vendors that support or run on Microsoft Products. MSDN User Groups and developer events are available
to further facilitate the sharing of technical expertise.
When you are in the depths of Visual C++, swimming through Class members, Interfaces, and Compiler options, remember that you are not
alone. The Microsoft Developer's Network has a variety of resources available to assist you in finding solutions, and keeping up with the
fast-paced world of software development.
Michael Lane Thomas, MCSE+I, MCSD, MCT, MCP+SB, MSS, A+
Now that weve discussed so much about Visual C++ 6.0 and its tools and wizards, lets look at a few scenario questions and their answers,
before taking on the test associated with this chapter. The questions are common ones that may not only help you with your exam, but also in
real world situations you may encounter.
What is source code control, and why is it important? Source code control enables you to track changes in
your programming code. This enables you to determine
changes that were made to the source code, when, and
by whom. This helps to organize the code, and enables
you to retrieve previous versions.
Why are two installations of Visual SourceSafe
available in Visual C++ 6.0?
There is a client and a server installation of VSS
available in Visual Studio. The client installation allows
developers to access a master source code control
database, whereas the server installation installs this
centralized database and administration tools.
New Page 6
I want more than one developer to be able to edit a
project file. How can I set VSS to allow multiple files to
be checked out?
On the General tab of Options in the Visual SourceSafe
Administrator tool, ensure that the Allow multiple check
outs check box is selected.
What are resource editors? Resource editors are interfaces used to view resources
included in a project. They allow you to view, add,
delete, and modify a number of different resources
associated with a project.
What is the purpose of the Gallery? The Gallery contains reusable components and controls
that can be added to your project. It also provides a
storehouse for source code that you want to reuse in
other projects.
Certification Summary
Source code control refers to tracking changes in the program code that developers have written. This gives a development team or single
developer the ability to view such things as the history of source code, when changes took place, who modified the code, and so forth. If the
source code has been saved to a control systems database, then developers can restore old versions of source code. This protects their work
against bad modifications to source code, or corruption of the original files.
Visual SourceSafe is a source code control system that conforms to the Microsoft Source Code Control Interface. As such, once installed, you
can interact with Visual SourceSafe through Visual C++ 6.0, or through the tools included with VSS. Visual SourceSafe Administrator is used
to administer VSS databases and users who will use these databases. Visual SourceSafe Explorer allows you to work with projects through an
interface similar to that of Windows Explorer. Together, they provide a powerful system of controlling source code.
Visual C++ 6.0 comes with a number of wizards that aid you in creating new applications, controls, classes, and so forth. In using the wizards,
you follow the instructions on each screen. By the end of these steps, Visual C++ 6.0 generates the source code files that you need to add
application-specific code.
Resource editors are interfaces that allow you to view and modify information contained in resource files of your project. They are similar in
appearance, making all of them easy to use once one of them is mastered. By using these editors, you can create new resources, and modify or
delete existing ones.
The Gallery is a folder thats installed when you install Visual C++ 6.0 on your system. It contains two folders when installed: Visual C++
components and Registered ActiveX controls. These folders respectively contain prepackaged components and ActiveX controls, which can
be inserted into your projects. You can also add source code, controls, and components of your own making to the Gallery. This enables you
to reuse code that youve written.
There are a number of information resources available from Microsoft. This includes online user assistance, resource kits, MSDN, TechNet,
and Web sites. Such sources of information may include technical papers, updates, a knowledge base of information, sample code, product
and SDK documentation, technical documents, examples, and so on.
Two-Minute Drill
The Gallery contains prepackaged components and registered ActiveX controls that can be added to your projects. A project is a
collection of files that make up your application.
Source code is the programming code you write, which makes your program actually do things (that is, make calculations, open and
close files, display data, and various other operations).
Tracking changes to source code during software development enables you to see what work has been done and who has done it.
Tracking changes helps you analyze how those changes have affected the project as a whole.
The Microsoft Source Code Control Interface provides a method for source code control systems such as Visual SourceSafe to integrate
with the Visual C++ environment.
The commands associated with source code control dont appear until a source code control system is installed.
The menu items and the Options dialog box in Visual C++ 6.0 dont provide complete control over the source code control system.
Visual SourceSafe (VSS) is a source code control system, which allows developers to save copies of their source code to a database.
When a file is added to VSS, that file is stored in the VSS database.
The first step toward using Visual SourceSafe 6.0 is installing it. The Visual Studio installation CD-ROM comes with two setup options
for VSS: Visual SourceSafe Client installation, and Visual SourceSafe Server installation.
The client installation can be installed at the same time you install Visual C++ 6.0.
The Visual SourceSafe server installation is used to install a source code control database that stores versions of source code. It also
installs an administration application that will enable you to control who can access the source code files stored in the database and control
who can perform administration tasks.
Its important that you understand what resides in each of the folders created by VSS during installation. This will allow you to quickly
find applications and files needed when administrating VSS.
Remember that of the folders created in client and server installations of VSS, the \Win32 and \Setup folders are common to each. The
\Win32 directory contains tools needed to use VSS effectively, while \Setup is used for installing additional components or removing VSS
from a system.
After Visual Studio has been installed, you can still perform a Visual SourceSafe Client installation by using the Visual Studio
Installation Wizard. In doing so, Visual C++ 6.0 and other development systems previously installed through Visual Studio will become
integrated with the source code control system.
After Visual C++ 6.0 has been installed onto a computer, you can also add and remove different Visual Studio products with the
Add/Remove Programs applet found in the Windows Control Panel.
Although installing the Visual SourceSafe Client from a CD-ROM is effective, it is not the only way of performing an installation. There
New Page 6
is also the NetSetup method of installing the client portion. This is generally the recommended method of installing the VSS Client software,
as it allows users to install NetSetup over the network themselves.
Since NetSetup is the recommended method of installing Visual SourceSafe Client software, you should be especially familiar with this
client installation type. Key points to remember are that NetSetup only installs the client portion, its run from the folder containing VSS
Server, no installation CD-ROM is required, and that users themselves can install VSS Client without administrator assistance. However,
because it uses the installation files in VSS Server, and NetSetup is installed with VSS Server, this means that you must first install VSS
Server before you can run NetSetup.
Once youve installed Visual SourceSafe, you will still need to configure it, and create a list of users who will be able to use the source
code control system. This is done through the Admin program, which is formally called Visual SourceSafe Administrator.
Until you actually open or create a project in Visual C++ 6.0, the only menu item in the Source control submenu is the one called
SourceSafe. Clicking this menu item opens the Visual SourceSafe Explorer. This application is similar to Windows or NT Explorer, except
that you use the VSS Explorer to browse and work with projects and files saved to the VSS database.
The SourceSafe menu is where we begin to see menu commands that appear in the Source control submenu of Visual C++ 6.0s Project
menu.
Until the Allow multiple check outs check box is selected, only one user at a time can check out a file from the VSS database. Allow
multiple check outs is found under the General tab of Options in the VSS Administrator.
The version control in Visual SourceSafe helps to ensure that only one person at a time is modifying a file. Unless Allow multiple check
outs has been selected, only one developer has the ability to check out and modify a file.
The way that Visual SourceSafe tracks different versions of files and projects is with version numbers, labels, and date/time stamps.
MFC is an acronym for the Microsoft Foundation Class Library. MFC provides the foundation for building a good application. It
provides you with commonly used code for such things as dialog boxes, menus, basic input/output, and many other things.
The MFC AppWizard comes in two forms. One creates an executable program with the extension of .EXE, while the other is used to
create dynamic link libraries with the extension of .DLL.
Until you name your project, the OK button on the New project dialog box will be disabled. You must name your project before you can
start any of the wizards or project types listed.
A resource editor is an interface that allows you to view and modify information contained in resource files of your project. They can be
used to create new resources, and modify or delete existing ones.
The Gallery is a folder on the hard disk where you installed Visual C++ 6.0 that contains source code. Basically, the Gallery is a
storehouse of reusable code.
You can use Windows Explorer to add additional folders to the Gallery folder. You can also use it to copy additional components,
controls, and source code to the Gallery for future use. Using Visual C++ 6.0, you can also use the Save As command on the File menu to
save source code files, components, controls, and so forth to the Gallery folder.
MSDN is the Microsoft Developer Network, and serves as a comprehensive source of information. It includes a knowledge base of
information, product and software development kit (SDK) documentation, technical documents, examples, sample code, and more.
TechNet is a technical reference source that is available through paid subscription from Microsoft.
New Page 6
Chapter 3: The Physical Design
Certification Objectives. 2
Documents. 4
Views. 4
Document Templates. 5
Frame Windows. 5
Thread Objects. 5
Application Object 5
Developing an MFC Application for Microsoft Windows 95/98/NT. 7
Using the MFC Framework. 10
Using Platform SDK for an MFC Application. 10
MFC Regular DLL. 12
MFC Extension DLL. 12
SDI 14
MDI 16
Non-Document/View Architecture. 17
Components. 19
Drawing. 19
Colors. 20
Text Drawing. 21
Mapping. 22
From the Classroom.. 24
Priorities. 27
Synchronization. 28
Incorporating a Database into the Application. 30
Types of Libraries. 30
Types of Objects. 31
From the Classroom.. 33
Properties. 35
Methods. 36
Events. 37
Certification Summary. 38
Two-Minute Drill 39
Answers to Exercise 3-3. 42
Answers to Exercise 3-5. 43
Answers to Exercise 3-6. 43
Answers to Exercise 3-7. 43
Certification Objectives
Elements of an Application Based on the MFC Framework
Platform SDK
DLLs
Chapter 03: The Physical Design
Routing Command Messages between a User Interface Object and a Handler Function
Document/View Architecture
MFC Drawing Architecture
MFC Printing and Print Preview Architecture
MFC Architecture and Multithreading
Accessing a Database
Properties, Methods, and Events of Components
Prior to the introduction of the Microsoft Foundation Class (MFC) Library, all Windows-based applications were created using the
Windows Application Programming Interface (API), (Win16 API). The Windows API is a set of functions and data structures written in
C that was used to interact with the Windows operating system. Programming application in Windows API was extremely complex. The
easiest tasks required several hundred lines of code. With MFC, the same tasks can be written in a few lines.
Since the introduction of the Microsoft Foundation Class (MFC) Library, developers have learned that using MFC will makes
Windows-based application development much easier. MFC functions as a thin layer over the Win32 API so developers can access the
Windows API with easy to use objects instead of calling the complex API functions. In order to be successful in Windows-based
programming with Visual C++, you must be familiar with every aspect of MFC, including the physical design, which we would talk
about in this chapter.
Elements of an Application Based on the MFC Framework
MFC is a set of prebuilt C++ components that are interfaces to Microsoft Windows. These reusable components encapsulate all the
common functions so that developers do not have to redevelop them every time. By using MFC, developers can greatly speed up their
development time. Another benefit of using MFC is that its included optional architecture simplifies development. Developers will have
a common location to add application-specific code in their application. Regardless of how an application is designed and structured, all
MFC applications have the same common elements: the documents, the views, the frame windows, the document templates, the
application object, and the thread objects. Please note that architecture included in MFC, such as the document/view architecture, does
not have to be used.
On The Job: Try to use MFC as much as possible. It greatly simplifies the coding process.
Documents
The document, specified by the document class, manages your applications data. The document is derived from the CDocument class.
The document object provides functions that other objects can use to access the data. The important functions within the document
object are as follows:
GetFirstViewPositionReturns the position of the first view to allow GetNextView to enumerate the views of the document
GetNextViewReturns a CView pointer to the next view in the view list of this document object
GetPathNameReturns path and filename of the document
GetTitleReturns the documents title
IsModifiedReturns nonzero if document has unsaved data and zero if it doesnt
SetModifiedFlagCan set or reset documents modified flag.
UpdateAllViewsUpdates all the views associated with this document
Views
The view object determines how the user sees and interacts with the documents data. MFC allows you to open multiple views of the
same data with a multiple-document interface (MDI) application, which we will talk about later in this chapter. An easy way to think of
a view is that the view is just a specific representation of the document. Each document can have multiple views.
The view object is derived from the view class. The view class shows the data on the document and it relies on the surrounding frame
windows for the basic windows functionalities, such as moving and resizing. The view class is derived from the CView class or a
CView-derived class and it handles the user interaction that affects the view.
Document Templates
The document template is in charge of linking your applications documents, views, and frame windows, which allows them to function
as one entity. You can create single-document or multiple-document templates, which the developer can use to create single-document
interface (SDI) and MDI applications.
Frame Windows
The frame windows host the applications view windows. The applications main frame window specifies the characteristics of the
frame windows that contain these views.
Chapter 03: The Physical Design
Thread Objects
A thread is the most basic unit of execution in a Windows-based application. If your application is multithreaded, you can create
multiple threads with the classes derived from CWinThread.
Application Object
The application object, derived from CWinApp, is the backbone of all MFC applications. It manages the start, the execution, and the
termination of an application by encapsulating the Win32 WinMain() function. The application object is also responsible for creating the
main frame window, which is where the user interfaces with the application. This object provides access to the following crucial
member functions of the CWinApp class function that dictate the execution of the application:
InitInstance()
Run()
OnIdle()
ExitInstance()
InitInstance() Member Function
The InitInstance() is the most important member function in the application object. This function initializes every instance of the
application that is executed. It is very common to override the InitInstance() member function in the classes of your application. Many
developers do it but are not required to do so.
Run() Member Function
The Run() function is responsible for sitting in a message loop waiting for and processing incoming messages. Once it receives
messages, it will send them to the main frame window of the application. When no messages are available to process, Run() will call the
OnIdle() member function to idle. When termination of the program is requested, the Run() member function will run the ExitInstance()
member function.
OnIdle() Member Function
The OnIdle() member function is used by the application object for idle processing. You are able to override the OnIdle() to perform
other background tasks. The default version updates the user interface element states.
ExitInstance() Member Function
The ExitInstance() member function is called when an instance of an application is terminated. This function is called by Run(), usually
when the user has requested that the instance of the application be closed. You usually would override the ExitInstance() member
function to clean up standard objects such as frame windows or views.
Developing an MFC Application for Microsoft Windows 95/98/NT
Windows 95, Windows 98, and Windows NT are Microsofts 32-bit operating systems. Because they all use the Win32 API and have
similar shells, most applications should work the same. However there are always some applications that developers find that work fine
on Windows 95/98, but encounter problems when running Windows NT. Some of these problems may be caused by not following the
proper API calling rules and conventions, misinterpreting the operating system platform, replacing system dynamic link libraries (DLLs)
with versions for the wrong platform, or simply bad coding.
However, not all malfunctioning applications are the fault of the developer. Windows 95/98 and Windows NT are different operating
systems. Windows NT enforces permissions and rights. Windows NT is also a Unicode operating system. In order for you to
successfully develop cross-platform Windows applications, you need to follow a few guidelines to minimize problems when developing
programs that are going to run on Windows 95/98 and Windows NT. Exercise 3-1 will show you a checklist so you will be able to
review the things to watch for when you develop on Windows 95/98/NT.
Versioning
Applications use either GetVersion or GetVersionEx to get the operating system platform, version, and build information. Some
applications encounter problems over their incorrect use of GetVersion. GetVersion returns two platform bits as well as the version
number. Because many applications only check for the operating system version number, and because Windows 95/98/NT all return 4 as
the version number, the application ends up calling Windows 95-specific calls to the Kernel32.dll. The same calls are not available on
Windows NT, so the Windows NT application ends up failing. Other times, applications only check for the two platform bits but will
end up misinterpreting the version of the operating system. In order for you to avoid these problems when using GetVersion, you should
get the two return bits as well as the version number or use GetVersionEx. GetVersionEx is the new version of GetVersion and is the
preferred method of acquiring version information from the operating system. GetVersionEx returns versioning information in an
OSVERSION structure that is less cryptic than the DWORD bits in GetVersion.
DLLs
Not all required DLLs exist on the users computer. An application should check to see if they are available. If they are not, it should be
prepared to install them. If the application detects an older version of a required DLL, users should be prompted to decide whether they
want to overwrite it or leave it as is. This is good practice because the user might not want his or her current version of the DLL to be
overwritten.
Chapter 03: The Physical Design
The application should check the operating system version. It is possible that the application will install a DLL from the incorrect
platform and this can cause many applications that access that DLL to function incorrectly. Applications must use refcount to maintain
the count on the DLLs that exist on the system. MFC and system DLLs should never be removed.
Security
Windows NT is a secure operating system and all applications that are being installed inherit the rights of the current user. Because the
application has the same rights as the user, some problems many arise when the current user does not have enough privileges for the
application to install critical files or write to the registry. To avoid problems like this, inform the user that he or she must have sufficient
privileges in order to install the application.
Exam Watch: The main difference between Windows 95/98 and Windows NT is security. Developers must keep this in mind when they
are designing programs that run on both platforms.
Large Drives
The creation of the FAT32 file system has caused some applications to display incorrect drive size information during installation with
drives larger than 2GB. The GetDiskFreeSpace API function, which returns the free space of the drive, caused many applications to fail
because it doesnt return the correct free space on a 2+ GB drive. If this is a big issue, you can use the updated API function
GetDiskFreeSpaceEx instead of the older GetDiskFreeSpace.
Hard-Coded Paths
API functions are available to start the operating systems executable files. Some developers choose to hard-code the path of the
executable rather than to use the API calls. Applications that have hard-coded paths can run into problems because executables are
stored in different paths on different operating systems. Sometimes the executables will change their implementation so that calling them
explicitly will not work.
Another problem with hard-coded paths is with the Registry. Keys are not necessarily in the same location on all platforms. In order to
ensure that your application will work in all platforms, substitute all hard-coded operating system executable calls and Registry keys
with API calls.
ANSI vs. Unicode
Because Windows NT is a Unicode operating system, all internal routines use Unicode character handling. Windows 95/98 uses
American National Standards Institute (ANSI) standards for internal routine character handling. In ensuring that an application is
Unicode-ready, it must be able to identify the operating system and use the ANSI or wide function calls (for Unicode) when necessary.
Exercise 3-1 Windows 95/98/NT Applications Development Differences Checklist
1. Ensure that you are retrieving the correct version of your Windows-based application by ensuring that you are returning the correct
variables, such as platform, build, and version with GetVersion and GetVersionEx.
2. Check to see if necessary DLLs are available.
3. If Windows NT is detected, be sure to tell users that when applications are installed they must have sufficient rights and privileges
to install the program.
4. The most accurate method to return the computers free space is to use GetDiskFreeSpaceEx.
5. Use API calls instead of hard-coding calls to an executable or to access keys within the Registry.
Platform SDK
Prior to MFC, the main way to write Windows-based applications was to do it with the Platform software development kit (SDK). By
using the SDK, you are essentially writing programs with the Win32 API. Though MFC makes Windows-based programming much
easier, it is not always the best way to create your applications.
Using the MFC Framework
MFC is more than a class library. The MFC is also an application framework that defines the structure of the application. The framework
encapsulates and handles many routine tasks for you. These abstractions are much more convenient and shield away many of the
nuances that Win32 API programmers face. An example of this is the document/view architecture. If the desired class or function is
available in MFC and it is sufficient, you should use the MFC framework.
Using Platform SDK for an MFC Application
With all the advantages surrounding using the MFC and its application framework, why would anybody want to use the Platform
software development kit (SDK), when its more difficult to use and it does not offer the abstractions that the MFC offers? MFC is a
C++ class library that is a wrapper around the Win32 API. The newest version, MFC 6.0, has about 200 classes available to it. Although
MFC could provide all of what you need, it also might not. Not everything available in the Win32 API is encapsulated in MFCone
example is the list control. Sometimes with extremely complex applications, you may need to mix your MFC application with some raw
Win32 API code. The only way to find out what you need is to gain some experience with MFC so that you understand its strengths and
weaknesses. Only then are you able to know when to use MFC by itself, or an MFC/Win32 API hybrid. Exercise 3-2 is a checklist that
allows you to review what you should have in mind when choosing between the Platform SDK and the MFC.
Exercise 3-2 Checklist for Choosing between the Platform SDK and the Application Framework
Chapter 03: The Physical Design
Company X is designing an MFC application. Here are the steps that a consultant will use to decide whether to choose the Platform SDK
or the MFC application framework.
1. If the functionality completely exists in MFC, then use MFC.
2. If the functionality is somewhat supported in MFC, then use MFC and the Platform SDK. Remember, MFC should always be your
primary choice to develop a Windows-based application as long as the functionality exists and is complete. If it does not, use as much of
MFC as possible and use the Platform SDK for the features that are not complete.
3. If the functionality is not supported in MFC, then use Platform SDK.
DLLs
Libraries are sets of compiled code that are included within an application at compile time. With DLL, or dynamic link libraries, the
libraries are linked at run-time, hence the name dynamic link libraries. DLLs are a lot more flexible, because you can update the libraries
without recompiling the entire application. AppWizard lets you create two types of DLLs that support the MFC library: MFC regular
DLLs and MFC extension DLLs. DLLs are similar to the static libraries that you encountered when you were dealing with C++. By
being able to link to the MFC library, your application is able to access the MFC methods and classes without having to duplicate the
object code within the API. With DLLs, code can be shared, which saves memory and space requirements.
MFC Regular DLL
An MFC regular DLL can use C++ classes, but it can only export C functions. If you need a DLL that can be loaded in any Win32
programming environment, you should use a regular DLL. With the MFC regular DLLs, you can choose to either dynamically or
statically link to the MFC library. With the statically linked library, a copy of the MFC library is included so that the DLL is
independently contained. With the dynamically linked library, the DLL is much smaller.
MFC Extension DLL
The MFC extension DLL can export entire MFC classes, MFC derived classes, C++ classes, member functions, and overloaded
functions. The client can create objects based on or derived from these classes and functions. The extension DLL can dynamically link to
the code in the MFC librarys DLL. Thus, the client program must be dynamically linked to the MFC library and the client program and
the extension DLL must be synchronized to the same version of the MFC DLLs. Because the client program is dynamically linked to the
MFC library, the DLLs are much smaller than regular, statically-linked DLLs. The MFC extension DLL can only be used with C++
compilers, such as Microsoft Visual C++ or Borland C++. Exercise 3-3 helps you to choose between the MFC extension and regular
DLL.
Exercise 3-3 Match the platform to the correct usage of the MFC Extension DLL and the MFC Regular DLL
Identify whether the platforms in the left column use the MFC extension DLL or the MFC regular DLL. (The answers to this exercise
appear just before the Self Test at the end of this chapter.)
Platform MFC extension or regular DLL?
Visual Basic
Visual C++
Visual J++
Borland C++
Symantec C++
Routing Command Messages between a User Interface Object and a Handler Function
Messages play a great role in Windows-based applications. Messages are created from a variety of actions, such as a mouse-click on a
menu item or by accelerator keystrokes. Command messages are messages that can be handled by many different objects, such as the
application, the documents, and the windows. Every object, which is capable of receiving command messages, has its own message map.
Each command message is identified by a constant that is assigned by a resource editor. When the object receives the command
message, it looks at its own message maps for a match. If it cant find the handler, it will route the command to the next object.
The handling order for SDI is as follows:
View
Document
Main Frame
Application
The handling order for MDI is as follows:
View
Document
Child Frame
Main Frame
Application
The application will go first to the class to which the message belongs. If it does not find a match, it will go down the list until it finds
the proper handlers. If there are multiple handlers, the handler at the higher level will be called.
Chapter 03: The Physical Design
Document/View Architecture
The document/view architecture is the core of the MFC application framework. In a document/view application, the data, also known as
the document, is managed separately from the application through which the users interact with the data. This allows the data to be
encapsulated by the way that the data is shown and the way that the user inputs it. The data and the code are separated. There are two
application types that have the document/view architecture: single-document interface and multiple-document interface.
SDI
The simplest application type that has the document/view architecture is the single-document interface (SDI). In an SDI application,
only one document is open at a time. An example of this is Notepad, as shown in Figure 3-1.
Figure 1: There can be only one document open at a time in an SDI application
Four classes make up SDI:
CWinApp
CFrameView
CDocument
CView
CwinApp creates all the applications components. Another main task is to receive all the event messages and to pass them to the
CFrameView and the CView.
CFrameView is the window frame that holds all the components that you see on the frame such as the toolbar, the menu, and the
scrollbar.
The CDocument class stores and manages your documents data, such as saving and retrieving information.
CView gets information from the CDocument class and it outputs the desired information for the user. This enables the user to interact
with the data that is managed by the Cdocument-derived class.
MDI
The multiple-document interface (MDI) is similar to the SDI application except that it allows the user to have multiple documents open
at the same time. Each document could consist of a different file, or of the same file but of a different view, such as a Microsoft Excel
spreadsheet and a pie chart based on the data from the Microsoft Excel spreadsheet, as shown in Figure 3-2.
Chapter 03: The Physical Design
Figure 2: MDI applications allow the user to have multiple documents open at the same time
Five classes make up an MDI application
CwinApp
CMDIFrameWnd
CMDIChildWnd
Cdocument
Cview
MDI contains all the same classes as an SDI application, except for the CframeView. Instead, the MDI has the CMDIFrameWnd and
CMDIChildWnd. The CMDIFrameWnd is the main frame of the application, where all interactions with the user take place. The
CMDIChildWnd class holds the CView class and it passes all messages and events to the Cview class. This class makes the access to
multiple documents possible, and this is where all the multi-document files are defined.
Non-Document/View Architecture
Although most of the applications that you will develop probably will use the document/view architecture, you can also develop
applications that do not use it. The document/architecture has many benefits, but the included disadvantages might make you decide not
to use it. For example, an application that does not show any documents does not need a main frame window or a view, such as the
Windows Sound Recorder shown in Figure 3-3.
Figure 3: The Sound Recorder is an example of a dialog-based application
A sample non-document/view architecture can contain the following:
An object based on the CWinApp class and a modal dialog box. This application is also called the dialog-based application
architecture. The dialog box will be the primary source for manipulating data.
An object based on the CWinApp object, a main frame (CFrameWnd) window, and a view. In this type of application, the view
will manipulate the data.
Chapter 03: The Physical Design
In the non-document/view application, you must override the CWinApp::InitInstance function to create the windows and the dialog
boxes. Exercise 3-4 will go over the things that you should remember when designing the interface of your application.
Exercise 3-4 Checklist for Using the Document/View Architecture
If your application does not need a main frame window or view, dont use the document/view architecture at all. Use a
dialog-based application.
If you need different views of your document or you need to have several documents open, use MDI.
If only one document needs to be open at a time, use SDI.
MFC Drawing Architecture
The drawing capabilities of MFC center on the Windows Graphical Device Interface (GDI). The GDI provides all the services needed to
draw in Windows. Prior to the GDI, programmers had to write program graphics to the video hardware and video standard.
Programming graphics was extremely frustrating because every new hardware device or standard had programmers scrambling to
support it. This all changed with the introduction of the GDI, which is a part of the hardware-independent graphics output model.
Programmers write to the GDI, and the GDI worries about interpreting the code to the hardware. This model frees up the programmer so
he or she can worry about graphics programming.
Whenever the Windows-based application needs to draw to a device, it accesses it through the device context. The device context (DC)
is a virtual desktop service that represents the device drawing surface. When you use MFC, you create a device context object and call
its member functions to do the drawing for you.
Components
The graphic components that MFC supports are as follows:
PensUsed to draw lines and curves
BrushesUsed to paint the interior of polygons and ellipses
PalettesSet of colors used by GDI to render an image
BitmapsGraphical image
FontsDefines the style of text being displayed
Drawing
The MFC CDC class encapsulates the device context, as well as the GDI function. The CDC functions for drawing lines, curves, and
closed figures are as follows:
MoveToSets the current position
LineToDraws a line from the current position to the defined position
PolylineConnects a set of defined points
PolylineToConnects a set of points from the current position to a set of defined points
ArcDraws an arc
ArcToDraws an arc and updates the current position to the end of the arc
PolyBezierDraws Bezier splines
PolyBezierToDraws Bezier splines and updates the current position to the end of the Bezier spline
PolyDrawDraws lines and Bezier splines and updates the current position to the last line or Bezier spline
ChordDraws a chord, an intersection of an ellipse and a line
EllipseDraws an ellipse
PieDraws a pie wedge
PolygonConnects a set of points to form a polygon
RectangleConnects a set of points to form a rectangle
RoundRectDraws a rectangle with rounded corners
Colors
You can set and manipulate colors by using the COLORREF value. COLORREF uses the red-green-blue (RGB) system, which uses the
intensity of three colors: red, green, and blue, to specify each color. To set the COLORREF value, you use the RGB macro. The RGB
macro takes three parameters: the intensities of red, green, and blue. You can set the colors with numbers in the range of 0 to 255. Table
3-1 shows the RGB values for the most common colors.
Color Red Value Green Value Blue Value
Black 0 0 0
Blue 0 0 255
Chapter 03: The Physical Design
Green 0 255 0
Cyan 0 255 255
Red 255 0 0
Magenta 255 0 255
Yellow 255 255 0
White 255 255 255
Dark gray 128 128 128
Light gray 192 192 192
Table 3-1: RGB Values for Common Colors
Text Drawing
Unlike drawing lines, to draw text you must first set the attributes to the text and then write it out to the device. The following is a list of
the main functions that control text-display attributes:
SetTextColor and GetTextColorThese control the color of the text displayed.
SetBkMode and GetBkModeThese functions control whether or not the cells that surround each letter are filled before the
corresponding characters are displayed. In Opaque mode, the cells are filled with the current background color. In Transparent mode, no
fill takes place.
SetBkColor and GetBkColorFunctions that control the color of the cells that contain the displayed text. The background mode
must be Opaque before this attribute is used in a fill.
SetTextAlign and GetTextAlignThese control the alignment of text relative to the window position specified in one of the
text-output functions.
The following is a list of functions that control text output:
TextOutDisplays a text string at the given location by using the currently selected font, colors, and alignment.
TabbedTextOutSimilar to TextOut, but supports expansion of tab stops.
DrawTextDisplays formatted text within a bounding rectangle.
ExtTextOutSimilar to TextOut, but allows specification of clipping options.
Mapping
In windows, the GDI translates logical coordinates to physical coordinates using the different mapping modes. You can set the mapping
modes with the SetMapMode device context function. By setting the different mapping modes, you control how the objects and the
coordinates are translated to the screen. Windows supports eight mapping modes.
MM_ISOTROPICLogical units are converted into random units with equally scaled axes.
MM_ANISOTROPICLogical units are converted into random units with random axes.
MM_HIENGLISHEach logical unit is converted to 0.001 inch. Positive X is on the right, positive Y is up.
MM_LOENGLISHEach logical unit is converted to 0.01 inch. Positive X is on the right, positive Y is up.
MM_HIMETRICEach logical unit is converted to 0.01 mm. Positive X is on the right, positive Y is up.
MM_LOMETRICEach logical unit is converted to 0.1 mm. Positive X is on the right, positive Y is up.
MM_TEXTEach logical unit is converted to 1 pixel. Positive X is on the right, positive Y is down.
MM_TWIPSEach logical unit is converted to 1/20 of a point. Positive X is on the right, positive Y is up.
MFC Printing and Print Preview Architecture
Like drawing, printing was a headache prior to Windows. The application had to be coded to deal with the many different print drivers.
With Windows, this process was streamlined in that the application printed to the GDI. To print without MFC, the application had to get
a device context to the printer and then call the StartDoc Win32 API function, which would start the print job. At every start in a page in
a document the StartPage function would be run. At every end in the page, the EndPage would run. This would loop until there were no
more pages to be printed. Then the EndDoc function would be called. This process is greatly simplified with MFC. With MFC, the
printer device context is automatically created and destroyed and the StartDoc, StartPage, EndPage, and EndDoc functions are called
automatically for you by using member functions in the Cview class. The necessary MFC functions that you should be familiar with are
as follows:
OnPreparePrintingThis is called prior to any printing or previewing.
DoPreparePrintingDisplays the Print dialog box and creates the printer device context. You set the maximum page count here.
OnBeginPrintingThis is called when the print job starts. You can overwrite this function to create resources that you need for
printing, such as fonts. You set the maximum page count here also.
OnPrepareDCThis is called before any drawing starts to prepare the device context. Override this function to modify the device
context, such as pagination.
OnDrawThis function displays the images you see in the print preview window as well as how it would appear on the printer.
Chapter 03: The Physical Design
OnPrintThe function that is called for printing or print preview. Override this function to provide additional printing features,
such as headers and footers.
OneEndPrintPreviewThis is called when print preview mode is exited.
OnEndPrintingThe function that is called when the print job is finished. You must override this function to release any resources
that you created.
Exam Watch: The most common print function to override is the OnPrint function. You must override this function to print more
standard features such as footers and headers.
Print preview is much different that printing. With print preview, the application simulates the printing of a document onto the screen.
This is done with the CDC derived class, CpreviewDC. When print preview is selected, the CpreviewDC object is created. You can
modify print preview so you can get a scrollbar, to maintain the users original position, and cause print preview to output specially
formatted page numbers. Exercise 3-5 will help you become more familiar with the print and print preview architecture in MFC.
Exercise 3-5 MFC Print and Print Preview Architecture
Based on the following scenarios, choose the MFC function that you need to override. (The answers to this exercise appear just before
the Self Test at the end of this chapter.)
1. You would like to have customized headers and footers.
2. You want to modify the device context.
3. You want to set the maximum page count.
4. After creating objects, you need to overload this function to release the resources created by your objects.
From the Classroom
MFC Printing Support
As discussed in this section, MFC adds printing support through member functions in the CView class. The most important of these
member functions are OnPreparePrinting, DoPreparePrinting, OnBeginPrinting, OnPrepareDC, OnDraw, OnPrint, OnEndPrintPreview,
and OnEndPrinting. With these functions you can perform all of the tasks necessary to include print and print preview capabilities in
your application. There are, however, a couple of other handy printing features built into the CView and CWnd classes that make
dealing with printers and print jobs very simple. Specifically, let's look at how to obtain information about the default printer, and how to
obtain information about the current print job.
There are two methods to find out default printer settings. You choose the method to use based on when the information needs to be
known by your application. If your application needs to know about the default printer on startup, you will need to override the
InitInstance member function of the application object derived from CWinApp. In InitInstance, call GetPrinterDeviceDefaults, which
gives you a reference to a PRINTDLG object, then call CreatePrinterDC, which gives you a reference to an object containing default
printer characteristics. This could be accomplished with code such as the following:
PRINTDLG pdialog;
GetPrinterDeviceDefaults(&pdialog);
CDC defaultCharacteristics;
if (CreatePrinterDC(dc) != 0)
{
//get default characteristics
}
If you need to get the default printer setting some time following application startup, or to monitor any changes made to the default
printer, you need to implement the OnWinIniChange member function of the main window class in your application. This method is a
member function of the CWnd class that provides the base functionality of all window classes in the Microsoft Foundation Class
Library.
You may also want to find out information about the printer's current print job. You can do this by using the pInfo parameter that is
passed to the CView member functions. The pInfo parameter of the CView:OnXxxx functions contains a pointer to an object named
CPrintInfo. Information about the print job is contained in the CPrintInfo object and accessed using its class members.
The MFC is a valuable tool for building Windows applications, and it has made one of the messiest tasks of application
developmentprintingseem almost trivial. We have only pointed out some of the major printing features in the MFC, but by no
means have we shown all of the printing support built into the Microsoft Foundation Classes. To find out more about these features, try
searching on the classes, objects, and member functions we have looked at in this section using MSDN, either on-line, through your
subscription, or on the MSDN CD provided with Microsoft Visual Studio.
Michael Lane Thomas, MCSE+I, MCSD, MCT, MCP+SB, MSS, A+
MFC Architecture and Multithreading
MFC supports multitasking through its threading model. Thread-based multitasking allows users to run more than one instance of a
program as well as run different tasks in a single application. This is similar to running subapplications within a single application. An
example of this is running a spell checker while you are typing a document. A thread is the basic unit of execution. With thread-based
multitasking, the developer can fully control the way the application executes. MFC has two types of threads: the interface thread and
Chapter 03: The Physical Design
the worker thread. An interface thread can receive and process messages. A worker thread does not receive or process messages, it just
provides additional paths of execution for the main thread. The user interface can create windows and process messages sent to those
windows. MFC supports multithreading with the CWinThread. The main thread of an executable is always an interface thread. The main
thread can spawn additional worker threads that will facilitate multithreading. You create a worker thread with the function
AfxBeginThread. You terminate the thread with AfxEndThread. You suspend a thread, or pause the execution of a thread, with the
CWinThread::SuspendThread() function. You can resume a suspended thread with CWinThread::ResumeThread.
Priorities
Every process has a priority class assigned to it. The priority is used to help determine how much central processing unit (CPU) time that
the process has access to. Processes that are crucial have higher priority than lower priority ones. The different priority classes are
REALTIME_PRIORITY_CLASS
HIGH_PRIORITY_CLASS
NORMAL_PRIORITY_CLASS
IDLE_PRIORITY_CLASS
By default, programs are given the normal priority class. You need to be cautious with assigning the correct priority class. Assigning an
applications priority class to real time can hog the entire CPU and slow down or halt execution of other threads. High priority class is
set when you need priority higher than normal but the program is not crucial to the system. The default priority class is the normal
priority class. Set applications to the idle priority class when you need the application to run only when no other applications are waiting
for the CPU. You can set the priority with the function SetPriorityClass(). You can return the current priority with GetPriorityClass().
You can also set the priority of the individual threads within a process. You use GetThreadPriority() and SetThreadPriority to do this.
The different priority settings are
THREAD_PRIORITY_TIME_CRITICAL
THREAD_PRIORITY_TIME_HIGHEST
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_IDLE
Synchronization
With multithreading, synchronization becomes a necessity when two or more threads need access to a shared resource that has a limit on
how many threads can access it. The prevention of one thread from accessing a resource that another thread currently is accessing is
called synchronization. The following classes encapsulate synchronization objects:
CCriticalSectionAllows only a section of code to be accessed at one time. This encapsulates the simplest type of thread object.
This is done with the CCriticalSection::Lock member function to lock the resource before it is used. CCriticalSection::Unlock unlocks
the resource after it is used.
CEventEvents can block a process from accessing a resource until another thread allows it. CEvent supports two types of events:
autoreset and manual reset. An autoreset event will automatically reset it itself after the resource is released. Manual reset forces the
developer to write code to release the resource. Autoreset events use SetEvent to trigger the event if it is one thread and they use
PulseEvent for two or more threads. ResetEvent is run automatically. With manual reset, the developer can check for the state of the
event with the m_hObject data member.
CMutexMutex is a combination of the words mutually and exclusive. It is used to gain exclusive access to a resource shared by
multiple threads, as well as to synchronize the threads running in the same process or in different processes. Like the CCriticalSection, it
uses the Lock and Unlock member functions to lock and free resources.
CSemaphoreA semaphore signals that a limited number of threads can access a resource. This is unlike the other synchronization
object classes. A semaphore uses a resource count to determine how many threads are accessing the resource simultaneously. Every time
the Lock member function is run, the resource count is incremented. When Unlock is run, the resource count is decremented. When the
count hits the resource maximum, Lock will lock the resource until the resource count goes below the threshold.
CSingleLockThis controls access to one synchronization object. You can use it to control a critical section, a mutex, an event, or a
semaphore.
CMultiLockControls access to multiple synchronization objects. This can control a critical section, a mutex, an event, or a
semaphore. The advantage of using CMultiLock is that it can block up to 64 synchronization objects at once, and it can block all of them
until one of them is free or until all of them are free.
Exercise 3-6 will help you choose the thread priority class when you are developing your application.
Exercise 3-6 Choosing the Thread Priority Class
Based on the following scenarios, choose the thread priority class that you should use. (The answers to this exercise appear just before
the Self Test at the end of this chapter.)
1. You want to do a background spell check.
Chapter 03: The Physical Design
2. You want to defragment your hard drive when the computer is idle.
3. You want to run a service critical to system operation.
4. You are creating a standard application.
Accessing a Database
As corporations depend more and more on databases, more applications are needed to access a database. Visual C++ provides many
technologies to allow access to databases in your applications. It supports Data Access Objects (DAO), Open Database Connectivity
(ODBC), OLE DB, and ActiveX Data Objects (ADO).
Incorporating a Database into the Application
In order for a database to be incorporated into the application, you will need to be able to access the database from your application.
Visual C++ contains all the components needed to create a database application. This can be done with the available libraries and
database objects included in Visual C++.
Types of Libraries
You can access database objects through libraries included in Visual C++, such as MFC, the Active Template Library (ATL), and the
Platform SDK.
MFC
In order to use the MFC library for databases, you must use ODBC or DAO. With the MFC library for ODBC, you can access any
database that has an ODBC driver. With MFC ODBC, you can use objects instead of using connection handles and statement handles.
MFC DAO is a set of Component Object Model (COM) interfaces. However, DAO only allows access to flat file databases, such as
Access. MFC DAO is the fastest way to access the flat file database.
ATL
The Active Template Library (ATL) is used to create lightweight controls based on COM. These controls are much smaller than MFC
and are extremely suitable for client/server applications. ATL is the way to develop applications if the functionality is to be used in
several applications. ATL will build controls that can be plugged into an application that will extend its functionality. However, ATL
can support OLE DB, which allows access to everything ODBC offers as well as access to other data sources, such as an Excel
spreadsheet. It must be noted that ATL does not support ODBC. Access to data must go through the OLE DB interface. Because OLE
DB is based on COM, data access is encapsulated and componentized. This is more efficient compared to traditional database access
because access is split into two components: the consumer and the producer. The consumer is the code that uses the OLE DB interface.
A provider exposes that interface. By splitting the access to the data, client-side resource overhead is much less. ATL provides templates
to make creating the two components much easier. For client/server applications, ATL is the ideal choice for accessing databases.
Platform SDK
Using the Platform SDK to access the database is the most powerful way to use databases, but also the most complex. You should use
the Platform SDK only if MFCs database classes and ATLs OLE DB are not sufficient to provide what you need.
Types of Objects
You access databases through different objects. There are pros and cons to each object.
ADO
Of all the different data objects available in Visual C++, ActiveX Data Objects (ADO) represents the future of database connectivity for
database developers. ADO is a wrapper around OLE DB, which was created to replace ODBC. Microsoft introduced OLE DB in an
effort to eliminate any bias to any data storage format. OLE DB allows a direct COM interface to the destination data source.
ODBC
Open Database Connectivity (ODBC) has been the most popular way for database developers to access any relational database. Its a
database interface standard that allows access with an ODBC driver. Though ODBC is currently very popular, Microsoft is pushing
developers to focus on ADO/OLE DB and wants it to be known that it is the proper way to access data stores.
RDO
Because using the ODBC API can be quite unwieldy, Microsoft introduced Remote Data Objects (RDO). RDO is a thin wrapper around
the ODBC API. RDO translates the manipulation of the data objects as well as their properties and methods and sends the appropriate
calls to the ODBC API. Because RDO has an object-type interface, it takes away a lot of the guesswork involved in connecting to an
ODBC data source. However RDO is not available in Visual C++. Exercise 3-7 will help you choose the correct database object and
library.
Exercise 3-7 Choosing Database Objects and Libraries
Based on the following scenarios, choose the database object or library that you should use. (The answers to this exercise appear just
before the Self Test at the end of this chapter.)
Chapter 03: The Physical Design
1. You want to do a client/server application. What library should you use?
2. You want to be able to access an Excel spreadsheet. What database object should you use?
3. You want to manipulate data in Access. What library should you use?
4. You are creating a standard database application. The database uses a standard ODBC driver. What database object should you
use?
From the Classroom
Unraveling the Variations in Microsoft Data Access Technologies
Almost all applications rely on the processing and maintenance of information, so one of the most important architectural decisions
made for an application is what method will be used to perform data access. Unfortunately, the various terms and acronyms associated
with using Microsoft technologies for data access are not always simple to remember or easy to keep straight. One topic I find myself
explaining over and over is defining the various data access methods and their associated acronyms. Since data access is such an
important topic, and there are so many terms floating around associated with Microsoft's data access technologies, let's go over them
again.
The first basic concept to understand is Open Database Connectivity (ODBC). ODBC is an international standard designed to allow
developers to access relational data using a similar syntax (SQL commands) regardless of the location and vendor of the database.
ODBC consists of two main pieces: ODBC Drivers and the ODBC Driver Manager. Drivers provide database management system
system-specific implementation of the ODBC interface specifications. The ODBC Driver Manager provides a means to set up and
manage connection settings for a driver to a specified data source.
The term DAO (Data Access Objects) is sometimes used to refer to all types of data access. It is important to remember the place of
Data Access Objects at the present time. DAO consists of a set of OLE automation classes that access data being stored in databases that
use the Microsoft Jet Database Engine, such as Access or FoxPro. The MFC DAO classes are easy to use and best suited for applications
that access desktop databases.
ActiveX Data Objects, or ADO, is the evolution of DAO. When using DAO, it is necessary to adhere strictly to the DAO object
hierarchy and create separate instances of the various classes in the hierarchy for each table or result set you need to access. ADO,
however, is much more flexible with fewer dependencies between the various objects in the ADO hierarchy. Another advantage ADO
has over DAO is that you are not limited to using it only with the Microsoft Jet Database Engine.
ADO accesses data from across an enterprise by providing a thin wrapper over OLE DB. Where as ADO is the evolution of DAO, OLE
DB can be thought of as the evolution of ODBC. Like ODBC, OLE DB provides access to multiple data sources, however, unlike
ODBC, OLE DB is not limited to only accessing relational data. An increasing number of OLE DB Providers are being made available,
and until all data sources can be accessed through OLE DB, there is an OLE DB Provider available for ODBC drivers.
OLE DB is the backbone of ADO, and Remote Data Service, or RDS, is an extension of ADO developed for client applications that
need to remotely use an ADO recordset using HTTP, HTTPS, or DCOM. RDS uses the Remote Data Object, RDO, on the client, and it
was mainly developed for use by VB and Internet developers. To use RDO in C++, it is necessary to embed the Remote Data Object in
your application.
Microsoft Data Access Components, or MDAC, encompass the four technologies of ADO, RDS, ODBC, and OLE DB, as well as the
Microsoft OLE DB Provider for ODBC. Another term used to refer to these data access technologies is Microsoft's Universal Data
Access. Read up on these technologies, and any new acronyms the data access developers come up with, on Microsoft's web site.
Knowing how each data access method works will help you pick the best access method for your application.
Michael Lane Thomas, MCSE+I, MCSD, MCT, MCP+SB, MSS, A+
Properties, Methods, and Events of Components
ActiveX controls are software components that can be attached to different programs, providing additional functionality. ActiveX brings
this type of plug and play interoperability to windows applications. Software components allowed only certain parts of an application
to be upgraded or replaced. ActiveX components are based on newer OLE (Object Link Embedding) and use the Component Object
Model. COM defines how components can interact seamlessly between each other.
Properties
A main feature of ActiveX controls is their ability to expose their properties using a primary dispatch interface. Through this dispatch
interface, an ActiveX control container can access the control as a resource. The properties of the control expose the attributes of the
control container to the container. There are two types of properties: stock and custom.
The stock properties are properties already implemented in the ColeControl-based class and cannot be altered. This is the common
functionality of the ActiveX control. There are nine stock properties:
AppearanceSets the control as flat or 3-d
BackColorSets the controls background color
BorderStyleSets the controls border style
CaptionSets the controls title
EnabledDetermines if the control is enabled
FontSets the controls current font
Chapter 03: The Physical Design
ForeColorSets the controls foreground color
hWndSets the controls window objects handle
TextSets the controls title
Sometimes the stock properties do not provide enough functionality. You may wish to introduce custom properties. For a custom
property, you must provide the declaration and the implementation. There are four types of implementation for a custom property:
Member VariableImplementation in which the member variable is exposed to a container
Member Variable with NotificationImplementation in which the member variable is exposed to a container and the control is
notified when there is a change in the property
Get/Set MethodsImplementation that calls a method that gets the current property value and a method that sets the property value
ParameterizedSame as the Get/Set methods implementation except it allows access to a group of values through a single property
Methods
ActiveX methods allow the client to perform functions on the control. Like properties, the methods are implemented by the primary
dispatch interface. There are two types of methods: stock and custom.
Stock methods are methods already implemented by the ColeControl base class. There are two stock method implementations.
DoClickThis event is fired when the control is clicked.
RefreshThis event refreshes the control.
Custom methods are methods that you create. The COleControl class does not support custom methods. MFC implements custom
methods using the DISP_FUNCTION() macro. The macro, which refers to the handler function, must be declared in the control class
and implemented in the projects program file. You must also insert the id statement in the primary dispatch interface of the .ODL file.
Events
Events in ActiveX are a way for the ActiveX control to notify the container about the control. An event is usually activated by mouse
actions or keystroke actions. Like properties and methods, MFC supports two types of events: stock and custom.
The ColeControl base class implements stock events. They are the most common events for an ActiveX control. The stock events are
ClickFired when the control is clicked
DblClickFired when the control is double-clicked
ErrorFired when an error has occurred within the control
KeyDownFired when the key is pressed down
KeyPressFired when the key is pressed and released
KeyUpFired when the key is released
MouseDownFired when the mouse button is pressed
MouseMoveFired when the mouse cursor is moving within the control
MouseUpFired when the mouse button is pressed within the control
ReadyStateChangeFired when the state of the control changed
Custom events are events that are not supported by the ColeControl class. Custom events are implemented with the EVENT_CUSTOM
macro by MFC. The syntax is: EVENT_CUSTOM(ExtName, FiringFunc,Params)
ExtName is the external name of the event. FiringFunc is the control classs event firing function. Params is the list of parameter types
passed to the FiringFunc.
The macro, which refers to the handler function, must be declared in the control class and implemented in the projects program file.
You must also insert the id statement in the primary dispatch interface of the .ODL file. Exercise 3-8 will help you review components.
Exercise 3-8 Checklist for Evaluating Components
If it has to do with the appearance of the component, set the properties of the component.
If you need to run a type of macro, set the methods of the component.
If you need to notify the component based on an action, set the events of the component.
Certification Summary
Since the introduction of the Microsoft Foundation Class (MFC) Library, developers have learned that using MFC makes
Windows-based application development much easier. MFC functions as a thin layer over the Win32 API so developers can access the
Windows application programming interface (API) with easy-to-use objects instead of calling the complex API functions.
MFC applications have the same common elements: -documents, -views, -frame windows,-document templates, -application objects,
and thread objects. When developing MFC applications, problems may arise in developing for the Windows 95/98/NT platform.
Problems are often caused by not following the proper API calling rules and conventions, misinterpreting the operating system platform,
Chapter 03: The Physical Design
replacing system DLLs with versions for the wrong platform, or simply bad coding.
Prior to MFC, the main way to write a Windows-based application was to do it with the Windows API and the Platform SDK, (Platform
software development kit). By using the SDK, you are essentially writing programs with the Win32 API. Although MFC makes
Windows-based programming much easier, it is not always the best way to create your applications.
Libraries allow you to share code in different applications. DLLs are dynamically linked at run time. There are two different types of
DLLs supported in MFC: MFC regular DLL and MFC extension DLL. MFC regular DLL can use C++ classes. However, unlike the
MFC extension DLL, the MFC regular DLL can only export C functions.
The drawing and printing capabilities of Windows center on the Windows GDI in MFC. MFC supports multitasking through its
threading model. Thread-based multitasking allows users to run more than one instance of a program and to run different tasks in a
single application.
Visual C++ provides many technologies to allow access to databases in your applications. It supports Data Access Objects (DAO),
ODBC, OLE DB, and ActiveX Data Objects (ADO). In addition to databases, components such as ActiveX controls can be created
allowing database functionality to be componentized. ActiveX brings this type of plug and play interoperability to Windows-based
applications.
Two-Minute Drill
MFC functions as a thin layer over the Win32 API so developers can access the Windows API with easy-to-use objects instead of
calling the complex API functions.
Regardless of how an application is designed and structured, all MFC applications have the same common elements: the
documents, the views, the frame windows, the document templates, the application object, and the thread objects.
The document is derived from the CDocument class. The document object provides functions that other objects can use to access
the data.
MFC allows you to open multiple views of the same data with a multiple-document interface (MDI) application.
An easy way to think about views is that the view is just a specific representation of the document. Each document can have
multiple views.
You can create single-document or multiple-document templates, which cam be used to create single-document interface (SDI) and
MDI applications.
The frame windows host the applications view windows. The applications main frame window specifies the characteristics of the
frame windows that contain these views.
A thread is the most basic unit of execution in a Windows-based application. If your application is multithreaded, you can create
multiple threads with the classes derived from CWinThread.
The application object, derived from CWinApp, is the backbone of all MFC applications. It manages the start, the execution, and
the termination of an application by encapsulating the Win32 WinMain() function.
In order for you to successfully develop cross-platform Windows-based applications, you need to follow a few guidelines to
minimize problems when developing programs that are going to run on Windows 95/98 and Windows NT. These guidelines cover
versioning, DLLs, security, drive size, hard-coded paths, and ANSI versus Unicode.
The main difference between Windows 95/98 and Windows NT is security. Developers must keep this in mind when they are
designing programs that run on both platforms.
MFC is a C++ class library that is a wrapper around the Win32 API. The newest version, MFC 6.0, has about 200 classes available
to it.
MFC is more than a class library. The MFC is also an application framework that defines the structure of the application.
Libraries are sets of compiled code that are included within an application at compile time. With DLL, or dynamic link libraries,
the libraries are linked at run-time, hence the name dynamic link libraries.
An MFC regular DLL can use C++ classes, but it can only export C functions. If you need a DLL that can be loaded in any Win32
programming environment, you should use a regular DLL.
The MFC extension DLL can export entire MFC classes, MFC derived classes, C++ classes, member functions, and overloaded
functions.
Command messages are messages that can be handled by many different objects, such as the application, the documents, and the
windows.
In a document/view application, the data, also known as the document, is managed separately from the application through which
the users interact with the data.
The simplest application type that has the document/view architecture is the single-document interface (SDI). In an SDI
application, only one document is open at a time.
The multiple-document interface (MDI) is similar to the SDI application except that it allows the user to have multiple documents
open at the same time.
In the non-document/view application, you must override the CWinApp::InitInstance function to create the windows and the dialog
boxes.
Whenever the Windows-based application needs to draw to a device, it accesses it through the device context. The device context
(DC) is a virtual desktop service that represents the device drawing surface.
Chapter 03: The Physical Design
You can set and manipulate colors by using the COLORREF value. COLORREF uses the red-green-blue (RGB) system.
Unlike drawing lines, to draw text you must first set the attributes to the text and then write it out to the device.
In windows, the GDI translates logical coordinates to physical coordinates using the different mapping modes. You can set the
mapping modes with the SetMapMode device context function.
With MFC, the printer device context is automatically created and destroyed and the StartDoc, StartPage, EndPage, and EndDoc
functions are called automatically for you by using member functions in the Cview class.
The most common print function to override is the OnPrint function. You must override this function to print more standard
features such as footers and headers.
Thread-based multitasking allows users to run more than one instance of a program as well as to run different tasks in a single
application. This is similar to running subapplications within a single application.
Every process has a priority class assigned to it. The priority is used to help determine how much central processing unit (CPU)
time that the process has access to.
With multithreading, synchronization becomes a necessity when two or more threads need access to a shared resource that has a
limit on how many threads can access it.
Visual C++ provides many technologies to allow access to databases in your applications. It supports Data Access Objects (DAO),
Open Database Connectivity (ODBC), OLE DB, and ActiveX Data Objects (ADO).
You can access database objects through libraries included in Visual C++, such as MFC, the Active Template Library (ATL), and
the Platform SDK.
ActiveX components are based on newer OLE (Object Link Embedding) and use the Component Object Model. COM defines how
components can interact seamlessly between each other.
A main feature of ActiveX controls is their ability to expose their properties using a primary dispatch interface.
ActiveX methods allow the client to perform functions on the control. Like properties, the methods are implemented by the
primary dispatch interface.
Events in ActiveX are a way for the ActiveX control to notify the container about the control. An event is usually activated by
mouse actions or keystroke actions.
Answers to Exercise 3-3
Platform MFC extension or regular DLL?
Visual Basic MFC regular DLL
Visual C++ MFC extension DLL
Visual J++ MFC regular DLL
Borland C++ MFC extension DLL
Symantec C++ MFC extension DLL
Symantec Caf MFC regular DLL
Answers to Exercise 3-5
1. You would like to have customized headers and footers. OnPrint
2. You want to modify the device context. OnPrepareDC
3. You want to set the maximum page count. DoPreparePrinting and OnBeginPrinting
4. After creating objects, you need to overload this function to release the resources created by your objects. OnEndPrinting
Answers to Exercise 3-6
1. You want to do a background spell checker. THREAD_PRIORITY_LOWEST
2. You want to defragment your hard drive when the computer is idle. THREAD_PRIORITY_IDLE
3. You want to run a service critical to system operation. THREAD_PRIORITY_TIME_CRITICAL
4. You are creating a standard application. THREAD_PRIORITY_NORMAL
Answers to Exercise 3-7
1. You want to do a client/server application. What library should you use? ATL
2. You want to be able to access an Excel spreadsheet. What database object should you use? OLE DB
3. You want to manipulate data in Access. What library should you use? MFC
4. You are creating a standard database application. The database uses a standard ODBC driver. What database object should you
use? ODBC.
Microsoft Developer Studio and Visual C++ include a rich set of tools and wizards for handling many of the
everyday programming tasks that are a part of almost every desktop application development project. This
chapter focuses on the tools that aid the developer in creating the visual elements of an application, as well as
two of Developer Studio's most important wizards, AppWizard and ClassWizard.
We'll discuss the typical issues that you may encounter when creating your application's user interface,
including guidelines and principles to follow to ensure your user interface is simple and easy to navigate. We'll
describe how to use and enhance the Microsoft Foundation Classes (MFC) toolbars and status bars, which are
generated by the MFC AppWizard. We'll also look at the capabilities of all the Visual C++ resource editors,
which allow you to create and edit various types of Windows resources such as icons, menus, accelerator
tables, dialog boxes, and strings.
In our discussion of AppWizard, we'll look at the options and steps involved in creating a new MFC project.
Then after seeing how you can enhance your application's user interface with the Visual C++ resource editors,
we'll use ClassWizard to "hook-up" events to code when the user interacts with your application's visual
elements.
At various stages in the chapter we'll create and build upon a simple sample application to provide a practical
demonstration of the concepts discussed in the chapter.
Navigation for the User Interface
Throughout the process of designing and implementing desktop applications using Visual C++, a large amount
of time is spent creating and refining the application's user interface. This process involves designing and
creating the interactive elements of the application such as toolbars, status bars, menus, dialog boxes, and
icons.
One of the biggest challenges in designing and implementing a desktop application comes in the creation of an
effective user interface. The design of your application's interface can affect how a user perceives your
software more than any other factor. Visual C++ and MFC provide the framework on which to build a visually
appealing and conventional user interface.
Chapter 04: The User Interface
Careful planning is required to ensure that the user interface exposes all the functionality of your application
while being intuitive and simple enough to allow the end user to quickly learn the application. When
considering your application's user interface, it is important to maintain the visual and functional consistency
that can already be found across the majority of applications running on the Windows platform. This enables
the users of your application to apply their experience of using other applications when they are learning to use
your application. With this in mind, developers are encouraged to follow the Windows user interface design
guidelines, which promote good interface design as well as visual and functional consistency within and across
Windows-based applications.
Close compliance to the Windows user interface design guidelines is especially important when you consider
the role of the user interface in modern desktop applications. Increasingly, the focus of application
development is to separate the user interface from the core functionality of the program. This often takes the
form of a distributed architecture with clear separation of user services, business services, and data services. In
such a model, the user interface should serve only as a tool for the user to concentrate on the task of interacting
with the application data, without being distracted or hindered by an overly complex front end. Fortunately,
Visual C++ and MFC provide all of the resources necessary to create a conventional and consistent user
interface.
Creating and Integrating Toolbars
A toolbar is a special organizational visual element that can manage sets of other controls such as buttons,
button separators, and combo boxes. The primary role of toolbars in desktop applications is to provide quick
access to commonly-used functions.
There are various toolbar styles commonly in use; however, the pervasive style now is the Internet Explorer
flat toolbar shown in Figure 4-1. This style of toolbar is sometimes referred to as a ReBar. These toolbars
provide the user with the additional feedback of seeing the toolbar buttons raise up as the mouse passes over
them.
Figure 1: Internet Explorer's toolbars are an example of the ReBar style of toolbar
Toolbars are usually positioned at the top of the client area of a main application window. Often, however,
toolbars are designed to be dockable, whereby the user can drag and place them on any border of the
application's top-level window or leave them in their own modeless window at any location on the screen. An
application isn't required to expose all of its functionality through toolbars because it may take up far too much
screen space. If your application has a lot of functionality that you would like to have exposed through
toolbars, then it might be a good idea to dedicate a separate, dockable toolbar to each logical group of
commands. You can then allow the user to configure your application so that only the toolbars that they
frequently use are on the screen. MFC allows you to easily create many conventional styles of toolbars,
depending on your choices in the MFC AppWizard.
With Visual C++'s toolbar resource editor, you can perform the following tasks:
Create new toolbars, toolbar buttons, and separators
Chapter 04: The User Interface
Convert bitmaps into toolbar resources
Create, move, and edit toolbar buttons and separators
All of the buttons of a toolbar resource are actually stored in a single bitmap. In an MFC project, the bitmap for
the initial AppWizard-generated toolbar is stored in the project's res subdirectory with the name Toolbar.bmp.
The Toolbar editor provides a special view of the underlying bitmap, which closely resembles how the toolbar
should look when your application is running. Figure 4-2 shows the various display elements of the toolbar
editor.
Figure 2: Visual C++'s Toolbar editor is used to edit toolbar resources
The toolbar editor window shows two views of the selected button image separated into two panes. The left
pane is editable, but in practice is only used to preview the button at its run-time size. the right pane is where
you would normally edit the toolbar button. The functionality provided by the toolbar editor is reasonably
straightforward. You can select from several different types of pens and tools on the Graphics toolbar and
select from a range of basic colors from the Color toolbar. Above the two views of the image is the preview
display of your toolbar. The button that currently is being edited is indicated by the fuzzy border.
There are two ways to view the properties of a toolbar button:
Double click it from the preview display
Select it in the toolbar editor preview display, and from the View menu select Properties.
The Toolbar Button properties dialog box is shown in Figure 4-3. Using this dialog box, you can change the
toolbar button's ID, width, height, and prompt. The ID is used by the application to identify the toolbar button
resource. The prompt contains text that will appear in the status bar when the mouse hovers over this toolbar
button; this text is placed in a string table and given the same identifier as the toolbar button. Note that by
design, the MFC AppWizard sets up a convenient association between the initial set of toolbar buttons and
their corresponding menu items whereby they share the same identifier and string resource. This means you
don't have to maintain separate copies of the string for the prompt property of a toolbar button and a menu item
that perform the same function. In addition, in the prompt field of the Toolbar Button Properties dialog box in
Figure 4-3, you'll notice the newline character \n followed by the word New.Any text to the right of the newline
character becomes the tooltip for the toolbar button.
Figure 3: The Toolbar Button properties dialog box allows you to change toolbar button properties
You might have noticed the blank button that is displayed at the right end of the toolbar, in the upper preview
display of the toolbar editor. This button is used to create a new button or separator. Separators on a toolbar
Chapter 04: The User Interface
group similar functions into logical sets. For example, the Cut, Copy, and Paste buttons are invariably grouped
together.
When you create a new button, another blank button appears to the right of the edited button, but note that
when you save your toolbar, the blank button is not saved to the underlying bitmap. Saving the toolbar also
updates the application's resource file script with the various resource IDs of the toolbar buttons.
Exam Watch: Often you'll want to add text to your toolbar buttons in the same way Internet Explorer has text
captions for its toolbar buttons. Unfortunately, the toolbar editor doesn't provide any support for this, so you'll
need to use the SetButtonText function from within your code. This function takes two arguments: the first is
the index of the button, and the second is the text for the button identified by the index in the first parameter.
Note that you'll also have to resize the toolbar to ensure that there is room for the text.
Here is a list of common functions that you may have to perform when using the toolbar editor.
How do you create a toolbar button? Assign an ID to the blank button at the right end of the toolbar
by opening its property page and editing its ID field.
Alternatively, you can select the blank button at the right end of
the toolbar, and begin drawing in the image editor. A default
button command ID will be assigned to the new button using the
convention ID_BUTTON<n> where n is a sequential number
representing how many new buttons have been added this way.
How do you move a toolbar button? Drag the button that you want to move to its new location on the
toolbar.
How do you copy buttons from a toolbar to
another toolbar?
Hold down the ctrl key and drag the button to its new location
either on the toolbar or a location on another toolbar.
How do you delete a toolbar button? Select the toolbar button and drag it off the toolbar.
How do you insert a separator before a
button that isn't followed by a space?
Drag the button to the right or down until it overlaps the next
button by about halfway.
How do you insert a separator before a
button that is followed by a space and then
retain the following space?
Drag the button until the right or bottom edge is just touching
the next button or just overlapping it.
How do you insert a separator before a
button that is followed by a space and not
retain the following space?
Drag the button to the right or down until it overlaps the next
button about halfway.
How do you remove a separator from
between two buttons?
Drag a button from one side of the separator toward the button
on the other side until it overlaps it about halfway.
Creating a New Toolbar
To insert a new toolbar in your application, you can select Insert Toolbar from the context menu of the Toolbar
folder in the ResourceView tab. This creates a new toolbar with a single blank button. For each new button you
start to draw, a new blank button is added on to the end of the toolbar.
Once you draw the pictures on your toolbar, you can change the properties for each individual button by
double-clicking the button and adjusting the values in the Toolbar button properties dialog box. If the button
will be used to execute the same operation as an existing menu item, then you assign the menu items ID to the
toolbar button. If you entered an ID that corresponds to an existing menu item, then youll notice that the
prompt field is automatically populated with the same description that was applied to the corresponding menu
item. The description in this prompt field will appear on the applications status bar when the mouse hovers
over the toolbar button. At the end of the prompt, you can add a newline character \n and a short description,
which will be used as the tooltip for the toolbar button.
Having finished designing your new toolbar, you should change the toolbar ID. To change the toolbar ID,
right-click the toolbar from the ResourceView and select Properties from the context menu. You will then be
able to change the toolbar ID in the toolbar Properties dialog box. By default, it would probably have been
called IDR_TOOLBAR1, but you may want to give it a more appropriate name that has some relationship to
the context in which it will be used.
A toolbar in an MFC application is actually a CToolBar object declared as a member of your applications
CMainFrame class. Therefore, to add your new toolbar to your application, simply add a member variable to
the protected section of your CMainFrame class definition, as in the following example:
class CMainFrame : public CframeWnd
{
Chapter 04: The User Interface
//
protected:
CtoolBar m_wndToolBar1;
};
The toolbar is actually created in the CMainFrame::OnCreate function. OnCreate is called by the MFC
framework just after the window has been created but just before it is shown. You can add your code to create
the new toolbar in this function as follows:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//
if (!m_wndToolBar1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
WS_VISIBLE | CBRS_TOP |
CBRS_GRIPPER | CBRS_TOOLTIPS |
CBRS_FLYBY | CBRS_SIZE_DYNAMIC)||
!m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
EnableDocking(CBRS_ALIGN_ANY);
m_wndToolBar1.EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar1);
//
}
The first part of this code that you add contains two functions that are required to create the toolbar. The first
function, CToolBar::CreateEx, actually creates the toolbar. The first parameter to this function is the only
required parameter and it specifies a pointer to the window that will be the toolbars parent. In this case, it is
the CMainFrame object itself. The second argument specifies additional styles for the toolbar, most notable of
which is the CBRS_TOOLTIPS flag, which activates ToolTips for the toolbar.
The second function, CToolBar::LoadToolBar, associates the toolbar object with the toolbar resource that you
created in the toolbar resource editor. This function takes a single argument that specifies the ID of the toolbar
resource.
The remaining functions in this OnCreate implementation are used to make the toolbar a dockable toolbar. In
order for toolbar docking to be enabled, the first thing you must do is enable docking on the main frame
window with the CFrameWnd::EnableDocking function. Then, docking must be enabled on the toolbar itself
with the CControlBar::EnableDocking function. Finally, you can specify that the initial position of the toolbar
should be docked with a call to CFrameWnd::DockControlBar. Conversely, you can specify that you would
like the toolbar to be undocked or floating by calling CFrameWnd::FloatControlBar.
Implementing ToolTips for Toolbar Buttons
Toolbars also include ToolTips, which are small modeless windows that are briefly displayed when the mouse
lingers over a button for a certain interval. ToolTips are used to proactively give the user some feedback about
the purpose of a button.
In order to activate tooltip support for your toolbar, you need to add the CBRS_TOOLTIPS style to the
dwStyle parameter passed into the CToolBar::Create (or CreateEx) function or the CControlBar::SetBarStyle
function. Then, use the following procedure to specify the tooltip text for each individual button on your
toolbar.
To create a ToolTip for a toolbar button:
1. Open the toolbar editor for your toolbar by double-clicking the toolbar in the ResourceView tab.
2. Double-click the button for which you want to define a tooltip. The toolbar button properties dialog box
will be displayed.
3. In the Prompt field, add a description of the button, followed by a newline character (\n) followed by the
text of the tooltip.
Chapter 04: The User Interface
Implementing and Writing to the Status Bar
Status bars give your application a place to display messages and useful information to the user without
interrupting the user. They are normally displayed at the bottom of a window and they consist of several panes,
which can include indicators and a message line. The indicators give the status of such things as Caps Lock,
Scroll Lock and Num Lock. The message panel on the status bar is usually used to display information about
the program status or about a toolbar button or menu item that the user is pointing to with the mouse. Figure
4-4 shows a status bar in action. Notice how a description is displayed on the status bar for the toolbar button
over which the mouse is hovering.
Figure 4: The status bar gives the user feedback about the current operation
Adding a New Status Bar Pane
Youve already seen how simple it is to display text in the status bar when the mouse is over a menu item or a
toolbar button. All that was required was to change the value of the Prompt property for the button or menu
item resource. However sometimes you will want to customize a status bar by adding panes that will be used to
give the user more detailed feedback regarding the status of your application or about a particular operation
that the user is performing.
Use the following steps to add a new pane to a status bar:
First, add a command ID for the new pane. Display the Resource Symbols dialog box, shown in Figure 4-5, by
selecting Resource Symbols from the View menu. This dialog box can display all of the currently defined
symbols for your application's resources.
Figure 5: The Resource Symbols dialog box shows all of your application's currently defined symbols
Add a new symbol by clicking the New button to display the New Symbol dialog box, shown in Figure 4-6.
Chapter 04: The User Interface
Call the new status bar pane ID_STATUSPANE1 (in practice you would give a more descriptive name to the
new status pane) and accept the default value for the ID. Click OK and then Close to add the new symbol.
Figure 6: The New Symbol dialog box lets you add a new resource symbol
Next, you must assign a default caption for the new status bar pane. The length of this default string will
determine the initial width of the status pane. To define the string, open the String Table resource editor by
double clicking the string table in the ResourceView tab of your project's workspace. Then, display the String
Properties dialog box, shown in Figure 4-7, for a new string by selecting New String from the context menu
which appears when you right-click inside the string table resource editor.
Figure 7: Use the String Properties dialog box to define the default caption for the new status pane
In the ID field of the String Properties dialog box, type the same ID that you assigned to the new pane in the
Resource Symbols dialog box. In this case, type ID_STATUSPANE1. Then, in the caption field, enter the
default caption that you would like to appear in the status pane. close the String Properties dialog box and close
the String Table resource editor.
Next, you need to add your new pane to your application's status bar's indicators array. A status bar in an MFC
application is usually initialized in the CMainFrame::OnCreate function. During the initialization of the status
bar, a call is made to CStatusBar::SetIndicators that pass in an array of IDs that determine the order and type of
panes to display in the status bar. In a normal MFC AppWizard-generated project, this array is defined near the
top of the file called MainFrm.cpp. You can use the FileView tab of your project workspace to open
MainFrm.cpp. All you have to do to activate your new status pane is add its ID to the array in the position that
you would like it to appear, so that the array should now look something like this:
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_STATUSPANE1, // our new status pane
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
Now when you recompile and execute your application, you will see the new status bar pane with your default
text. However, it isn't much good if you aren't able to dynamically change the text that is displayed in it. So to
make the status bar pane fully functional, you create an UPDATE_COMMAND_UI event handler that you will
subsequently be able to use to set the text in the pane.
You would normally use ClassWizard to set up the mechanism for messages to be caught, but ClassWizard
doesn't allow you to catch status bar messages. Therefore, you must manually add the event handler entries to
the MFC message maps and create the code for the message handler. Note that any code between the
AFX_MSG_MAP and the AFX_MSG comments is used by ClassWizard and generally shouldn't be modified.
we will be adding our event handler entries outside the ClassWizard blocks.
First, we'll change the message map entries in the header file for your CMainFrame class. you can open this file
Chapter 04: The User Interface
by double-clicking the CMainFrame class in the ClassView tab of the project workspace. The message map
appears near the end of the file. Modify this message map by adding in the OnUpdateStatusPane1 entry so
that it looks like the following listing:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
afx_msg void OnUpdateStatusPane1(CCmdUI *pCmdUI);
DECLARE_MESSAGE_MAP()
Next, you need to add the handler to the message map in the class implementation file in order to associate the
status pane's resource symbol with your handler function. This message map is located in the MainFrm.cpp
file. Open this file by double-clicking it from the FileView tab in your project workspace. The message map
will be located somewhere near the top of the file. Once you've found it, add the
ON_UPDATE_COMMAND_UI entry so that it looks like the following listing:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code !
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_UPDATE_COMMAND_UI(ID_STATUSPANE1, OnUpdateStatusPane1)
END_MESSAGE_MAP()
The mechanism is now in place for the function OnUpdateStatusPane1 to be called whenever the status bar
pane ID_STATUSPANE1 needs to be updated. All that remains is to add the actual handler function itself. To
do this, copy the code from the following listing into the very bottom of the MainFrm.cpp file.
void CMainFrame::OnUpdateStatusPane1(CCmdUI *pCmdUI)
{
CTime theTime = CTime::GetCurrentTime();
CString sStatusText = theTime.Format("%H:%M:%S");
CClientDC dc(this);
SIZE size = dc.GetTextExtent(sStatusText);
int index = m_wndStatusBar.CommandToIndex(ID_STATUSPANE1);
m_wndStatusBar.SetPaneInfo(index,ID_STATUSPANE1, SBPS_POPOUT, size.cx);
pCmdUI->Enable();
pCmdUI->SetText(sStatusText);
}
The parameter to this message handler function is a pointer to a CCmdUI object. The CCmdUI class is always
used within the handler of the ON_UPDATE_COMMAND_UI message. The handler can call member
functions of the CCmdUI object to update the status bar pane. The following list describes the purpose of the
CCmdUI member functions as they apply to the updating of a status bar pane:
CCmdUI::EnableMakes text in the status bar pane visible or invisible
CCmdUI::SetCheckChanges the border of the status bar pane to be a pop-out (raised) border or a
normal border
CCmdUI::SetRadioSame as SetCheck
CCmdUI::SetTextSets the text to display in the status bar pane
You should now be able to recompile and run your application. You'll notice that the updating of the time in
the pane is relatively irregular. This is because the triggering of the message depends on when the application
enters an idle state, and that is dependant on many factors. In fact this method of implementing a clock in the
status bar may not be entirely practical in a real application and only serves as an example of how to change the
text in a status bar pane.
In the handler function, we are simply formatting and displaying the current time in our new status bar pane.
These types of user interface update handlers should do as little as possible because they can tend to be called
very often. This particular handler will be triggered whenever the application is idle.
The first thing we do in the handler is obtain and format the current time, which is then saved in the StatusText
Chapter 04: The User Interface
variable. Then, we determine how wide the pane will need to be in order to draw the text. this is done with the
call to GetTextExtent, using a device context from the main frame window. Then, we obtain the index of our
pane through a call to the CommandToIndex function of the status bar member. The index is used to set the
width of our pane in a call to SetPaneInfo. notice also in this call that we set a flag which gives the status bar
pane a raised bevel effect. finally, we ensure that the status bar pane is in fact enabled and we set its text value
with a call to SetText, passing in the formatted string containing the current time.
Using the MFC AppWizard
The starting point of many Microsoft Visual C++ projects is the AppWizard. The MFC AppWizard gives
developers a great head start when beginning a new Windows-based program using MFC. AppWizard helps
you generate the basic source files for a variety of different types of Windows-based programs, allowing you to
get down to the task of creating your application. The extensive amounts of AppWizard-generated code
handles many routine programming tasks, freeing the developer to concentrate on implementing program
functionality. It is possible to use Visual C++ to create a Windows-based program without using AppWizard,
but the range of project types available in AppWizard make it the sensible choice for any Visual C++ project.
Creating an Application with the MFC AppWizard
We'll now walk through the steps involved in creating a new Visual C++ project using the MFC AppWizard. In
this exercise, you'll create a simple MFC executable application to demonstrate the features of the MFC
AppWizard. On completion of this exercise you will know about the following items:
Identification of the different MFC project types supported by AppWizard
How to create a new Visual C++ project and project workspace
The optional features that can be added to an MFC application through AppWizard
The initial source files that AppWizard generates
How to compile and run the newly-created MFC AppWizard project
To use the MFC AppWizard to create a new Visual C++ project, select File | New and select the Projects tab
from the new dialog box as shown in Figure 4-8. Choose MFC AppWizard (EXE) from the list of project types
on the left, give the project the name MFCWiz, and click OK.
Figure 8: Select the MFC AppWizard project type from the Project tab of the New dialog box
Step 1 of the MFC AppWizard is shown in Figure 4-9. This step requires you to decide upon the basic
Chapter 04: The User Interface
characteristics of your application, such as whether it will be a single-document interface (SDI), a
multiple-document interface (MDI), or a Dialog-based application.
Figure 9: Step 1 of the MFC AppWizard requires you to choose the type of application that you wish to build
There are three main types of application architecture supported by the MFC AppWizard:
A single-document interface application can only present one document to the user at any given time. A
simple example of an SDI is Windows Notepad. Choosing this option will create an application with a view
class based on CView.
A multiple-document interface application can present the user with several documents at once, each in
its own child window. An example of a MDI application is Microsoft Word. MDI applications are also based
by default on the CView class.
A Dialog-based application such as Windows Character Map, is based on the CDialog class and typically
displays a single dialog box to the user.
Beneath the choice of application type is a check box that allows you to indicate whether you want support for
the document/view architecture using the CDocument and the CView base classes. You would probably clear
this check box if you were porting an application from another development environment. However, an
application without the document/view architecture wont have MFC support for opening a file from a disk.
Further down on the screen is a drop-down list box that allows you to select the language for your applications
resources. The drop-down list displays the languages available on your system. If you wish to use a language
other than English, the appropriate DLL for that language must be installed on your system. The DLLs follow a
naming convention of AppWzxxx.dll, where xxx is a three-letter language identifier.
For the purposes of this demonstration, we are going to create an SDI application with document/view
architecture and English (United States) resources. Select the appropriate options and click Next.
Step 2 of the MFC AppWizard, shown in Figure 4-10, is to select the desired level of database support for your
application.
Chapter 04: The User Interface
Figure 10: Step 2 of the MFC AppWizard is to select the desired level of database support
There are four levels of database support for MFC applications:
The default option is None, which specifies that you do not wish AppWizard to include support for
database access in your application.
The next level of support, Header files only, gives your application a basic level of database support
whereby a header file, AFXDB.H, and link libraries are created but no database-specific classes are generated.
This allows you to create recordsets and use them to view and update records from a database.
The third level of support, Database view without file support, includes the header and link libraries as
well as a record view and a recordset class. Choosing this option will give your program a
CrecordView-derived view class. AppWizard will also create a Crecordset-derived class that will be associated
with your view class. This option includes document support but no serialization support. A form-based
application will be created in which the record view is used to view and update records through its recordset.
The final level of database support is Database view with file support. This option will create an
application similar to an application created with the previous level of support, except that this application will
also support document serialization. If you choose either of the levels of database support that include a
database view, you will also have to specify a data source for the application.
The purpose of this exercise isnt to create a database application, so we will select None as our level of
database support and click Next.
Step 3 of the MFC AppWizard, shown in Figure 4-11, is concerned with selecting the amount of ActiveX and
compound document support for your application.
Chapter 04: The User Interface
Figure 11: Step 3 of AppWizard allows you to specify ActiveX options
There are five choices for compound document support:
The default option is to not include support for compound documents in your application.
The next option, Container, allows your application to contain embedded or linked ActiveX objects, such
as Word documents.
The next option, Mini Server, specifies an application that has the ability to create and manage compound
document objects that can be embedded in other applications, but it cant run as a standalone application.
To have an application that can create and manage compound document objects such as the Mini Server,
but also run as a standalone application, choose Full Server.
Choosing Both Container and Server creates an application that can contain embedded or linked objects
from other applications as well as create and manage its own document objects for other applications to use.
If you choose to support compound documents, you can also support compound files. Files saved in the
compound file format can contain several automation objects, and those objects are stored in such a way that
objects can be changed without rewriting the whole file. This can greatly improve the efficiency of your
application. You can use the option buttons in the middle of the Step 3 dialog box to say Yes, Please, or No,
Thank You to compound files.
If you want your application to surrender control to other applications through automation, or if you would like
your application to control other applications through automation, select the Automation check box. In
addition, if you intend to use ActiveX controls in your application, select the ActiveX Controls check box.
In our exercise we will take all the defaults for this step and move on to step 4.
Step 4 of the MFC AppWizard, shown in Figure 4-12, is concerned with selecting some of the common
features of Windows-based applications such as toolbars, status bars, and print preview support.
Chapter 04: The User Interface
Figure 12: Step 4 of the MFC AppWizard allows you to specify the common features that your application will
support
The various options for Step 4 of the MFC AppWizard are described in the following list:
Select the Docking Toolbar check box to include a toolbar in your application. The toolbar that is created
for you will include buttons for various common operations such as Cut, Copy, and Paste. A couple of menu
items will also be created for you to allow the user to choose whether to hide or show the toolbar. Notice that a
dockable toolbar will be created by default.
Select the Initial Status Bar check box to include a status bar in your application. The default status bar
will include panels that display the status of the Caps Lock, Num Lock, and Scroll Lock keys as well as a panel
that displays information when the mouse is passed over menu items. Just like the toolbar, some menu
commands will be added to allow the user to choose whether to hide or show the status bar.
For applications using the document/view architecture, the Print and Print Preview check box enables
AppWizard to generate code that will handle print, print setup, and print preview commands. Menu items will
be created for these operations.
Selecting the Context Sensitive Help check box will generate a set of help files that you can compile with
the help compiler.
The 3D Controls check box is selected by default and it allows the controls that appear in your
application to have 3D shading.
Selecting the MAPI check box will include support for the Messaging Application Programming
Interface in your application.
Selecting Windows Sockets will include Winsock support in your application. Winsock support will
enable your application to take part in interprocess communication (IPC) through Transmission Control
Protocol/Internet Protocol (TCP/IP).
If you chose to include a toolbar in your application, you will be able to specify the style of toolbar you
prefer. The Normal option button will produce a traditional style of toolbar with a simple list of buttons. The
Internet Explorer ReBars option button will create toolbars like those in Internet Explorer, which are capable of
containing standard windows controls such as combo boxes.
The edit box at the base of the Step 4 wizard form allows you to select the number of files to show in the
recently used file list of your application's File menu.
The Advanced button displays another dialog box that allows you to specify options for document template
strings and frame characteristics. The first tab of the Advanced Options dialog box is shown in Figure 4-13.
This tab allows you to specify a file extension for your document type as well as various strings that identify
Chapter 04: The User Interface
your application's document type and may require localization. These strings are kept in the resource script of
the application where they are associated with the resource ID of the main frame window of the application.
Figure 13: The first tab of the Advanced Options dialog box allows you to specify options for document
template strings
The second tab of the Advanced Options dialog box, titled Window Styles, is shown in Figure 4-14.
Figure 14: The Window Styles tab of the Advanced Options dialog box allows you to specify various flags that
affect the appearance of your application's window
This tab allows you to choose to use a split window in your application. Selecting this option will insert a split
bar in your application's main views. In an MDI application, the client area of the child windows will contain
the split bar, whereas in an SDI application, the client area of the main application window will contain the
split bar. Recall that we chose to build an SDI application back in Step 1 of the AppWizard and so the MDI
Chapter 04: The User Interface
section of Figure 4-14 is disabled.
The other options on the Window Styles tab are explained here:
Selecting the Thick Frame check box will give your application window a thick edge and the user will be
able to resize the window. Clearing this option prevents resizing.
The Minimize Box check box determines whether your application window will have a minimize button
in the top-right corner.
The Maximize Box check box determines whether your application window will have a maximize button
in the top-right corner.
The System Menu check box determines whether your application window will have a System menu in
the top-left corner of the main window. The System menu is a special pop-up menu that is located in the far left
of an application's title bar. It typically includes the Close, Restore, Move, Size, Minimize, and Maximize
commands.
Selecting the Minimized check box causes your application to be minimized when the application starts.
Selecting the Maximized check box causes your application to be maximized when the application starts.
Once again we will stay with the defaults for all the options in Step 4 and click Next to move on to Step 5.
Step 5 of the MFC AppWizard is shown in Figure 4-15. The items in Step 5 aren't logically grouped together;
they are more of a miscellaneous collection of the remaining information that AppWizard collects.
Figure 15: Step 5 of AppWizard includes some miscellaneous options
The first choice that you are required to make concerns the style of application that will be created. The default
is to create a standard MFC application using the normal MFC architecture. The alternative is to create an
Explorer-like application using a split window, where the left pane is a CTreeView and the right pane is a
CListView.
The next set of option buttons is concerned with choosing whether you would like the MFC AppWizard to
generate source code comments for your application. These comments include prompts telling you where to
add your code. a ReadMe.txt file will be generated in your project directory. This ReadMe.txt file contains
comprehensive information regarding all of the files generated by AppWizard.
The next question asks if you would like the MFC libraries installed as a shared DLL or statically linked to
your application. Using MFC as a shared DLL will reduce the size of your application's executable, but may
introduce complex distribution issues. Choosing to statically link your application to the MFC libraries at build
time will produce a much larger executable, but it may be simpler to distribute.
Chapter 04: The User Interface
The final step of the MFC AppWizard involves reviewing and confirming the names, filenames, and base
classes of the classes that AppWizard will generate. Step 6 is shown in Figure 4-16.
Figure 16: Step 6 of the AppWizard allows you to change filenames, class names, and base classes
By default, AppWizard creates names for your application classes and files based on an abbreviation of your
project name. The majority of the time, you won't want to change the default names. if the Base Class combo
box is enabled, you will be able to select a different class from which to derive your new class. This option
usually only applies to your application's view class. The default is CView, but depending on the type of
application that you are building, you may wish to use another view class, such as CFormView, CscrollView,
or CEditView.
Accept the defaults on the final step and click Finish. You will be shown a summary of all the options that you
have selected for your application. When you are happy with the selected options, click OK and the project
workspace will be created. You can build and run your application immediately by selecting Build and then
Execute from the Build menu.
On the Job: Sometimes you'll want AppWizard to generate code with different options after you have run
AppWizard. AppWizard is a one-time process that you perform at the start of a project. This doesn't give you
the opportunity to go back and change options if a new requirement arises at some later stage in the
development process. Say, for example, your client suddenly requires that you include Winsock support in
your application in order to talk to an external system through TCP/IP. we'll look now at a technique that you
can use to still use AppWizard to generate the code that you require.
AppWizard works by piecing together bits of code according to the options that you select. Therefore, if you
know exactly what code AppWizard adds into a project to support the feature that you require, you will be able
to paste the feature in yourself. Visual C++ includes a tool called WinDiff that can help you do exactly that.
Follow these steps to add an AppWizard-generated feature to your existing MFC application:
1. use AppWizard to create a new project with exactly the same options you used to create the existing
project.
2. Next, create a second new project in a different folder with the same name and all the same settings but
also specify the option that you wish to add in (for example, Winsock support).
3. compare the two directories of the new projects using WinDiff. You'll be able to use the results of
WinDiff to discover which parts of the code from the second new project need to be copied into your original
project to implement the feature that you want to add.
Resource Editors
A Windows-based desktop application makes use of resources defined in a resource file, which is simply a text
Chapter 04: The User Interface
file with the extension .RC. A Windows resource file contains a script with various statements that define
resources. For resources that exist in separate files, such as icons and cursors, the script specifies the resource
and the file that contains it. For certain resources, such as string tables and menus, the entire definition of the
resource exists within the script. Visual C++ provides a rich set of tools to simplify the task of editing resource
files and visual elements, allowing the developer to easily use and enhance the initial user interface produced
by AppWizard.
Although Visual C++ provides many tools to edit resource files visually, there may be times when you want to
view the contents of your project resource file as text. For example, you may want to perform a multiple find
and replace of a string, or perhaps you are curious to see how much resource script the Visual C++ editors
automatically generate for you. You could, of course, open the .RC file in a simple editor such as notepad, but
the file can also be opened as text within Developer Studio. Developer Studio will display it with full-color
coding and give you all the benefits of the Developer Studio environment, such as the Find and Replace dialog
box.
To open a resource file (.RC) as text, follow these steps:
1. From the File menu choose Open, and use the open dialog box to navigate to the resource file (.RC) that
you wish to view.
2. From the Open as drop-down list, select Text and click the Open button.
It is understood that any manual modification of Visual C++-generated resource scripts should be performed
with great care.
The ResourceView Tab
Now that youve looked at the underlying content of an AppWizard-generated resource file, the next logical
step is to review the tools available within Visual C++ to make editing of your desktop applications resources
as painless as possible. To see all of your applications resources represented in the Visual C++ ResourceView
tab, use the MFC AppWizard to create a new project, and click the ResourceView tab at the base of the Project
Workspace window. You will see a list of the project resources, as Figure 4-17 shows.
Figure 17: The ResourceView allows you to view your project resources
Expanding the folder for each resource type shows the individual resources of that type in your project. You
can right-click this window to bring up a shortcut menu of commands. you can double-click any resource to
Chapter 04: The User Interface
invoke its resource editor. Right-clicking a resource displays a context menu that allows you to insert new
resources. When you select Insert from this context menu, you are presented with the Insert Resource dialog
box shown in Figure 4-18. this dialog box is also available by selecting Resource from the Insert menu.
Alternatively, the context menu will always have a command that allows you to immediately create a new
resource of the type on which you right-clicked.
Figure 18: The Insert Resource dialog box lists the various types of resources that you can create in Visual C++
When a new resource is added to your project, it is automatically given a unique name. For example, a new
dialog box resource may be given the name IDD_DIALOG1, then the next dialog box resource added to the
project will be called IDD_DIALOG2. It is common convention, however, to change the generated name to
one that more accurately reflects the purpose of the particular resource in the context of your application. To
view the names of all the resources in the project, select Resource Symbols from the View menu. The Resource
Symbols dialog box is shown in Figure 4-19.
Figure 19: The Resource Symbols dialog box can be used to find a resource from its symbolic name
On occasion, you may find it convenient to use the Resource Symbols dialog box to locate a particular resource
from its symbolic name. When you have located a resource in the Resource Symbols dialog box, you can go to
it by selecting the name in the list and clicking the View Use button.
In the following sections, we will briefly describe each of the types of resources that can be created and look at
their respective resource editors.
Accelerator Editor
An accelerator table contains a list of accelerator keys (or shortcut keys) and the command identifiers that are
Chapter 04: The User Interface
associated with them. A program can have more than one accelerator table. Accelerators are usually used as
keyboard shortcuts for program commands that appear on your application's menu or toolbar. However, they
can also be used to define key combinations for commands that dont have a corresponding user-interface
object. Figure 4-20 shows the Accelerator editor.
Figure 20: Use the Accelerator editor to edit accelerator table resources
You can perform the following actions with the Accelerator editor:
View, add, edit, and delete accelerator key assignments on individual or multiple accelerator keys
View and change the resource identifier associated with each entry in the accelerator table. The identifier
is used to reference each accelerator table entry in your code.
Associate an accelerator key with a menu item
You can display the Accel Properties dialog box shown in Figure 4-21 by double-clicking an accelerator key,
or from its context menu. This property page allows you to control the values associated with each accelerator
key.
Figure 21: The Accel Properties dialog allows you to edit accelerator keys
Exam Watch: To associate a menu item with a keyboard combination, simply assign the same resource
identifier to both the menu item and the relevant entry in the accelerator table. It's often appropriate to edit the
menu item's caption to show the name of the accelerator, as this isn't done automatically. Refer to the section
on the Menu editor to see how to do this.
Binary Editor
The Binary editor, shown in Figure 4-22, allows you to edit resources at the binary level in either hexadecimal
format or ASCII format. it also can be used with the Find command to search for either ASCII strings or
hexadecimal bytes with the binary resource. Binary resources are usually custom resources, such as WAV files,
for which native editing support isn't provided by the Visual C++ environment. For this reason, it may not
always be the most appropriate tool to use for such resources, and incorrect editing of the resource at the binary
level could cause the resource to be corrupted.
Chapter 04: The User Interface
Figure 22: The Binary editor lets you edit custom resources
You can bring a new custom resource into your project by placing the resource in a separate .RC file using
normal resource script file syntax, and then including that file by using the Resource Includes command from
the View menu. When the Resource Includes dialog box, shown in Figure 4-23, is displayed, you can type an
#include statement in the Compile Time Directives edit box that gives the name of the file containing your
custom resource. For example, you could type #include myres.rc.
Figure 23: The Resource Includes dialog box allows you to insert custom resources into your project
Take care to ensure that the spelling and the syntax of all entries in the Compile Time Directives edit box are
accurate, because this text is copied directly into your project's resource script.
Dialog Editor
The Dialog editor, shown in Figure 4-24, can be used to create or edit dialog boxes. Dialog boxes that you
create can be stored as templates so that you can reuse them.
Chapter 04: The User Interface
Figure 24: Use the Dialog editor to create and edit dialog boxes
The Dialog editor allows you to perform the following tasks:
Add, arrange, or edit controls on a dialog box
Change the tab order of controls on a dialog box
Use guides in the dialog box layout to position controls precisely
Preview the dialog box as it will appear when your application is running
Create message handlers for the dialog box and its controls
Jump to the code that implements the dialog box and its controls
You can add controls to a dialog box by using the Controls toolbar, which enables you to choose the control
that you want and then drag it to the dialog box. You can also add additional ActiveX controls to the Controls
toolbox by using the Insert ActiveX Controls command from the context menu of the Dialog editor. You can
change the properties of controls that are in your dialog box by using the controls property page. The property
page for a control can be displayed by selecting Properties from the context menu of the control. You can also
select multiple controls and change their common properties all at the same time.
Double-clicking a dialog box control will take you to the handler code for that control. If a handler function
didn't already exist, then a stub handler function will be created. In addition, you can double-click the dialog
box itself to jump to its class definition. Windows controls usually have a range of events and messages
available to them, you can create and edit handler functions for these events by selecting the Events item from
the context menu for the control.
To preview some of the run-time behavior of your dialog box, select Test from the Layout menu. This can
speed up the process of building a dialog box by giving you immediate feedback on how the dialog box will
look and feel to the end user.
Graphics Editor
The Graphics editor, shown in Figure 4-25, has an extensive set of tools for creating and editing bitmaps, icons,
and cursors, as well as integrated features to support the creation of toolbar bitmaps. In addition to creating and
editing images in bitmap format, you can edit bitmap images and save them in GIF or JPEG format. You can
also convert images in GIF or JPEG format to bitmap format.
Chapter 04: The User Interface
Figure 25: The Graphics editor is shown here editing an icon resource
Within the Graphics editor workspace, the Image Editor window shows two views of your image resource. The
size of the two panes can be adjusted by the split bar that separates them. Also within the Graphics editor is the
Graphics toolbar, which consists of the following two sections:
A toolbar, which contains various tools, shapes, and brushes for drawing, painting, entering text, erasing,
and manipulating views
An option selector, which can be used to select brush widths and other drawing options
In addition, the Graphics editor provides the Colors palette, which consists of an indicator showing the current
foreground and background colors and selectors for screen and inverse colors. It also has a range of colors from
which to select the foreground and background colors. The foreground color is selected by clicking a color in
the Colors palette. a background color is selected by right-clicking a color in the Colors palette.
On the Job: When creating images for an application that you plan to distribute internationally, it is important
to take into account various localization issues. It can be challenging to design bitmaps that are simple and
specific enough to identify a command and at the same time ensure that they avoid cultural references and
stereotypes that could offend international users. You could keep separate versions of bitmaps for different
language editions of your application; however, this can be very time consuming. A better approach may be to
take advantage of the common toolbar buttons defined for Windows or to use internationally recognized
symbols, such as those used on road signs or in airports.
Another internationalization issue to keep in mind when using image resources is that it is generally best to
keep images free of letters that represent the first letters of commands, such as B for Bold. You certainly
should not include text in images unless the text is not intended to be translated (for example, a company
name). An alternative might be to retrieve the text from a locale-specific string table and use Win32 API calls
to draw the text onto the image.
HTML Resources
A Hypertext Markup Language (HTML) resource is an HTML file that is stored and compiled as part of your
resource script. When you create a new HTML resource, Visual C++ includes it in the resource script of the
active project, providing you with easy access to the HTML page.
HTML resources were introduced to support the CHtmlView class; however, you can insert them into any
project and use them as you would any other resource. With the HTML resource editor, you can create an
HTML page using the text editor's native support for syntax coloring of HTML tags. Figure 4-26 shows an
HTML page being edited in the text editor. You can easily preview the page as you develop it by selecting
Preview from the context menu that appears within the text editor.
Chapter 04: The User Interface
Figure 26: The Text editor natively supports syntax coloring for HTML resources
When you create a new HTML page or import an existing one, if your page contains bitmaps or other such
graphics, you should be sure to import the relevant images into your project's resource script. This ensures the
availability of the images when the application is run on the end user's PC. You should use the res:// protocol
to display such graphic images in your page. The res:// protocol supports the retrieving and displaying of a
resource that resides in a compiled .DLL or .EXE module.
Menu Editor
Windows menu resources allow you to arrange commands in a logical, easy-to-find fashion. With the Menu
editor, shown in Figure 4-27, you can create and edit menus by working directly with a menu bar that closely
mimics the behavior of the menu as it would appear in the finished application.
Figure 27: The Menu editor creates and edits menu items while emulating the run-time behavior of your
application's menu bar
With the Menu editor, you can perform the following tasks:
Create standard menus and commands
Move menus or commands from one place to another
Edit the properties of several menu items at the same time
Double-clicking a menu item displays the Menu Item Properties dialog box. From there, you can change many
properties of the menu item, such as whether it is checked, inactive, or unavailable. You can also set the
caption of the menu item from the Caption field in the Properties dialog box. Following the menu caption text,
you can type the tab escape character (\t), followed by text representing the menus accelerator keys. At run
time, this will show the menu's caption in the format familiar to users, where the menu caption text is
left-aligned and the text describing the accelerator keys for the menu is right-aligned.
Adding new menu items is simple using the Menu editor. All you have to do is select the new item box (the
Chapter 04: The User Interface
empty rectangle) on the menu bar, or use your mouse to move the new item box to the appropriate position and
type the menu item's caption. Note that when you are typing the caption, you can define a mnemonic key that
allows the user to select the menu with the keyboard. to do this, type an ampersand (&) in front of a letter to
specify it as the mnemonic, then at run time, that letter will appear underlined. You should take care to ensure
that all the mnemonics on a menu bar are unique.
String Editor
A string table is a Windows resource that contains a list of IDs, values, and captions for all the strings of your
application. For example, the status bar prompts that appear as your mouse moves over menu items are located
in the string table. String tables make it easy to localize your application into different languages. If all text that
could be displayed in your application is kept in a string table, you can localize the application by translating
the strings and still maintain common source code for international editions of the application.
With the String editor, shown in Figure 4-28, you can edit your application's string table resource. In a string
table, strings are grouped into segments, or blocks, of 16 strings each. The segment that a string belongs to is
determined by the value of its identifier. For example, strings with identifiers of 0 to 15 are in one segment,
strings with identifiers of 16 to 31 are in a second segment, and so on. Thus, to move a string from one segment
to another you only need to change its identifier.
Segments of the string table are loaded into memory on demand. For this reason, it is a good idea to try to
organize your application's string resources into logical groups within 16-string segments that are likely to be
required at the same time. This ensures that memory is used as efficiently as possible by not keeping the entire
string table in memory when only a few strings may be required at any given time.
Figure 28: The String editor lets you create and edit string resources
Double-clicking a string in the String editor will display its property page, which allows you to edit the string's
ID or caption. You can also select multiple strings and change their properties all at the same time.
Version Information Editor
A version resource consists of company and product identification such as a product version number, and
copyright and trademark information. The Version Information editor, shown in Figure 4-29, is a tool for
creating and maintaining this data.
Chapter 04: The User Interface
Figure 29: The Version Information editor allows you to embed information, such as your company name, into
your application
A Windows-based application isn't required to contain version information to run, but it would be
unconventional not to have a version resource. Note that the Windows standard name for an application version
resource is VS_VERSION_INFO. The known formatting of version resources allow the version information to
be accessed from other applications. In order to access your application's version information
programmatically, you should use of the GetFileVersionInfo and VerQueryValue Win32 APIs.
Using ClassWizard
Most developers spend a significant amount of time in the early stages of a desktop project working
exclusively on the visual elements of their application before moving on to the application-specific
functionality. At some stage in the development process, it is necessary to hook-up the user interface objects to
the core functionality of the application. Visual C++ provides a reliable framework within which to achieve
this. The principle that tool Visual C++ provides to you to perform these tasks is ClassWizard.
Some of the operations that ClassWizard assists you with include creating new classes, defining message
handlers, creating virtual function overrides, and mapping data from dialog box controls to class members.
ClassWizard only works with MFC applications.
Chapter 04: The User Interface
Figure 30: Use the MFC Class Wizard to create new classes, define message handlers, override virtual
functions, and gather data from controls
The user interface of ClassWizard is a tabbed dialog box, as shown in Figure 4-30. you can access ClassWizard
by selecting ClassWizard from the View menu. The following list describes the use of each tab:
Message MapsUse the Message Maps tab to browse the messages that a class can handle and to create,
edit, and delete the member functions mapped to the messages. You can also use the Edit Code button to jump
straight to a message handler function's code.
Member VariablesUse the Member Variables tab to bind member variables to dialog, form view, or
record view controls. You can also bind record view member variables to both record view controls and to the
columns of a table in your data source.
AutomationUse the Automation tab to create and edit the Automation aspects of your application. For
example, you can create Automation properties and methods that allow other applications to control your
application.
ActiveX EventsIf your project includes a class that implements an ActiveX control, you can use the
ActiveX Events tab to specify which actions will cause events to fire in your ActiveX control. For example,
you can specify that an event will be raised in the control's container in response to a user's mouse-click.
Class InfoUse the Class Info tab to browse and set general class options. You can set the message filter
to determine what messages ClassWizard offers to map to handlers. You can also view or set a foreign object
associated with your dialog form view or record view class.
In addition, on every tab of the ClassWizard is the Add Class button. This button allows you to create a class,
import a class from a file, or import a class from an ActiveX type library.
Adding Member Variables
You can use ClassWizard to add member variables to dialog classes to represent the dialog box's controls. The
mechanism of mapping a dialog control to a dialog class member variable is called Dialog Data Exchange
(DDX). DDX eliminates the need for you to transfer data between the control and its corresponding member
variable yourself.
We will do an exercise now that demonstrates creating a simple dialog resource and associating it with a dialog
class based on CDialog that includes member variables that map to each of the controls in the dialog resource
through DDX.
Chapter 04: The User Interface
For each dialog box in your application, you need to have a dialog box resource and a dialog box class. The
resource script commands making up the dialog box resource are interpreted to determine how the dialog box
should be drawn on screen when your application is running. The dialog box class contains member variables
that hold the values of the controls in your dialog box and it also contains member functions that create and
show your dialog box. The dialog box resource is built with the dialog resource editor. ClassWizard is used to
create and manage the dialog box class.
To start the exercise, use AppWizard to create a new SDI MFC executable application. select the
ResourceView tab from the project workspace and choose Insert from the context menu that appears when you
right-click inside the ResourceView tab. The Insert Resource dialog box will appear. From this dialog box,
select Dialog and click New or double-click Dialog. A simple dialog box with an ID of IDD_DIALOG1 should
appear in the dialog resource editor, as shown in Figure 4-31.
Figure 31: The Dialog resource editor lets you add user interface elements to a dialog resource
Now display the Properties dialog box by right-clicking somewhere inside the dialog box and selecting
Properties from the context menu. The Properties dialog box, shown in Figure 4-32, is used frequently when
modifying a dialog box resource. Because of this, you might find it useful to click the pushpin button in the
top-left corner, which will cause the Properties dialog box to become a modeless dialog box that will float on
the screen while the dialog resource editor is open. Using the Properties dialog box, change the ID of the dialog
box resource to IDD_TESTDIALOG and change the Caption to Test Dialog.
Figure 32: The Properties dialog box lets you change values that affect the appearance of the dialog box
resource
You can add controls to your dialog box resource by dragging and dropping them from the control palette,
Chapter 04: The User Interface
which is pictured on the right side of the resource editor workspace in Figure 4-31. Because the purpose of this
exercise is to demonstrate ClassWizard functionality rather than how to use all of the common user interface
elements, we'll keep this dialog box simple by just adding a single Static Text control and a single Edit Box
control. Use your mouse to drag each of those controls to somewhere in the middle of your dialog box. Select
Static Text and use the Properties dialog box to change its caption to say Enter some text:. Now select Test
from the Layout menu and you'll be presented with a preview of the dialog box, which should look something
like Figure 4-33. You can close the preview dialog box by clicking either of its command buttons.
Figure 33: The preview of your dialog box as it will appear in your running application
Now that the dialog resource is complete, its time to create the dialog class. Bring up ClassWizard by
choosing ClassWizard from the View menu or by double-clicking somewhere within the dialog box in the
resource editor. ClassWizard knows that you haven't yet defined a dialog class for this resource and so it offers
to create one for you, as in Figure 4-34.
Figure 34: ClassWizard offers to create a dialog class for your new dialog resource
Accept the default option of creating a new class and click OK. The New Class dialog box will appear as in
Figure 4-35. Give your class a class name of CTestDialog. Notice that the base class for this dialog will be the
MFC CDialog class and that ClassWizard has already associated your dialog's resource symbol with the new
class. When you click OK to create the class, two new files will be created in the directory in which your
project resides, TestDialog.cpp and TestDialog.h.
Chapter 04: The User Interface
Figure 35: The New Class dialog box enables you to create a new class based on CDialog
Now you can use the Member Variables tab of ClassWizard to connect the dialog box controls to member
variables in your class. The Member Variables tab of ClassWizard, in Figure 4-36, shows a list of the control
IDs for the dialog resource associated with the dialog class displayed in the Class Name combo box.
Figure 36: The Member Variables tab of ClassWizard enables you to connect dialog controls to member
variables
We'll now connect a member variable to the Edit Box on our dialog box by highlighting IDC_EDIT1 in the
Control IDs list and clicking the Add Variable button. The Add Member Variable dialog box shown in Figure
4-37 will be displayed. In the member variable name field, give the variable the name m_EditBox. You'll
notice that ClassWizard suggests a prefix of m_ for the variable; this is the convention that is used to identify
member variables in MFC applications. The Category combo box lets you specify whether this is a value
variable or a control variable. For standard Windows controls such as the Edit Box, you should choose Value
Chapter 04: The User Interface
to create a variable that will contain the text or status of the control as entered by the user. the type of the
variable is determined by your selection in the Variable Type combo box. If you choose Control from the
Category combo box, the Variable Type will be a class such as CEdit that wraps the functionality of the
control. For this exercise, choose Value from the Category combo box and CString from the Variable Type
combo box. click OK to create the variable.
Figure 37: The Add Member Variable dialog box is where you define the new member variable
Once the variable m_EditBox is associated with the IDC_EDIT1 resource, if you highlight it in the Control IDs
list, you'll see a field labeled Maximum Characters appear at the bottom of the Member Variables tab of
ClassWizard. This allows you some control over the validation of the data entered into the control by limiting
the length of the text that a user is able to enter into the text box when the application is running. Enter a value
of 20 into this field and then click OK to close ClassWizard.
Now that the dialog resource and corresponding dialog class have been created, all that remains is to use the
dialog box in the application. In the next section, we'll see how to show the dialog box in response to a menu
item being selected.
Adding a Message Handler for an Event
Windows-based applications are message driven. This means that for every event such as a mouse-click or a
keystroke, Windows sends messages to the appropriate windows. The MFC framework processes Windows
messages, and in doing so provides some enhancements that make processing messages easier, more
maintainable, and better encapsulated.
The main application object of an MFC application is an instance of CWinApp. This class contains a member
function called Run, which is responsible for retrieving queued messages. The message loop in the Run
member function of class CWinApp retrieves queued messages generated by various events and dispatches
them to the appropriate window. In an MFC application, a dedicated handler function processes each separate
message. Such message handler functions are member functions of a class.
Each class in the MFC framework that is able to receive messages has a message map. Message maps are used
to connect messages and commands to their appropriate handler functions. All classes derived from the
CCmdTarget base class can have message maps. When such a class receives a message, it searches its message
map for an appropriate handler. If it finds one, it calls it; otherwise, it will probably route the message to
another command target.
After generating a new application using the MFC AppWizard, you'll find some message maps already defined
for you in the command target classes which may look something like the following listing:
BEGIN_MESSAGE_MAP(CMFCWizApp, CWinApp)
//{{AFX_MSG_MAP(CMFCWizApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard file based document commands
Chapter 04: The User Interface
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
The message map consists of several macros. Two macros in particular, BEGIN_MESSAGE_MAP and
END_MESSAGE_MAP, define where the message map starts and ends. There are many other macros such as
ON_COMMAND that make up the content of the message map. You'll also notice comments in the message
map that include tags such as AFX_MSG_MAP. These comments are used by ClassWizard to determine which
message map entries it is managing.
On the Job: You'll rarely, if ever, need to edit the message map entries between the ClassWizard
AFX_MSG_MAP tags. In fact, doing so could prevent ClassWizard from being able to read the message map
at all. Many a developer has experienced grief while attempting to bypass ClassWizard and edit these entries
directly.
Your implementation of a message handler function is your opportunity to respond to the message in whatever
way is appropriate for your application. ClassWizard assists by creating the stubs of the message handler
functions for you. It also allows you to logically navigate within your source code by jumping straight to the
appropriate handler for various user interface elements such as menu items.
In working with the MFC framework, you'll find that ClassWizard greatly simplifies the task of managing
numerous handlers for Windows messages. Changes you make in ClassWizard affect your source files in the
following ways:
Message map entries are written to connect the handler function to the message.
A message handler function is declared as a member of the class.
A stub is created for the handler function where you can write your code to handle the message.
Continuing with the dialog box exercise that we created in the previous section on adding member variables,
we'll create a menu item that, when selected, will show the dialog box. To start off, open the project workspace
from the previous exercise. The first thing we need to do is to add a menu item that will be used to show the
dialog box. To display the menu resource editor, go to the ResourceView tab of the project workspace and
expand the Menu folder. double-click the IDR_MAINFRAME resource. When the menu editor is open, use
your mouse to click the View menu item and then double-click the blank menu item in your view menu's
drop-down menu. When the Menu Item Properties dialog box is displayed for the new menu item, assign it an
ID of ID_VIEW_TEST_DIALOG. enter the caption as Test&Dialog, and in the prompt field enter Display
the Test Dialog. When you are done, the Menu Item Properties dialog box should resemble Figure 4-38.
Figure 38: Use the Menu Item Properties dialog box to select the properties of a new menu item
After closing the Properties dialog box for this new menu item, you will see it displayed in the menu editor.
Right-click it in the menu editor and select ClassWizard from the context menu. When ClassWizard is
displayed, go to the Message Maps tab and in the Class Name combo box, select the class that is derived from
CWinApp in your application (if you selected the AppWizard defaults when creating your project this will be
the class with a name ending in App). Now select ID_VIEW_TEST_DIALOG from the Object IDs list box.
This list box shows all of the objects in the current class that are able to generate messages. The list box labeled
Messages shows the messages that the selected object can handle and any MFC virtual functions that can be
overridden. If a message in this list already has a handler function associated with it, the message will be
displayed in bold. For the ID_VIEW_TEST_DIALOG menu item, select the message called COMMAND. The
ClassWizard should look like Figure 4-39.
Chapter 04: The User Interface
Figure 39: The Message Maps tab of ClassWizard is where you can create handler functions
Now click the Add Function button to display the Add Member Function dialog box, as shown in Figure 4-40.
Accept the default function name of OnViewTestDialog and click OK.
Figure 40: The Add Member Function dialog box suggests a name for the new member function
when you click the Edit Code button, ClassWizard will close and you'll be taken to the source code editor in
the function stub that has been created for you. Complete the implementation of the function so that it is the
same as the following listing:
void CMFCWizApp::OnViewTestDialog()
{
CTestDialog testDlg;
testDlg.DoModal();
}
Now in order for the compiler to recognize an object of type CTestDialog, you must include the header file for
the dialog class in the header file of the class to which this handler function belongs. Go to your
CwinApp-derived classes header file by selecting the ClassView tab in the project workspace and
double-clicking the name of the appropriate class (as previously explained, it will probably be the class with a
name ending in App). When the appropriate header file is displayed, go to the top of the file and type the
following line of code after any other #include statements that appear there: #include "TestDialog.h".
You'll now be able to recompile and run the application by selecting Build and then Execute from the Build
menu. When the application runs, you'll be able to go to the View menu of your application and select Test
Dialog and you should see the dialog box modally displayed as in Figure 4-41.
Chapter 04: The User Interface
Figure 41: The Test Dialog has been launched by the message handler function that ClassWizard set up
The Test Dialog doesn't do anything at the moment, so to finish the exercise we'll add a message handler
member function to the CTestDialog class. This message handler function responds to the user clicking OK in
the dialog box and displays any text that the user may have entered in the Edit Box. Perform the following
steps to add a message handler function for the OK button in the CTestDialog class:
1. Open ClassWizard and go to the Message Maps tab.
2. Select CTestDialog from the Class Name combo box.
3. Select IDOK from the Object IDs list.
4. Select BN_CLICKED from the Messages list.
5. Click the Add Function button and accept the default function name, OnOK, in the Add Member
Function dialog box by clicking OK.
6. Back in the Message Maps tab of ClassWizard, click the Edit Code button. You'll be taken to the message
handler function stub in the TestDialog.cpp file.
7. Edit the implementation of the function so that it resembles the following listing:
void CTestDialog::OnOK()
{
// TODO: Add extra validation here
CDialog::OnOK();
AfxMessageBox(m_EditBox);
}
Notice that this function calls the base classes implementation of OnOK, which in turn calls DoDataExchange.
The DoDataExchange function performs the DDX for this CDialog-derived class so that when
AfxMessageBox is called, the m_EditBox member variable will contain the value that had been entered in our
dialog box's Edit Box with the resource ID IDC_EDIT1.
You should now be able to recompile and execute your application again. This time when you display Test
Dialog and enter something into its edit box, if you click OK to dismiss the dialog box you'll see a message box
containing the text that you entered, just like in Figure 4-42.
Chapter 04: The User Interface
Figure 42: A message box from the message handler of our dialog box's OK button
From the Classroom
Enhancing User Interface Navigation Coding through Dynamic Menus
In this chapter, you were introduced to menus and you learned how to define menus at design-time using the
resource editor. When developing an intuitive, user-friendly interface it is sometimes desirable to change the
menu items that the user sees based on the activity that the user is currently performing within the application.
In order to make your menus context-sensitive, it may be necessary to implement dynamic menus. We will
discuss the first step in creating a dynamic menu: consolidating handlers into a command range.
When adding and removing menu items while your application is running, you will benefit from learning how
to consolidate handlers into a command range. When implementing command handlers for your menu items,
you may find that many command handlers are performing the same, or very similar, functions. Instead of
writing individual command handlers for each menu item, a command range can be used to map several menu
items to a range of messages.
To consolidate command handlers, first determine the maximum number of new message entries, and add
symbolic constants in the resource table for each message entry. To do this, open the Resource Symbols dialog
box from the view menu, and select New. In the New Symbol dialog box, specify a name and a value for the
menu item. Repeat this for each item that you want to include in the range. Be sure to use consecutive numbers
greater than 33,000 for the resource symbol values. Using numbers greater than 33,000 avoids conflicts with
any predefined or existing messages.
Next, add an ON_COMMAND_RANGE entry, an option not available through the ClassWizard, to the
message map of the class that you want to receive the commands from the dynamic menu. Specify the first and
last numbers of the range that you entered in the resource symbols table as the first and second arguments of
the ON_COMMAND_RANGE macro, for example: ON_COMMAND_RANGE( ID_VIEW_ITEM1,
ID_VIEW_ITEM4, OnNewItems).
you will need to add an entry to the class's header file in the DECLARE_MESSAGE_MAP section, such as the
following example:
afx_msg void onNewItems( UINT nID );
To complete the process of adding menu items dynamically, you will need to add entries to the string table to
store your menu captions, write the code that adds your menu items, write the code to accept the commands
generated by the added menus, and add an entry to the header file for the class. When designing your
application's user interface, start by utilizing the code generated by the MFC AppWizard and the ClassWizard,
then add some "bells and whistles", such as context-sensitive menus, to make your interface professional and
polished.
Michael Lane Thomas, MCSE+I, MCSD, MCT, MCP+SB, MSS, A+
Certification Summary
This chapter has demonstrated the tools available in Visual C++ that aid the developer in creating the visual
elements of an application. We looked at how two of Developer Studio's most significant wizards, AppWizard
and ClassWizard can make it easier to develop Windows-based applications.
Chapter 04: The User Interface
You've learned how to create and use MFC toolbars and status bars in your applications, as well as how to use
the various resource editors available in the Visual C++ environment. These resource editors assist you in
creating common Windows user interface elements.
We used AppWizard to create a new MFC application and then learned how to map messages to member
functions through ClassWizard. We also examined how ClassWizard is used to create member variables in a
dialog class that are connected to controls in a dialog resource.
Two-Minute Drill
One of the biggest challenges in designing and implementing a desktop application comes in the creation
of an effective user interface. The design of your application's interface can affect how a user perceives your
software more than any other factor.
Careful planning is required to ensure that the user interface exposes all the functionality of your
application while being intuitive and simple enough to allow the end user to quickly learn the application.
A toolbar is a special organizational visual element that can manage sets of other controls such as buttons,
button separators, and combo boxes. The primary role of toolbars in desktop applications is to provide quick
access to commonly-used functions.
Toolbars are usually positioned at the top of the client area of a main application window. Often,
however, toolbars are designed to be dockable, whereby the user can drag and place them on any border of the
application's top-level window or leave them in their own modeless window at any location on the screen.
All of the buttons of a toolbar resource are actually stored in a single bitmap. In an MFC project, the
bitmap for the initial AppWizard-generated toolbar is stored in the project's res subdirectory with the name
Toolbar.bmp.
Often you'll want to add text to your toolbar buttons in the same way Internet Explorer has text captions
for its toolbar buttons. Unfortunately, the toolbar editor doesn't provide any support for this, so you'll need to
use the SetButtonText function from within your code.
Toolbars also include ToolTips, which are small modeless windows that are briefly displayed when the
mouse lingers over a button for a certain interval. ToolTips are used to proactively give the user some feedback
about the purpose of a button.
Status bars give your application a place to display messages and useful information to the user without
interrupting the user. They are normally displayed at the bottom of a window and they consist of several panes,
which can include indicators and a message line.
AppWizard helps you generate the basic source files for a variety of different types of Windows-based
programs, allowing you to get down to the task of creating your application. The extensive amounts of
AppWizard-generated code handles many routine programming tasks, freeing the developer to concentrate on
implementing program functionality.
The final step of the MFC AppWizard involves reviewing and confirming the names, filenames, and base
classes of the classes that AppWizard will generate.
By default, AppWizard creates names for your application classes and files based on an abbreviation of
your project name. The majority of the time, you won't want to change the default names.
A Windows-based desktop application makes use of resources defined in a resource file, which is simply
a text file with the extension .RC. A Windows resource file contains a script with various statements that define
resources.
When a new resource is added to your project, it is automatically given a unique name. For example, a
new dialog box resource may be given the name IDD_DIALOG1, then the next dialog box resource added to
the project will be called IDD_DIALOG2. It is common convention, however, to change the generated name to
one that more accurately reflects the purpose of the particular resource in the context of your application.
To associate a menu item with a keyboard combination, simply assign the same resource identifier to
both the menu item and the relevant entry in the accelerator table. It's often appropriate to edit the menu item's
caption to show the name of the accelerator, as this isn't done automatically.
At some stage in the development process, it is necessary to hook-up the user interface objects to the core
functionality of the application. Visual C++ provides a reliable framework within which to achieve this. The
principle that tool Visual C++ provides to you to perform these tasks is ClassWizard.
The mechanism of mapping a dialog control to a dialog class member variable is called Dialog Data
Chapter 04: The User Interface
Exchange (DDX). DDX eliminates the need for you to transfer data between the control and its corresponding
member variable yourself.
Windows-based applications are message driven. This means that for every event such as a mouse-click
or a keystroke, Windows sends messages to the appropriate windows.
Each class in the MFC framework that is able to receive messages has a message map. Message maps are
used to connect messages and commands to their appropriate handler functions.
return TRUE;
}
8. Create and display a dialog object. Once the dialog box has been dismissed, read the value from the member variable
before the object has been destroyed:
New Page 7
CTestDDXDlg dlg;
int iRes;
CString sQuant;
iRes = dlg.DoModal();
if (iRes == IDOK) {
sAuth = dlg.m_sAuthorizedBy;
}
else {
// Dialog was canceled
sAuth = Not Applicable// Set a default value
}
Storing and Retrieving Personalized User Settings from the Registry
Often it is desirable to store application settings on a per-user basis; when a particular user logs onto a machine and runs an
application, they will find the settings restored to the same state as when they last used the application. This is achieved by
storing the settings in the HKEY_CURRENT_USER hive of the Registry; usually as values under the key
HKEY_CURRENT_USER\Software\CompanyName\ApplicationName\SectionName\.
MFC provides a very simple mechanism for reading and writing personalized user settings to and from the registry; several
member functions of the CWinApp class are provided to do just that. The steps to achieving this are as follows:
1. Create your MFC application using the MFC AppWizard.
2. Your application will contain a class derived from CWinApp, for example CMyProgramApp. In the InitInstance()
member of this class, there will be an AppWizard-generated line of code that calls SetRegistryKey() and passes in some
default text. Modify this line to set the name of your company:
SetRegistryKey(_T("ACME Software Company"));
3. Integer values can be read from the registry using CWinApp::GetProfileInt(), and string values can be read from the
registry using CWinApp::GetProfileString().The following code could be placed in the InitInstance() method of your
CWinApp-derived application class, after the call to SetRegistryKey(): The following code could be applied when a user
selected some new settings, such as in the handler for an Apply button on a property sheet:
// Restore the user's settings from the registry
int nHeight;
CString sMessage
nHeight = pMyApp->GetPRofileInt("Window Settings", "Height", 500); /* 500 is a default */
sMessage = pMyApp->GetPRofileString(("Window Settings", "Startup Message", "Hi"); /* "Hi" is a default */
Integer values can be written to the registry usingCWinApp::WriteProfileInt(), and string values can be written to the registry
using CWinApp::WriteProfileString(). The following code could be applied when a user selected some new settings, such as
in the handler for an Apply button on a property sheet:
int nHeight;
CString sMessage
...
// User selects a value of 600 for window height,
// and "Good Morning" for startup message
// Store these settings in the registry
pMyApp->WriteProfileInt("Window Settings", "Height", nHeight);
pMyApp->WriteProfileString("Window Settings", "Startup Message", sMessage);
Implementing Online User Assistance in an Application
In developing desktop applications, you will generally want to provide one or more forms of user assistance; Visual C++
provides several mechanisms for you to do this. Status bars can be used to provide feedback to users, tool tips can be
employed to pop up a concise piece of text explaining the function of a tool (a control or child window), and full-blown help
systems can be provided that use either WinHelp or Hypertext Markup Language (HTML) Help. It is also possible to link
from a WinHelp help system to a Web site that contains help files.
Status Bars
As covered in Chapter 4, status bars comprise a set of panes, each of which may display certain text that may be updated at
any time. An example of a status bar giving dynamic feedback to a user is shown in Figure 5-11; Internet Explorer provides
useful information in its status bar.
New Page 7
Figure 11: You can create status bars that provide dynamic feedback for user assistance
In order to change the text in a pane of a status bar, you use the SetText() method, passing in the text to be displayed, the
integer index of the pane to display it in, and a type. An example is:
myStatusBar.SetText(You may click Finish at any time, 0, SBT_NOBORDERS);
The following types are valid for the third parameter:
0 The text is drawn with a sunken look.
SBT_NOBORDERS The text is drawn without borders.
SBT_OWNERDRAW The text is drawn by the parent window.
SBT_POPOUT The text is drawn with a raised look.
Tool Tips
Tool tips are small boxes containing help text specific to a specific control or child window. As the mouse cursor pauses over
the tool the tool tip is displayed, giving the user potentially valuable information about the usage of the tool. As buttons with
only icons and without any textual description have become more popular, tool tips have become an essential device for a
user to learn how to use an application.
In Chapter 4 you saw how support for tool tips is included with MFC toolbar buttons. However, it is also possible to provide
tool tips for any other tools in your application. This is achieved by following these steps:
1. Construct an instance of a CToolTipCtrl object and call Create(), passing the parent window as a parameter:
CToolTipCtrl* pMyToolTipCtrl;
pMyToolTipCtrl->Create(pMyDialog);
2. Call AddTool() to register a tool with the tool tip control, so that the information stored in the tool tip is displayed when
the cursor is on the tool:
pMyToolTipCtrl->AddTool(pMyControl, This is my control!);
Context-Sensitive Help
Context-sensitive help comprises a set of hyperlinked help topics. Many of these topics can relate to a certain context within
an application; the context may be the top level of the application itself, the dialog box that the user is currently working
with, or maybe a particular control. The context-sensitivity comes in to play when the help for the particular part of the
application that the user is currently working with is displayed.
There are several ways for the user to access help from within your application:
F1 HelpThe user can press the F1 key from an active window, dialog box, or message box, or with a menu item or
toolbar button selected. This will invoke the appropriate Help topic relevant to the selected item. For menu items, help is
summoned for the item currently highlighted.
shift-f1 Help or Help modeHelp mode can be activated by pressing shift-f1, or clicking the Help toolbar button. In
New Page 7
Help mode, the mouse cursor changes to an arrow with a question mark and the user can click any window, dialog box,
message box, menu item, or toolbar button to activate specific help for that item. Help mode ends when either Esc is pressed,
Help is displayed, or the user switches to another application and back again.
Using the Help menuBy selecting a Help menu item, the user can activate the applications Help file. Figure 5-12
shows the result of selecting the Help topics menu item in an MFC application.
Figure 12: You can create context-sensitive Help in MFC applications
When you use the MFC AppWizard to create either an SDI or MDI application, you will be given the opportunity to add
context-sensitive help. In Step 4 of the AppWizard, select the check box labeled Context-sensitive Help. When you enable
this option, the AppWizard adds the following features to your application:
The main menu now includes a Help menu with several commands. Note that for an MDI application there will be
multiple copies of this menu; one for an application with no documents open, and one for each type of document that uses its
own menu structure.
Your CFrameWnd-derived class will contain several additional message-map entries which bind the f1 and shift-f1
commands to their respective command handlers. These are created by AppWizard and should not be modified. In a simple
SDI application these look as follows:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
// NOTEthe ClassWizard will add and remove mapping macros here.
// Do not edit what you see in these blocks of generated code !
ON_WM_CREATE()
//}}AFX_MSG_MAP
// Global help commands
ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder)
ON_COMMAND(ID_HELP, CFrameWnd::OnHelp)
ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp)
ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder)
END_MESSAGE_MAP()
The base class CWinApp provides the WinHelp() method, which is responsible for invoking the Windows Help
program, WINHELP.EXE.
AppWizard also adds several skeleton .RTF files that contain Help entries for the common elements of the Windows
user interface, such as the File and Edit menus. You can edit these files to revise the supplied text and add your own
application-specific Help information. RTF files must be edited by an application that can edit the Rich Text Format;
Microsoft Word is such an application.
A mechanism and tool for mapping resource and command IDs in your application to Help contexts in Windows Help.
When you build your application, a tool called MakeHm is run to perform this mapping.
An .HPJ file is created by AppWizard, which serves as a Help project. This file will need to be recompiled whenever
New Page 7
you add new Help topics to your application.
Linking to a Web Page Containing Help Files
The emerging method of providing Help is HTML Help, which uses Internet Explorer functionality to display the Help.
HTML Help applications are compiled into a .CHM file. It is possible to link from a WinHelp topic to an HTML Help topic,
and it is also possible for the WinHelp topic to link to a .CHM file located on a Web site. To do this, you add a call to the
!execfile WinHelp macro to the link in the appropriate WinHelp topic:
!execfile(hh.exe, ms-its:http://www.mysite.com/MyHelpFile.chm::/MyTopic.htm)
Error Handling
No matter how much a programmer may believe otherwise, error conditions are to be expected in the use of any desktop
application, and the usefulness of an application will depend to a certain extent on how errors are handled. There are a couple
of methods of both raising and handling errors in a Visual C++ application; the most common methods are function return
values and C++ exceptions.
Exception Handling
Exceptions are error condition objects which are thrown by a function when an error condition is encountered. They are then
passed progressively back up the call stack until they are caught by some code that then handles the error, or else the
application will abort.
MFC provides two versions of exception handling; the MFC exception macros, which are provided for
backward-compatibility, and C++ exceptions, which are now the recommended mechanism. For the exam, you should
understand the C++ exception mechanism.
The base class for all MFC exceptions is CException; a number of other exception classes are derived from this, including
CMemoryException, COleException, and CInternetException. All of these classes include the following two methods:
GetErrorMessage() Retrieves the message describing an exception. This method takes as minimum
parameters a string buffer pointer and the size of the buffer.
ReportError() Reports an error message in a message box to the user; does not require any
parameters.
The steps for handling exceptions are as follows:
Any code that makes calls that may throw exceptions should be wrapped in a try block. As an example, the MFC file
class CFile constructor throws exceptions of type CFileException when error conditions are encountered:
CFile* pMyFile;
try
{
pMyFile = new CFile(C:\\Nonexistant File.txt, CFile::modeRead);
// This will throw an exception if the file does not exist
}
Follow the try block with one or more catch blocks for the appropriate exception types, or for CException to catch all
exceptions. The following code will display the message box as shown in Figure 5-13:
catch(CException* e)
{
e->ReportError(); // Displays a message box
e->Delete(); // Delete the exception when weve done with it
}
Figure 13: Message box produced by CException::ReportError()
If you wish to handle different kinds of exceptions selectively, use multiple catch blocks. Control will be passed to the
first catch block that matches the type of the exception.
catch(CFileException* fileException)
{
// Handle a file exception
New Page 7
fileException->Delete();
}
catch(CDaoException* daoException)
{
// Handle a DAO exception
daoException->Delete();
}
catch(CException* e)
{
// Default catch for all other exceptions
e->Delete();
}
Exam Watch: Make sure you are confident with multiple catch blocks for the exam. You should understand that a catch
block will catch any exceptions of the specified type, or of any type derived from that class. So catching exceptions of type
CFileException will catch any exception class derived from CFileException, and catching exceptions of type CException
will catch all exceptions, as CException is at the top of the exception class hierarchy.
Handle the exception appropriately. In this example, you would consider prompting the user for a new filename to load,
or ask the user if they would like to create the file.
Appropriate Deletion of Exception Objects
It is always safer to use the Delete() member of the CException class and its derived classes rather than the C++ delete
statement, as the exception object may not always have been created using new and so may not be on the heapin this case
the delete would fail. Also note that if your catch block re-throws the same exception object, you should not delete that
object; it should be deleted by the catch block that catches it further up the chain.
Determining How to Handle an Error
Whether errors have been thrown and caught as exceptions or passed back to the caller as return values, they need to be
handled in a fashion appropriate to the situation. There is no point in detecting that an error has occurred in the opening of a
file, only to go on and attempt to write to a file. Likewise, your applications users will not be very impressed if the
application aborts due to a trivial and noncritical error.
It is impossible to speculate about all of the different error scenarios that may arise in the applications you will build;
however, there are some basic rules to keep in mind:
Determine which error conditions users should be notified about.
Ensure the application cannot get into an inconsistent state.
Fatal errors, or errors from which you cannot recover, should cause the program to abort gracefully. A message box
should be displayed to inform users, and if possible any data should be saved prior to exit.
These rules on error handling are illustrated by some scenarios.
A user wishes to save a file to a pre-existing filename. Inform the user that the file exists and prompt them as to
whether they wish to overwrite the file.
A CFile object throws an exception during construction. Ensure that the program cannot go on to attempt to use
that object.
A fatal CMemoryException exception occurs. Inform the user of the reason that the application must
terminate and attempt to save data before exiting.
From the Classroom
Exploring exception handling strategy
With all of the time and effort you put into programming software's desired functionality, it is hard to swallow the fact that
about 30 percent of your final code will exist to handle undesired functionality, or error conditions. Considering the large
portion of code involved, the need for a planned approach to error handling is evident. There are several factors to consider
when constructing your error handling/recovery strategy.
Since exceptions do not have to be handled by the function in which they originate, one factor is simply deciding where the
exception will be handled. When an exception is thrown, the call stack is searched for the first handler with an argument that
matches the type of the exception. Let's walk through the steps that occur when a block of code within a try block executes,
so we can understand the stack unwinding process better.
The try block is entered as a part of the normal flow of execution in the application. Many functions can be called within a
try block, and these functions may throw the same or different types of exceptions. However, only one exception at a time
can be handled. If every function within the try block executes normally, the program will skip over the catch block(s)
following the try block, and continue executing.
New Page 7
If one of the function calls within the try block throws an exception, the exception will then search through the call stack for
a catch block that can handle it. First, the catch blocks following the try block will be searched, in order, for one with an
argument that matches the type of exception thrown. If no match is found, the exception will be thrown to the try block
encompassing the try block where the error occurred. That try block will then search through its catch blocks for a suitable
handler, and if a match is not found, the exception will be thrown to the try block encompassing it. This process continues
until the exception is either handled, or there are no more encompassing try blocks to which the exception can be thrown. If
the exception reaches this level, the process where the exception occurred will be aborted.
Once you decide where to handle an exception, the next consideration is deciding what code to put in the exception handler.
Besides sending error messages to the user, or reporting the error to an error tracking system, you need to look carefully at
what is skipped after an exception is thrown. It is very important to free allocated memory and close any open files. Using
the built-in features of the C++ language, the MFC Exception Classes, and a well thought-out error handling strategy, you
will be able to build a robust application that gracefully handles the majority of exceptions that can, and will, occur.
Michael Lane Thomas, MCSE+I, MCSD, MCT, MCP+SB, MSS, A+
Certification Summary
Data input forms and dialog boxes are created by editing dialog templates with the Dialog editor, and then using ClassWizard
to create classes derived from CDialog, CFormView, and CPropertySheet or CPropertyPage. ClassWizard can then be used
to configure dialog data validation, or DDV, as well as dialog data transfer, or DDX.
Personalized user settings for an application should be stored in the Registry under the HKEY_CURRENT_USER hive.
MFC provides facilities for reading and writing string and integer values to the Registry using member functions of the
CWinApp class.
Online user assistance can take a number of forms, including status bars, tool tips, context-sensitive WinHelp Help, and
HTML Help. Context-sensitive Help can be added to an application by choosing a setting in the MFC AppWizard. It is also
possible to link from a WinHelp topic to compiled HTML Help stored on a Web site.
Error handling is of great importance in a desktop application. There are several methods of passing errors back to calling
functions, including C++ exception handling. Depending upon the type of error, the application developer must decide the
appropriate method of handling it.
Two-Minute Drill
Using Visual C++ with Microsoft Foundation Classes (MFC), you have several options for creating these data input
windows: you can create a form that adheres to the document/view architecture by deriving a class from CFormView;
you can create a modal or modeless dialog box from a class derived from CDialog; or you can create a tabbed dialog
box, known as a property sheet, from a class derived from CPropertySheet.
The Visual C++ integrated development environment (IDE) provides a Dialog editor for editing dialog templates.
To make the Visual C++ developers job easier, the Dialog editor has been provided to allow drag and drop creation
of dialog templates. It provides for WYSIWYG, or what you see is what you get editing of the template, along with
property sheets for setting the general properties, such as dialog box size and the font to be used, as well as all of the
associated styles, such as border type.
Once you have created a dialog template you must create an appropriate C++ class and associate the template with
the class before it can be used in your application.
Be sure that you understand the distinction between dialog templates and the C++ classes that they are associated
with. A dialog template purely describes how the dialog box will look, how controls will be laid out on the dialog
box, and so on, whereas a C++ class provides the actual code that gives the dialog box functionality to be displayed,
respond to messages, validate user input and the like.
It has become customary for C++ programmers to name classes using a capital C as the first letter. If you follow
conventions such as these, your code will be much easier for other people to comprehend and maintain.
A property sheet is a tabbed dialog box, which is really a collection of dialog boxes laid over the top of each other
with each one being selectable by a tab.
The CFormView class provides the functionality for associating a dialog template with a view class, and allows you
to produce an application that combines dialog-style user input with standard application user interface elements such
as menus, toolbars, and status bars.
Visual C++ provides a mechanism known as dialog data validation, or DDV, which is configured through the
ClassWizard.
DDV, or dialog data validation, provides some fairly basic validation for controls that are mapped to either CString
or various numeric variable types.
Status bars comprise a set of panes, each of which may display certain text that may be updated at any time. In order
to change the text in a pane of a status bar, you use the SetText() method, passing in the text to be displayed, the
integer index of the pane to display it in, and a type.
Tool tips are small boxes containing help text specific to a specific control or child window.
The context-sensitivity comes in to play when the help for the particular part of the application that the user is
currently working with is displayed.
The emerging method of providing Help is HTML Help, which uses Internet Explorer functionality to display the
Help.
Exceptions are error condition objects which are thrown by a function when an error condition is encountered. They
are then passed progressively back up the call stack until they are caught by some code that then handles the error, or
else the application will abort.
New Page 7
Make sure you are confident with multiple catch blocks for the exam. You should understand that a catch block will
catch any exceptions of the specified type, or of any type derived from that class. So catching exceptions of type
CFileException will catch any exception class derived from CFileException, and catching exceptions of type
CException will catch all exceptions, as CException is at the top of the exception class hierarchy.
Whether errors have been thrown and caught as exceptions or passed back to the caller as return values, they need to
be handled in a fashion appropriate to the situation. There is no point in detecting that an error has occurred in the
opening of a file, only to go on and attempt to write to a file.
Data input forms and dialog boxes are created by editing dialog templates with the Dialog editor, and then using
ClassWizard to create classes derived from CDialog, CFormView, and CPropertySheet or CPropertyPage.
ClassWizard can then be used to configure dialog data validation, or DDV, as well as dialog data transfer, or DDX.
New Page 7
Chapter 6: Implementing ActiveX Controls
Certification Objectives. 1
Inserting a Control using Component Gallery. 3
ActiveX Control Properties. 8
Handling an Event from an ActiveX User Interface Control 12
Dynamically Creating an ActiveX User Interface Control 23
ISAPI Server Extensions. 33
ISAPI Filters. 33
Advantages of Using ISAPI DLLs. 34
Using the MFC AppWizard to create an ISAPI DLL. 35
Creating Secondary Threads. 48
Downloading ActiveX User Interface Controls. 50
Certification Summary. 55
Two-Minute Drill 56
Certification Objectives
Using an ActiveX User Interface Control
Using the Internet Server API
Incorporating Dynamic HTML Scriptlets
Invoking a COM Component
Adding Asynchronous Processing
Using an Active Document
In this chapter, well discuss Microsofts ActiveX technology. ActiveX is a set of technologies that enables software
components to interact with each other in a networked environment, regardless of the language in which they were
created. Using it, you can build real business applications for the Internet and intranets that run across multiple
platforms.
An ActiveX component is a unit of executable code, such as an .exe, a .dll, or an .ocx file, that follows the ActiveX
specification for providing objects. ActiveX technology allows programmers to assemble these reusable software
components into applications and services. Using ActiveX, you can create controls, documents, and components that
run on desktops or the Internet. The functionality packaged within these building blocks can then be easily reused in
other Windows-based applications.
A number of vendors offer ActiveX components that you can purchase and use in your applications. These
components provide a wide variety of generic services, including numerical analysis, user interface elements, and
data management. You can also create your own components and combine these with generic components. Reusing
tested, standardized code in this way is called component software development.
ActiveX allows you to create compelling, interactive web sites using a variety of tools. Most importantly, ActiveX
provides interoperability between development tools, authoring tools, database products, and networking
technologies.
Well begin our exploration of ActiveX with a discussion of ActiveX controls and how you can utilize them in your
applications. Well also learn about the Internet Server Application Programming Interface (ISAPI). Finally, well
learn how to implement and use active documents.
Using an ActiveX User Interface Control
ActiveX controls are reusable objects that include visual elements and code. They are used in some type of
container, such as a form, an application, or a web page, to enable or enhance a users interaction with an
application. These controls have an .ocx file name extension.
Chapter 06: Implementing ActiveX Controls
ActiveX controls were originally called OLE controls. The first version of the OLE control specification appeared in
1994 and was intended to provide a generic, COM-based architecture for building reusable Microsoft Windows
controls. The specification was revised in 1996 and OLE controls were renamed ActiveX controls. At the same time,
Microsoft Internet Explorer gained the ability to host ActiveX controls in web pages. Thus, the primary purposes of
ActiveX controls are:
To provide developers with a way to easily incorporate existing software components into their applications
To provide web authors with a way to implement interactive web pages by providing a standard for
components that run on the client computer
You can easily utilize functionality provided by an ActiveX control in your Windows-based applications. In the
following section, well create a calendar application that uses Microsofts MonthView control.
Inserting a Control using Component Gallery
In this section well learn how to use an ActiveX control in a Microsoft Foundation Classes (MFC) application. In
order to do this, we must first create a new project which includes support for ActiveX controls.
Exercise 6-1 Creating the Calendar Project
1. Select the File | New menu entry. This opens the New dialog box, as shown in Figure 6-1. Click the Projects
tab and select MFC AppWizard (exe) as the project type. Type Calendar for the project name.
Figure 1: Select the MFC AppWizard to begin creating the Calendar project
2. Click the OK button in the New dialog box. This runs the MFC AppWizard, which asks a series of questions
before generating the project.
3. In the Step 1 dialog box, select Dialog based for the type of application you want to create, then click Next to
proceed to Step 2.
4. In the Step 2 dialog box, make sure that the check box for ActiveX Controls is selected, as shown in Figure
6-2. At this point, click Finish and AppWizard creates and opens the new project.
Chapter 06: Implementing ActiveX Controls
Figure 2: In Step 2 of the AppWizard, make sure support for ActiveX Controls is selected
Now that we have a project that supports ActiveX Controls, we can add to the project the control we wish to use. We
do this using the Components and Controls Gallery, as illustrated in the following exercise.
Exercise 6-2 Inserting an ActiveX Control into the Project
1. Open the Calendar project (if its not already open).
2. Select the Project | Add to Project | Components and Controls menu entry to open the Components and
Controls Gallery dialog box.
3. Open the Registered ActiveX Controls folder. This lists all of the ActiveX components that are registered on
your computer.
4. Select the Microsoft MonthView Control, version 6.0 as shown in Figure 6-3.
Figure 3: Use Component Gallery to insert an ActiveX control into our project
Chapter 06: Implementing ActiveX Controls
4. Click Insert to insert the control into your project.
5. When the message box appears, confirm that you wish to insert the control into the project by clicking the OK
button.
6. When the Confirm Classes dialog box appears, accept the default class and file names by clicking the OK
button.
7. Close the Components and Controls Gallery dialog box by clicking the Close button.
Exercise 6-3 Adding the ActiveX Control to a Dialog
Now that weve inserted the MonthView control into our project, we can use the dialog editor to place it on a dialog
box as we would a standard control item.
1. Open the Calendar project (if its not already open).
2. Switch to ResourceView and expand the Dialog folder.
3. Double-click the IDD_CALENDAR_DIALOG dialog box. This opens the application dialog for editing in the
dialog editor.
4. Delete the static text control created by AppWizard. This contains a note reminding you to place controls on
the dialog.
5. Because we have inserted the MonthView control into our project, an icon for it will appear on the dialog
editors Controls toolbar. Select this icon, as shown in Figure 6-4.
Figure 4: The dialog editor's Controls toolbar after adding the MonthView control to the project
6. Click in the dialog box at the location where you wish to place the control. Once youve placed it, you can
move and resize it as you would with any control.
7. Using the dialog editor, resize the dialog and arrange the controls as shown in Figure 6-5.
Chapter 06: Implementing ActiveX Controls
Figure 5: The actual date shown in the finished dialog box will vary depending on your systems date setting
8. Test the dialog box. It should show the current month with todays date circled in red. Try clicking some
different dates and using the buttons at the top of the MonthView control to view different months. You can return to
the current month at any time by clicking the Today text at the bottom of the control.
Thats all there is to using an ActiveX control in an MFC application!
This is very powerful, but what if you want to alter the default appearance or behavior of the control? Fortunately,
most ActiveX controls allow a great deal of flexibility by providing customizable properties.
ActiveX Control Properties
In the previous exercise, we placed the MonthView control in a dialog and then tested the dialog box. Because we
didnt manipulate any of the control properties, we saw the default appearance and behavior.
Obviously, it would be difficult to write a control that was generic enough to be widely useful without allowing for
customization. Yet, that is the driving philosophy behind ActiveX controls. A well-designed ActiveX control
provides a great deal of flexibility by providing methods, properties, and events. An ActiveX control fires events to
communicate with its control container. The container, in return, uses methods and properties to communicate with
the control. In this section, well learn about control properties and how to manipulate them. In the next section,
well talk about methods and events.
Simply put, properties are data members of the ActiveX control that are exposed to any container. Properties
provide an interface for applications that contain ActiveX controls, such as Automation clients and ActiveX control
containers. By manipulating the properties of a control, we can customize its default appearance and behavior.
Exercise 6-4 Setting ActiveX Control Properties
Suppose the application we are writing requires that weeks begin on Monday, rather than Sunday. We can easily
modify the MonthView control to meet this requirement, as illustrated in the following steps:
1. Open the Calendar project (if its not already open).
2. Switch to ResourceView and expand the Dialog folder.
3. Double-click the IDD_CALENDAR_DIALOG dialog box. This opens the application dialog for editing in the
dialog editor.
4. Right-click the MonthView control and select Properties MonthView Object from the pop-up menu. This
opens the MonthView properties dialog box.
5. Click the Control tab.
6. Using the drop-down list, change the value of the Start of Week item from mvwSunday to mvwMonday, as
shown in Figure 6-6.
Chapter 06: Implementing ActiveX Controls
Figure 6: Changing the StartOfWeek item on the Control tab of the MonthView Control Properties dialog box
7. Close the MonthView Control Properties dialog box.
8. Select the File | Save menu entry to save the modifications.
Notice that the MonthView control now displays weeks that run from Monday through Sunday, rather than Sunday
through Saturday, as shown in Figure 6-7.
Figure 7: The modified dialog box, displaying weeks that begin on Monday
The MonthView control provides a number of properties that you can modify through the Properties dialog box.
Spend some time experimenting with different properties and determine how they affect the appearance and
behavior of the control. When youre finished, close the dialog editor without saving your changes. Well be using
this project in the next lesson and we want to have the properties set the way we saved them at the end of the
exercise.
In the previous example, we learned how to set the properties of an ActiveX control and spent some time
experimenting with the options available. This is fine for simple controls, but what if you need more information
about the properties, methods, and events that a control supports?
Fortunately, most controls provide a help file that contains this kind of information. The following exercise
demonstrates how you can access this information.
Exercise 6-5 Getting More Information about an ActiveX Control
1. Open the Calendar project (if its not already open).
2. Select the Project | Add to Project | Components and Controls menu entry to open the Components and
Controls Gallery dialog box.
3. Open the Registered ActiveX Controls folder. This lists all of the ActiveX components that are registered on
your computer.
Chapter 06: Implementing ActiveX Controls
4. Select the Microsoft MonthView Control, version 6.0.
5. Click the More Info button. This opens a help file, as shown in Figure 6-8.
Figure 8 : Use the Help file to obtain information on using the MonthView control
6. Close the Components and Controls Gallery dialog box by clicking the Close button.
As you can see, the help file provides extensive information about the MonthView control and the properties,
methods, and events it supports. Leave this help file open because well be referring to it in the next lesson, where
well learn how to use methods and events to interact with the MonthView control within our MFC application.
Handling an Event from an ActiveX User Interface
Control
In the previous section, we learned how to add an instance of the MonthView control to a dialog box and manipulate
its properties to customize the default appearance and behavior. So far, all of our interaction with the control has
been at design time. As we saw, ActiveX controls provide a great deal of power and flexibility that we can use in our
applications.
But, suppose that you want to extend the default functionality provided by the control. Perhaps you would like to
change the appearance of the control dynamically at runtime based on user input. Or, you might want to customize
the controls response to a particular user action.
Fortunately, most ActiveX controls provide methods and events that allow you to accomplish these goals. In this
section, well learn about methods and events and how to utilize them to interact with a control from its containing
MFC application.
Methods are similar in usage and purpose to the member functions of a C++ class. Control methods can be called
from a containing application to do useful work, such as dynamically changing control properties or accessing some
functionality provided by the control.
ActiveX controls use events to notify a container that something has happened to the control. An example might be a
user-input event, such as a mouse-click or a keyboard event. Such an event would cause the control to fire an event
to alert the container. By responding to these events, our application can customize the default behavior of the
control.
Suppose that you were writing an application to schedule hard disk backups, and wanted to allow the user to select
the backup date using a MonthView control. Your application would need to respond to the MonthView controls
SelChange event so that it could respond appropriately when the date was changed.
Chapter 06: Implementing ActiveX Controls
Well emulate this by adding a couple of controls to our Calendar applications dialog box to display the currently
selected backup date. Then well learn how to add code to update these controls when the user changes the date
using the MonthView control.
Exercise 6-6 Using Methods and Events to interact with an ActiveX Control
Open the Calendar project (if its not already open). 1.
Switch to ResourceView and expand the Dialog folder. 2.
Double-click the IDD_CALENDAR_DIALOG dialog box. This opens the application dialog for editing in the
dialog editor.
3.
Select the Static Text tool on the Controls toolbar and place a static text control in the dialog box. Then,
right-click the control and click Properties in the shortcut menu to open the Text Properties dialog box. In this
dialog box, change the static text control caption to Backup Date:.
4.
Select the Edit Box tool on the Controls toolbar and place an edit box control next to the static text control in
the dialog box. Then, right-click the control and click Properties in the shortcut menu to open the Edit
Properties dialog box. On the General tab, change the edit controls ID to IDC_BACKUPDATE. On the
Styles tab, click Read-only.
5.
Using the dialog editor, arrange the controls as shown in Figure 6-9. 6.
Figure 9: Use the Dialog editor to add new controls to the Calendar dialog box
At this point, were ready to add code to allow our program to interact with the MonthView control at runtime.
When we add an ActiveX control to our project, the Component and Controls Gallery automatically adds the
appropriate wrapper class implementation file (.CPP) and header file (.H) to the project. To get and set properties
and invoke methods for the MonthView control, the CMonthView wrapper class provides a declaration of all
exposed methods and properties. These functions can then be called from other application procedures using normal
C++ syntax. In this example, these declarations are found in MONTHVIEW.H
After the ActiveX control has been added to the project and embedded in the dialog box container, it can be accessed
by other parts of the project. The easiest way to access the control is to create a member variable of the dialog class,
CCalendarDlg, that is of the same type as the wrapper class added to the project by the Component and Controls
Gallery. You can then use the member variable to access the embedded control at any time.
Exercise 6-7 Adding a Member Variable for a Control to a Dialog Box
The following steps illustrate adding a member variable for the MonthView control to our CCalendarDlg dialog box.
From the View menu, click ClassWizard. 1.
Choose the Member Variables tab. 2.
In the Class Name list box, select the main dialog class CCalendarDlg. 3.
In the Control Ids list box, select the control ID of the MonthView control, IDC_MONTHVIEW1. Your
settings should now match those shown in Figure 6-10.
4.
Chapter 06: Implementing ActiveX Controls
Figure 10: Using ClassWizard to add a member variable for the MonthView control to the main dialog box
Click the Add Variable button to open the Add Member Variable dialog box. 5.
In the Member Variable Name box, type the name m_monthViewCtl. 6.
In the Category box, select Control. 7.
Verify that the Variable Type edit box contains the name of the control wrapper class, CMonthView. Your
settings should now match those shown in Figure 6-11.
8.
Figure 11: Adding the m_monthViewCtl member variable
Click OK to close the Add Member Variables dialog box. 9.
Click OK to accept these changes and exit ClassWizard. 10.
Thats all there is to adding a member variable for the MonthView control to our main application dialog box. Now
we can use common C++ syntax to access the properties and methods of the embedded control.
A common place to modify the properties of a control is in the OnInitDialog member function of the main dialog
class. This function is called just before the dialog box appears and is used to initialize its contents.
The following code example uses the m_monthViewCtl member variable to access the currently selected date within
the MonthView control. It then converts this value to a string and uses the string to initialize the Backup Date edit
control.
Well add the following line of code to call a member function to set the value of the IDC_BACKUPDATE edit
Chapter 06: Implementing ActiveX Controls
control. Well be adding this member function next.
SetBackupDateEditCtl(m_monthViewCtl.GetValue());
This line should be added near the end of the CCalendarDlg::OnInitDialog function, after the TODO comment line.
The finished function should look like this:
BOOL CCalendarDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
SetBackupDateEditCtl(m_monthViewCtl.GetValue());
return TRUE; // return TRUE unless you set the focus to a control
}
We added a call to a member function that sets the contents of the Backup Date edit control, IDC_BACKUPDATE,
based on the value of an input variable of type DATE. Notice that in the argument to this function, we use the
member variable that we created, m_monthViewCtl, to access the GetValue member function of the MonthView
control. The GetValue function returns the current setting of the Value property. Most ActiveX controls supply
member functions that allow you to get and set their internal properties in this way.
Exercise 6-8 Adding a Member Function to the CCalendarDlg Class
In the previous code sample, we added a call to this member function. Now we need to add this member function to
the CCalendarDlg class, as illustrated in the following steps.
Switch to ClassView. 1.
Right-click the CCalendarDlg class and select Add Member Function from the shortcut menu to open the Add
Member Function dialog box.
2.
In the Function Type box, type void. 3.
In the Function Declaration box, type SetBackupDateEditCtl(DATE currentDate). 4.
In the Access box, select Protected. Your entries should now match those shown in Figure 6-12. 5.
Figure 12: Adding the SetBackupDateEditCtl member function to the main dialog class, CCalendarDlg
Click OK to add the member function. 6.
Chapter 06: Implementing ActiveX Controls
a skeleton of the new member function, SetBackupDateEditCtl, is added to the CCalendarDlg class, as shown:
void CCalendarDlg::SetBackupDateEditCtl(DATE currentDate)
{
}
Add the following lines of code to the function body:
COleDateTime date(currentDate);
CWnd* pWnd = GetDlgItem(IDC_BACKUPDATE);
pWnd->SetWindowText(date.Format(VAR_DATEVALUEONLY));
The first line of code creates a variable called date of the type COleDateTime. The value of this variable is
initialized using the input currentDate variable. The second line of code gets a pointer to the Backup Date edit
control, IDC_BACKUPDATE. In the third line of code, this pointer is used to call its SetWindowText member
function. The Format member function of the COleDateTime class is called to convert the date value to a formatted
string.
If we test our program at this point, well see that when the main dialog box opens, the Backup Date edit control is
correctly initialized to the currently selected date within the MonthView control. However, if we select a different
date in the MonthView control, the Backup Date is not updated.
In the following steps, well learn how to add an event handler to remedy this problem.
Open the main dialog box, IDD_CALENDAR_DIALOG, in the dialog editor. 7.
Right-click the MonthView control and click Events in the shortcut menu to open the New Windows Message
and Event Handlers for class CCalendarDlg dialog box.
8.
In the Class or Object to Handle list box, select IDC_MONTHVIEW1. 9.
In the New Windows Messages/Events list box, select SelChange. Your settings should now match those
shown in Figure 6-13.
10.
Figure 13: Adding a new Windows message for CCalendarDlg
Click the Add and Edit button. This will open the Add Member Function dialog box. 11.
When the Add Member Function dialog box appears, confirm that the Message is SelChange and the Object
ID is IDC_MONTHVIEW1, then accept the default function name of OnSelChangeMonthview1 by clicking
the OK button.
12.
a skeleton of the new event handler member function, OnSelChangeMonthview1, is added to the CCalendarDlg
class, as shown:
void CCalendarDlg::OnSelChangeMonthview1(DATE StartDate, DATE EndDate, BOOL Far* Cancel)
{
Chapter 06: Implementing ActiveX Controls
// TODO: Add your control notification handler code here
}
Replace the TODO comment line in the function body with the following line of code:
SetBackupDateEditCtl(StartDate);
Now that weve added an event handler for the SelChange event, it will be called whenever the user selects a new
date in the MonthView control. The parameters to this function include the StartDate and EndDate variables of type
DATE. Both of these dates are included because, by changing a property of the MonthView control, you can
configure it to allow a selection range. Because were using the default properties that allow the selection of a single
date, well be interested only in the value of the StartDate variable. The value of StartDate represents the newly
selected date.
The line of code that we added to the function body sets the value of the Backup Date edit control,
IDC_BACKUPDATE, to the date passed to the function in the StartDate variable.
Test the program now that weve added the event handler. Youll see that the Backup Date edit control is correctly
updated when the user selects a new date in the MonthView control. You have successfully added an event handler
to an ActiveX control!
Dynamically Creating an ActiveX User Interface Control
Using these features of Visual C++ allows us to create very user friendly and useful applications. Properly designing
dialog boxes to help users interact with our applications will help them to be more productive when using these
programs. Using the Dialog editor, we are able to design these dialogs with ease. There are times, however, when we
are not able to use the Dialog editor to place these controls onto the dialogs and windows in our applications. When
needed, Visual C++ allows us to dynamically add these to our project. In this section we will be discussing how this
is done.
Adding controls dynamically at runtime can be as simple as creating a new instance of an existing control onto a
defined dialog or as complex as having the user specify the type of control to be added to a window. We will use an
example that falls somewhere between these two extremes. This example will show you how to add a control and
allow you to respond to the events that are raised by the control. Adding controls that we do not know about in
advance is an advanced concept and beyond the scope of the tests or this book.
Exercise 6-9 Dynamically Adding an ActiveX Control at Runtime
In this example we will duplicate some of the functionality that we created in the last exercise, but this time we will
do it by adding a MonthView control to the view in an SDI application. By now you should be very familiar with
using the AppWizard, so we will not detail those steps in this exercise.
1. Select File | New from the menu and create a new MFC AppWizard (exe) project type.
Name the project DynamicControl and ensure that the Create New Workspace option button is selected. 2.
In step 1 of the wizard, select a Single document as the type of application to create. Accept the defaults in
step 2. In step 3, be sure the ActiveX Controls check box is selected. select Finish and create the application.
3.
Again, we will be using the MonthView control from Microsoft and so we will need to add it to this project as
we did before. To do this, select Project | Add to Project | Components and Controls. Open the Registered
ActiveX Controls folder and select the Microsoft MonthView Control, Version 6.0 control. click the Insert
button. When prompted, click OK to insert the component into the project. Select OK to accept the default
class names. Finally, click Close to close the Components and Controls Gallery dialog box. We have now
created the necessary wrapper classes for the MonthView control.
4.
The next step is to add a Resource Symbol for the control that we will add at runtime. To do this, select View |
Resource Symbols. Then select New and type IDC_SELECTDATE. Accept the default value as shown in
figure 6-14. Click OK to create the symbol. select Close to close the Resource Symbol dialog.
5.
Figure 14: Adding the IDC_SELECTDATE symbol to our application
As stated earlier, the goal of this exercise is to add a MonthView control to the View window of our SDI
application. In step 4 we created the wrapper classes that define the behaviors of the MonthView control. To
6.
Chapter 06: Implementing ActiveX Controls
allow the View class to interact with this control, we now need to add the monthview.h header file to the
DynamicControlView.h header file. Place this include statement before the class definition in the file as
shown.
#include MonthView.h
class CDynamicControlView : public CView
{
The next step is to add a member variable to our CDynamicControlView class. To do this, right-click the
CdynamicControlView class on the Class View tab and select Add Member Variable. Specify CMonthView
as the variable type and m_monthSelectDate as the variable name. Set the access mode to Protected, and it
should look like the dialog shown in Figure 6-15. Finally, click OK to create the variable.
7.
Figure 15: Adding the m_monthSelectDate member variable to the view class, CDynamicControlView
The next step is to actually create the control. In our example, we will need to add a message handler to our
view class. To do this, open classwizard and select as the class name, CDynamicControlView. Next, be sure
that the Object ID that is selected is also CDynamicControlView. In the Messages list, select WM_CREATE
and click the Add Function button. At this point, the classwizards Message Maps tab should look like Figure
6-16.
8.
Figure 16: Adding the OnCreate function to the view class, CDynamicControlView
From the ClassWizard, click Edit Code. This will take us to the new message handler that we created and
allow us to add code to create our control.
9.
Now that we are editing the code, we need to call the Create method of our m_monthSelectDate object from
the OnCreate method of the CDynamicControlView class. The code is shown here.
10.
int CDynamicControlView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
Chapter 06: Implementing ActiveX Controls
Figure 1: In Step 1 of the MFC AppWizard, you choose the type of application that you want to create
Now that you are familiar with the CFile and CArchive classes, it is time to see how to use them for quick file I/O with
serialization. Serialize is a virtual function in the MFC library. MFC provides you with a menu bar in a document/view application
that supports the File Save and File Open commands. These menu choices will call the applications serialize function.
Serialization is a way to stream data to and from a persistent file.
Now lets look at the first thing MFC generates for us when we choose an MDI or an SDI. MFC gives us the declaration for the
virtual function in the document header portion. This takes in one parameter, a CArchive reference that is named &ar by default.
This file in the underlying MFC framework interfaces with a CFile object to actually read or write to the disk. In the
implementation file is the function CDocument::Serialize. This function has a simple ifelse statement that calls the
CArchive::IsStoring function to determine whether to stream to or from a file. Lets look at some code and then we will go over the
specifics.
Class CPayroll : public CObject //derive from CObject to support Serialization
{
DECLARE_SERIAL (CPayroll)
private:
int m_hours, m_overtime, m_employeeID;
CString m_szName;
public:
CPayroll () {} //default constructor
CPayroll (int employeeID, int hours, CString szName);
~CPayroll() {}
void Serialize (CArchive&); //function override
int GetHours();
void SetHours(int);
int GetEmployeeID();
void SetEmployeeID(int);
int CalculateOvertime(int hours);
CString GetEmployeeName();
void SetEmployeeName(CString);
}
We have started adding serialization support. This will be a class declaration in the document header file. First, we have derived
this from a CObject class; this will inherit Cobjects support for serialization. Next you will see the DECLARE_SERIAL macro;
this is required for the serialization process. The class also overrides its base class Serialize member function in order to persist
this object to disk. One important thing to mention is the need to have a empty constructor, as you can see in the preceding code.
Now we are halfway there and all we have to look at is the implementation file. This consists of using the IMPLEMENT_SERIAL
macro and the actual storage routine. We will lightly touch on versionable schema and leave a more thorough explanation for later.
The first thing we would like to add to the document implementation is the following:
IMPLEMENT_SERIAL (CPayroll, CObject, 1)
This takes the class that we are adding serialization to, the class it is based on, and the schema number. The following is a sample
of the serialization function:
void CPayroll::Serialize (CArchive &ar)
Chapter 08: Creating Data Services
{
CObject::Serialize (ar);
if (ar.IsStoring())
ar << m_hours << m_overtime << m_employeeID;
else //is loading
ar >> m_hours >> m_overtime >> m_employeeID;
}
In the preceding example, the serialization function will call the base class serialize function only for good practice. Although it
isnt necessary here, it is called in case the base class had contained other data members that would need serialization. CArchives
member function IsStoring is called in order to determine whether we are writing to or reading from the archive. The appropriate
action is then taken for streaming data with the << and >> operators. These operators are inherited from the CArchive class and are
overloaded to work with the following data types.
CObject* SIZE CSize float
CString POINT CPoint DWORD
RECT CRect double LONG
CTimeSpan int BYTE WORD
COleDateTimeSpan COleVariant COleCurrency CTime COleDateTime
Another way a document may be serialized is a direct call to the Serialize function. This is useful when you dont have a
document/view architecture set up for your program (which means choosing a dialog-based application, as shown in Figure 8-1).
When you choose this route you will need to handle what MFC usually takes care of for you, but dont worry its a snap! First we
want to make a CFile object on the stack. Next, we create a CArchive object on the stack. Remember, when an object is created on
the stack it wont need to be deleted because it will be deleted when the function goes out of scope. As of right now this should
look familiar from what we have learned about how MFC handles serialization using the document/view architecture. The final
step will be the actual call to the objects Serialize function. Here we will use the class CPayroll from the preceding code and the
instance of it is called roster.
CFile tempFile;
if (tempFile.Open (ThisFile.prl, CFile::modeCreate | CFile::modeWrite))
{
CArchive ar (&tempFile, CArchive::store);
roster.Serialize (ar);
This opens the file, ties the archive to the file, and then serializes it to the file with the Serialize call. There is no need to close the
file as that will be taken care of when these objects go out of scope. Optionally, you may close them if you like. That will cover our
normal serialization methods and we will move on to talk about versioning an archive.
We will modify some of the earlier code snippets to support a new schema, which will write the employee name variable to the
archive. That isnt anything different from what we have been doing, but we will also allow for it to read an archive with and
without this variable included using a technique called versionable schema. For example, if you write an upgrade to your software
and it needs to save information to the archive that wasnt originally in the persistent file, serialization will still work and will read
the old format as well. Here we will teach you how to use a schema by adding the employee name into the archive. The class
header will remain unchanged and you may see that again above. However, the implementation file where we used the macro to
implement serialization will need some modifications. Dont worry; most of the details of versioning are again handled by MFC.
First, we want to change the macro to include the constant VERSIONABLE_SCHEMA as follows:
Step Into Specific Function Steps through the code in the program, and step into the
specified function call.
Exceptions Displays the Exceptions dialog box. This can be used to
specify how you want the debugger to handle your
program exceptions.
Threads Displays the Threads dialog box. This can be used to
control program threads.
Figure 3: You can use the function keys shown on the Debug menu to execute the debug commands
Build Menu
On the Build menu, there is a Start Debug item that contains a submenu. It includes commands to start debugging a project. The command
available on this menu that we have not covered yet is Attach to Process. This command can be used to attach the debugger to a process that is
running on the system. This way, you can break into a process and perform debugging operations on it. The process does not have to be
started from within Visual C++. This can be useful if you have a module you are working on that is part of an application for which you do
not have all of the source code. In this scenario, you cannot start the application from within Visual C++, but you can attach to the process and
perform debugging on the modules for which you have the source files. The Build menu is shown in Figure 9-4.
Figure 4: You can access the Start Debug command from the Build menu
View Menu
On the View menu, you can open up the debug windows. This menu is shown in Figure 9-5. You can open the following debug windows:
Watch, Call Stack, Memory, Variables, Registers, and Disassembly. These can also be opened using the Alt and number key combinations
shown in the figure.
Chapter 09: Testing and Debugging the Solution
Figure 5: The Debugging commands on the View menu help you to debug your applications efficiently
Watch Window
The Watch window is probably one of the most commonly used debug windows. You can use it to specify local and global variables and
expressions that you want to watch while running your program. You can modify a local variables value from this window. The Watch
window is shown in Figure 9-6.
Figure 6:The Watch window allows you to watch specific variables and expressions while running your program
There are four tabs at the bottom of the window. This allows you to maintain separate sets of watch variables without having to wade through
variables that are not in the current scope. If you have an array, an object, or a structure variable in the Watch window, a plus (+) or a minus
sign () appears in the Name column. You can use these boxes to expand or collapse the variable data to see the data contained within the
variable. There are several ways to add variables to this window. Type, paste, or click in the first column of an empty row to enter the variable
name. You can also drag and drop variables onto the Watch window. To accomplish this, highlight the variable you want to drag, hold the
mouse down until a small box appears below the mouse cursor, and then drag it to the Watch window. This is helpful when you have several
nested structures and it saves you from having to type the entire variable. Also when you have nested structures, the pop-up tool tip sometimes
doesn't show the value. Another way to add a variable is to place the cursor on the variable, press Shift-F9 to bring up the Quick Watch dialog
box and click the Add Watch button to add it to the Watch window.
Call Stack Window
The Call Stack window displays the active functions on the stack. The function that is currently executing is at the top of the window. The
function that called the currently executing function is below that and so on. The window will also display function parameters along with
their values and types. This allows you to see all of the parameters that are passed along down the stack. This can be helpful in looking for an
unexpected value or a possible NULL or invalid value for a pointer. You can also move to the code for the different functions by
double-clicking the function that you want to view in the Call Stack window. This will bring you to the line of code where the function above
it was called. See the code and Figure 9-7 for an example. The call stack that is shown is from stopping inside Func2.
int Func2(int Val)
{
//the call stack is viewed from this line of code.
return (Val + 2);
}
int Func1(int Val)
{
return Func2(Val + 1);
}
int main()
{
int x = 5;
int Res;
Res = Func1(x);
return 0;
}
Chapter 09: Testing and Debugging the Solution
Figure 7: The Call Stack window displays the active functions on the stack
Variables Window
The Variables window displays the variables in a tree that are important in the programs current context. You cannot add variables to this
window as you could in the Watch window. As in the Watch window, you can expand and collapse variables with the plus (+) and minus (-)
signs. You can modify the value of a variable from the Value column. Also, the call stack can be viewed from the Context box.
There are three tabs on the Variables window. The Auto tab displays variables from the current and preceeding lines of code. The Locals tab
displays all of the local variables in the current function. The This tab displays the object pointed to by the this pointer. See the code below
and Figure 9-8 for an example of the Variables window.
int main(int argc, char* argv[])
{
int x = 0;
int i;
int Res;
for (i=0; i < 4; i++)
x = x + 3;
//the Variables window is shown from the line of code below.
Res = Func1(x);
return 0;
}
Figure 8: You can see all of the variables in the current function by using the Locals tab of the Variables window
Exercise 9-1 Using the Call Stack and Watch Windows
1. Create a new Win32 Console Application project named Chap9_1.
2. When asked What kind of Console Application?, select A Hello World Application.
3. Open the Chap9_1.cpp file.
4. Add the following functions:
int Func2(int Val)
{
//the call stack is viewed from this line of code.
return (Val + 2);
}
int Func1(int Val)
{
//Place a breakpoint on the line of code below.
return Func2(Val + 1);
}
5. Add the following code to the main procedure.
int x = 5;
int Res;
Chapter 09: Testing and Debugging the Solution
Res = Func1(x);
6. Right-click the line of code in the function Func1 and select Insert/Remove Breakpoint from the pop-up menu or press F9. Notice the
red button that appears next to the line. This will stop the application when it executes this line of code. A breakpoint suspends the execution
of the program at the specified line of code. This allows you to view how a program is executing a particular piece of code. We will cover this
later in the chapter.
7. From the Build menu, select Start Debug and select Go, or press F5.
8. When the debugger stops at the breakpoint, go to the View menu, select Debug Windows, and select Call Stack. (You can also press
Alt-7 or press the Call Stack button on the Debug toolbar.) If the Debug toolbar is not visible, select Customize from the Tools menu. Go to
the Toolbars tab and select the Debug box to turn on the Debug toolbar.
9. Notice that the top of the Call Stack window displays Func1(int 5).
10. On the Debug toolbar, click the Step Into button or press F11.
11. Notice that the top of the Call Stack window displays Func2(int 6) and the next line displays Func1(int 5).
12. Double-click the line containing Func1 in the Call Stack window.
13. Notice that a green arrow appears next to it in the Call Stack window. In the source file, a green arrow appears by the line of code that
called Func2.
14. Double-click the line that contains main in the Call Stack window.
15. Notice that a green arrow appears next to it in the Call Stack window. In the source file, a green arrow appears by the line of code that
called Func1.
16. On the Debug menu, select Go or press F5 to let the program finish executing.
17. From the Build menu, select Start Debug and select Go, or press F5.
18. When the debugger stops at the breakpoint, go to the View menu, select Debug Windows and select Watch, press Alt-3, or press the
Watch button on the Debug toolbar.
19. On the following line of code, where the breakpoint is set, right-click the Val variable and select Quick Watch from the pop-up menu.
return Func2(Val + 1);
20. When the Quick Watch window comes up, notice that Val = 5. Press the Add Watch button. This will add Val to the Watch window.
21. In the Watch window, double click the cell below Val to allow editing.
22. Enter Val == 6 and press enter. Notice this expression is 0.
23. Press the Step Into button on the Debug Window or press F11. You are now in function Func2. Notice that Val = 6 in the Watch window,
and the expression Val == 6 is now 1.
24. Press the Stop Debugging button on the Debug toolbar, or press Shift+F5, to terminate the program.
Using Depends
The IDE has many debugging features available. Many of the features can be accessed from the Debug, Build, View, and Edit menus. The
most common of these debugging commands can also be accessed by the Debug toolbar.It can also be used for general information about
modules in an application. The Depends tool is shown in Figure 9-9.
Chapter 09: Testing and Debugging the Solution
Figure 9: The Depends tool can assist you in determining the dependencies of file types
For troubleshooting purposes, the Depends tool can be used to detect files that are required by a module, but cannot be found. It can find files
that arent Win32 compliant or files that are corrupt. It can find import and export mismatches such as when imported functions are not
resolved. It can even find circular dependencies. Another common error is when a DLL cannot be found at a specified path. Depends can find
the complete path of all the modules being loaded for an application so you can check to see if the DLL is in the path being searched.
Depends can also be used for general information purposes. It can show all the modules required for an application. This can help you in
determining if you have included all required files in your setup program. It can list the functions that are called in each module by other
modules. This can help you understand why a module is being linked, and help you to remove modules that are not needed. The following
information is included for each module found:
Full path to the module file
Time and date of the module file
Size of the module file
Attributes of the module file
Type of machine that the module was built to run on
Type of subsystem that the module was built to run in
Whether or not the module contains debugging information
The preferred base load address of the module
The file version found in the modules version resource
The product version found in the modules version resource
The image version found in the modules file header
The version of the linker that was used to create the module file
The version of the operating system (OS) that the module file was built to run on
The version of the subsystem that the module file was built to run in
A possible error message if any error occurred while processing the file
Exercise 9-2 Using the Depends Tool
1. Open the Depends tool. It can be opened from Start | Programs | Microsoft Visual Studio 6.0 | Microsoft Studio 6.0 Tools | Depends.
Notice the window title says Dependency Walker.
2. From the File menu, select Open or click the Open button on the toolbar.
Chapter 09: Testing and Debugging the Solution
3. Find the MSDEV.EXE file and click open. Notice the tree view in the top left pane. If the tree is not expanded, right-click MSDEV.EXE
and select Expand All from the pop-up menu.
4. In the bottom pane, the dependent modules are listed with information for each module. Click each column header. Notice that the list
can be sorted by each column.
5. Notice the top-right pane. These are import functions.
6. Notice the bottom-right pane. These are export functions.
7. In the top-left pane, right-click MFC42.DLL, and select Full Path from the pop-up menu. Notice all of the modules are now listed with
the full path to where they are located.
8. In the top-left pane, double-click MFC42.DLL. Notice a Quick View window opens up. This will contain technical information about
the selected file.
9. From the File menu, select Exit to close the Depends tool.
Using Spy++
Spy++ is a utility that has windows to view the systems processes, threads, windows, and window messages. To start Spy++, go to the Tools
menu and select Spy++. When Spy++ starts, a tree view of the windows and controls opens in the system. Spy++ is shown in Figure 9-10.
You can also open views for messages, processes, and threads. To open a view, go to the Spy menu and select the view you want to open. The
tree views can be expanded and collapsed by clicking the + or symbols to find the desired object.
Figure 10: Use the Windows view of the Spy++ tool to find properties of open windows
Windows View
The Windows view can be used to find windows that are open in the system and view the properties of them. The Windows view has the
Desktop as the top window. All other windows are child windows to the Desktop. You can find windows by scrolling though the view and
expanding the tree as needed. You can see more detailed information for a window by double-clicking the desired window. You can also use
the Window Finder tool to find windows. The Window Finder tool is shown in Figure 9-11. To use this tool, arrange your windows so that
you can see both the window you are looking for and Spy++. From the Spy menu, select Find Window. Click the Finder tool, and drag it to
the window for which you want to see the properties. As you drag the mouse over a window, the properties of that window will be displayed
on the Window Finder tool. If you know the handle of a window, you can also use that to find a window. Select the Hide Spy++ check box to
help find a window. This will minimize Spy++ to get it out of your way.
Chapter 09: Testing and Debugging the Solution
Figure 11: The Spy++ Find Window dialog box displays the properties of a window as you drag the Finder tool over it
The Window Properties dialog box contains five tabs: General, Styles, Windows, Class, and Process. The General tab contains information
about the windows caption, the handle, the dimensions of the window, and more. The Styles tab displays the window display codes. The
Windows tab shows the handles for the Next, Previous, Parent, First Child, and Owner Window. To see the properties of any of these
windows, just click the handle link. The Class tab displays information about the window class, name of the menu, icon handle, cursor handle,
and handle for the Background. The Process tab displays information about the Process and Thread IDs.
Processes View
The Processes view is used to display information about what processes are running on the system and view information about those
processes. The Processes view is shown in Figure 9-12. Processes are identified by their module names. The Processes view tree can be
expanded to see threads that belong to each process. To search for a particular process, with the Processes window in the foreground, go to the
Search menu and select Process. When the Process Search dialog box comes up, type the process ID or a module name to search on. Then
choose either up or down for the direction of the search.
Figure 12: Use the Processes View in Spy++ to display information about the processes that are running on a system
Chapter 09: Testing and Debugging the Solution
Threads View
The Threads view displays a tree of all of the active threads associated with windows. The Thread ID and module name are shown for each
thread. Processes are displayed in this view. From this view, you can search for threads by the threads ID or module name. You can view the
properties for a particular thread by double-clicking it. This will bring up a dialog box which will display the module name, thread and process
ID, and the threads current and base priority. The Threads view with a Properties dialog box is shown in Figure 9-13. This can be especially
helpful if you suspect that a low priority for your thread is causing it to not run as expected.
Figure 13: The Threads view in Spy++ allows you to search for active threads and displays their properties
Message View
The Message view allows you to see the messages associated with a thread, process, or window. Messages are what make the graphical user
interface (GUI) in Windows work. Everything you do with the mouse, keyboard, or other device is represented by a message. For example,
when you move your mouse, WM_MOUSEMOVE messages are created to indicate where the mouse is. Also, when you click a button, a
WM_LBUTTONDOWN message is created when the button goes down. The Messages window allows you to see the message stream being
used by the selected thread, process, or window. By capturing the messages for a process, you can view the initialization of all windows. The
first column contains the window handle, and the second column contains a message code. The third column contains the decoded message
parameters and return values. When the Messages view is first opened, an options dialog box opens allowing you to select the window to
view, and the types of messages to log. You can also start and stop the logging of messages and format the Messages view. The Messages
view is shown in Figure 9-14.
Chapter 09: Testing and Debugging the Solution
Figure 14: You can select the types of messages that you want to log from the Messages view in Spy++
Exercise 9.3 Using Spy++
1. Open the Chap9_1 project you created in Exercise 9-1.
2. Open the Chap9_1.cpp file.
3. On the Tools menu, select Spy++.
4. Notice the Windows view appears. If the Windows view is not visible, on the Spy menu, select Windows or press Ctrl-W.
5. Find the Microsoft Spy++ window and double-click it to see the properties of the window.
6. Click Close to close the window.
7. Click the + symbol next to the Microsoft Spy++ window to expand the tree.
8. Click the + symbol next to the MDI Client window to expand the tree. Notice the Windows window. Keep expanding this tree until you
get to the bottom. Notice the window is a list box.
9. Arrange your windows so that you can see Chap9_1.cpp in Visual C++ and the Spy++ tool.
10. On the Spy menu, select Messages. Notice the Message Options dialog box appears.
11. Click the Finder tool and drag it to the Chap9_1.cpp window.
12. Click OK on the Message Options dialog box.
13. Move the mouse over the Chap9_1.cpp window and notice the Messages view displaying the mouse and cursor messages.
14. On the Messages menu, select Stop Logging.
15. Close the Spy++ tool.
Integrated Debugger
The integrated debugger can be used to find bugs in executables, DLLs, and ActiveX controls. One of the ways to check how your code is
executing is stepping through your code one line at a time. If you dont want to step through your entire program, you can set a breakpoint on
a particular line of code. This will cause the program to stop execution at that line of code. We have used some of these features in earlier
exercises in this chapter. We are going to cover how to step through your code and using breakpoints in more detail in this section.
Breakpoints
First, lets talk about setting breakpoints. You can set one or more breakpoints to stop execution at the point where you want to debug your
program. You can also set breakpoints when certain conditions exist. After the program has stopped, you can then inspect your code to look
for problems. To set and view breakpoints, you can use the Breakpoints dialog box. The Breakpoints dialog box has three tabs: Location,
Chapter 09: Testing and Debugging the Solution
Data, and Messages. To open the Breakpoints dialog box, from the Edit menu, select Breakpoints, or press Alt-F9.
The Location tab of the Breakpoints dialog box allows you to set a breakpoint by source code line number, memory address, register, or
function name. This tab is only available in the Enterprise Edition of Visual C++ 6.0. Enter this information in the Break at text box. The
existing breakpoints are displayed at the bottom of the dialog box. If you click the Edit Code button, it will take you to the line of code where
the breakpoint is set. The Location tab is shown in Figure 9-15.
Figure 15: The Location tab of the Breakpoints dialog box provides options for setting breakpoints
If you are not sure how to enter the information in the Break at textbox, click the button with the arrow next to it for more options. When you
click this button, you will see a pop-up menu with two options. The first is the line number that the cursor is currently at in your project.
Select this to add a breakpoint at the current line. The other option is advanced. If you click this, it will bring up the Advanced Breakpoint
dialog box. You can enter the location (which is the same information as the Break at text box), or enter information in the Context section.
This allows you to set a breakpoint outside of the current scope by selecting a function in a different source or executable file. The Advanced
Breakpoint dialog box is shown in Figure 9-16.
Figure 16: Use the Advanced Breakpoint dialog box to set a breakpoint outside of the current scope
You can also set the breakpoint based on a condition. To do this, click the Condition button. This will bring up the Breakpoint Condition
dialog box. This will allow you to enter an expression to break on at the location specified. When the expression evaluates to true, the program
will break. You might want to check for a variable equal to a certain value. If you enter an expression you can also enter how many times to
skip this breakpoint before stopping on the breakpoint. You can also set the breakpoint based an array element being changed. Set the
expression to an array index (for example, YourArray[0]), and enter how many elements in the array you want to watch (one to number of
elements in array). The Breakpoint Condition dialog box is shown in Figure 9-17.
Chapter 09: Testing and Debugging the Solution
Figure 17: The Breakpoint Condition dialog box allows you to set a breakpoint based on a condition
The Data tab in the Breakpoints dialog box allows you to enter an expression within the current scope. You can set a breakpoint for when a
variable changes or an expression evaluates to true. You can also set a breakpoint for an array element changing or an expression being true,
as you could on the Location tab. The Data tab is show in Figure 9-18.
Figure 18: You can use the Data tab of the Breakpoints dialog box to stop execution when a specified expression is true
The Messages tab allows you to set breakpoints when specified window procedure messages are received. The Break at WndProc list box
contains the exported functions in your project. The Set One Breakpoint for Each Message to Watch list box contains messages to break on.
You can select multiple messages as desired. The Messages tab is show in Figure 9-19.
Figure 19: You can set breakpoints for window procedure messages with the Messages tab of the Breakpoints dialog box
Chapter 09: Testing and Debugging the Solution
At the bottom of each tab is a list of existing breakpoints. You can edit and remove these breakpoints. To edit them, select one and the
properties for that breakpoint will be displayed. Edit the properties as desired. To remove breakpoints, highlight the breakpoint and click the
Remove button. Click the Remove All button to remove all of the breakpoints.
You dont always have to use the Breakpoints dialog box to set breakpoints. You can place the cursor on a line of code and press F9, click the
Insert/Remove button on the Build toolbar or right-click a line of code and select Insert/Remove breakpoint. You can use the Find box on the
Standard toolbar to search for a function or label and click the Insert/Remove button to set the breakpoint. You can also use the Call Stack
window to set breakpoints with the Insert/Remove button or by pressing F9.
Stepping through Code
Now that we can set breakpoints, lets talk about stepping through your code. Once you have stopped the execution of your application, you
can step through lines of code to determine if your code is doing what you expect. While you are stepping through your code, you can use the
debug windows to see the values of variables, expressions, the call stack ,and parameters passed, and so on. You can modify variable values
and view debug output.
To step through your code, use the Debug menu or the Debug toolbar. To move to the next line of code, use Step Into or Step Over. When you
get to a line of code with a function call, these two commands have different effects. The Step Into command will go to the first line of code
inside the function being called. Use this command when you want to see how the function executes. The Step Over command will go to the
line of code following the current line of code. Use this command when you know the function is executing correctly. It will not go into the
function being called.
If you are inside a function, you can use the Step Out command to exit the function and go to the line of code after the line that called the
function. Use this command when you have reached the part of a function that you wanted to check and dont want to step through the rest of
the function.
Another command is Run To Cursor. This command will execute the program until it reaches the line of code the cursor is on. This can be
helpful for skipping loops so you dont have to step through 1000 iterations.
The Step Into Specific Function command allows you to view the code inside a function that you specify. This is used when there are nested
function calls on the same line of code. This allows you to view how a function executes without having to step through all of the functions.
Edit and Continue
A new feature added to Visual C++ 6.0 is Edit and Continue. If you have used Visual Basic, you are already familiar with this feature. This
allows you to edit the source code while debugging and apply these changes without having to rebuild the application. The application will be
returned to the state that it was in when the bug occurred and you can see if your change fixes the bug. If you have compile errors, the changes
are not applied, and your compiler errors are displayed in the Output window. You can change variable values, expressions, and function
parameters, and you can even add new functions and call them in the code that you are debugging. When you are finished editing the code,
select Apply Code Changes from the Debug menu.
You can configure your project to automatically perform the Apply Code Changes command when a Debug command is executed. This way
you dont have to keep running the command every time you edit the code. To set this option, on the Tools menu, select Options. When the
Options dialog box comes up, go to the Debug tab and select Debug Commands Invoke Edit and Continue. The Debug tab on the Options
dialog box is shown in Figure 9-20.
Figure 20: The Debug tab on the Options dialog box contains options that allow you to change the code and then continue debugging
Exercise 9-4 Using Breakpoints and Stepping through Code
1. Create a new Win32 Console Application project named Chap9_4.
2. When asked What kind of Console Application?, select A Hello World Application.
3. Open the Chap9_4.cpp file.
4. Add the following functions:
Chapter 09: Testing and Debugging the Solution
int Func2(int Val)
{
int x = 6;
Val += (x / 2);
return Val;
}
int Func1(int Val)
{
int x;
x = Func2(Val);
return x;
}
5. Add the following code to the main function:
int y = 4;
int res;
res = Func1(y);
printf("Func1 returned %d\n", res);
getchar();
6. Place the cursor on the following line of code in the main function and press F9 to set a breakpoint. Notice the red dot that appears next
to the line of code.
res = Func1(y);
7. From the Edit menu, select Breakpoints or press Alt-F9. Notice the breakpoint at the bottom of the dialog box.
8. Place the cursor inside the Func2 function.
9. Go to the Data tab and click the arrow button to bring up the Advanced Breakpoint dialog box.
10. In the Expression text box, enter Val == 7.
11. In the Function text box, enter Func2.
12. In the Source File text box, enter CHAP9_4.CPP.
13. Click OK to close the Advanced Breakpoint dialog box. Notice the breakpoint has been added at the bottom of the Breakpoints dialog
box. It should appear similar to: when {Func2,chap9_4.cpp,} Val == 7.
14. Click OK to close the Breakpoints dialog box.
15. From the Build menu, select Start Debug, and select Go or press F5 to start the program. Notice the program stopped at the breakpoint in
the main function.
16. Click the Step Into button on the Debug toolbar or press F11 twice to step into the Func1 function. This will bring you to the following
line of code.
x = Func2(Val);
17. Click the Step Over button on the Debug toolbar or press F10 to step over the Func2 function call. Notice that you received a message
box for the breakpoint that we set when Val == 7.
18. Click Ok. Notice it took you inside the Func2 function.
19. Hold the mouse over the variable Val. You should get a tool tip showing Val = 7.
20. If the Variables window is not visible, from the View menu, select Debug Windows, and select Variables. Notice the variables Val and x
are displayed.
21. Press F5 to continue the program. Notice the console displays Func1 returned 7.
22. Press the Enter key to finish the program.
23. From the Build menu, select Start Debug, and select Go or press F5 to start the program.
24. After it stops at the breakpoint, press F5 and click OK when you get the Breakpoint message box.
25. On the following line of code, change Val to 15. On the Debug menu, select Apply Code Changes, or make sure that the Debug
Commands Invoke Edit and Continue option is selected on the Options dialog box, as described earlier in the chapter. Press F5 to continue the
program.
return Val;
26. Notice the console now displays Func1 returned 15. This is an example of using the new Edit and Continue feature.
27. Press the Enter key to let the program finish.
MFC Macros Used to Debug Applications
The MFC library contains macros that can be used for debugging applications during run-time. These macros can be used to display
debugging information during run-time. This can make the debugging process much less difficult. A couple of the most commonly used
Chapter 09: Testing and Debugging the Solution
macros are assert and trace. These macros allow you to check for logic errors and to output diagnostic data. The first step in using these
macros is to include the CRTDBG.H file in which they are defined.
ASSERT
The ASSERT macro allows you to check for logic errors during program execution. When the expression is false or 0, it prints a message and
aborts the program. The message includes the expression checked for, the source file name that the error occurred in, and the line number in
the source file. Where the message appears depends on the type of project. For console applications, the message goes to stderr. For a
windows application, the error is displayed in a message box with an OK button that will terminate the program. If the application has been
linked to the debug versions of the run-time library, the message box will have three buttons, Abort, Retry, and Ignore. If you press Abort, the
program is terminated. If you press Retry, the debugger is opened and you can then debug the application. If you press Ignore, the assert is
ignored and application execution continues. Be careful though, you could have unexpected results by ignoring the error condition.
When you have finished debugging and testing your application, build a release version of your program. This will use the run-time libraries
that do not contain the debug versions of functions, and asserts will be ignored. This will significantly increase the performance of your
application. You dont want your program aborting on an assert when your customer is using it, you should have ways of handling errors in
the code. Assert checking can also be turned off by defining NDEBUG with a #define. It must be defined before the ASSERT.H include
statement. Assert is used to notify you when there is an unexpected error. As an example, lets say you are programming a linked list and you
are deleting a node from the list. You could use an assert to check for the node pointer being NULL. Obviously, you shouldnt be trying to
delete a node from a NULL pointer. A word of caution, do not use assert for all of your error checking. Remember that ASSERT is ignored in
the release version of your application. Do not put code in the assert statement. For example, if you set a variables value inside the ASSERT
statement, when the release version runs, that variable would not be set. See the following code for an example.
ASSERT((x = ComputeValue()) == 0);
One solution to the preceding problem would be to use the VERIFY macro. It is the same as ASSERT, except the expression is executed
without the assert test being performed in the release version. If there is any error checking that should always be performed, use error
checking that will handle the error. You would not want the assert functionality in your release version anyway because the unneeded
overhead would cause a performance hit. Also, imagine the displeasure of your customers if they received a dialog box informing them of the
error and then the application terminated. Your application should handle all errors gracefully. You can also use the ASSERTE macro. It is the
same as the ASSERT macro, except it also displays the expression that was evaluated.
One of the new library functions in version 6.0 is the debug report function for logging errors and warnings during application execution. The
ASSERT macro calls the _CrtDbgReport function for sending messages for debugging. These messages can be sent to a file, the Visual C++
debugger, or a debug message window. The message can also include the source file name, the line number in the source file, and the .EXE or
.DLL filename. The message can be formatted similar to the printf function using a format-control string.
TRACE
The TRACE macro allows you to send formatted strings to a dump device. The formatting of the trace string is the same as printf. The strings
can be dumped to a file or debug monitor. To turn on tracing, you must define _DEBUG, use the debug version of your application, enable the
afxTraceEnabled flag, and set the afxTraceFlags to determine the level of detail output. These flags can be set using the tracer.exe tool. This
tool modifies the AFX.INI file. You can use trace to display variable values or any other logging functionality that you require.
Be careful in the use of TRACE. Dont output too much information or you wont be able to sort through it. Imagine sifting through a file
over a megabyte in size looking for the answer to your problem. Try not to put TRACE statements inside loops that iterate a large number of
times. When different developers are working on different units, you will have to sift through all of their TRACE statements also. One
common solution is to use conditional compilation for each developer. TRACE is useful when you need to see a sequence of events that you
cannot create by stepping through the code. Put TRACE statements at the beginning and end of critical functions and where critical events
occur.
DEBUG_NEW
The DEBUG_NEW macro is used to help find memory leaks. It is used in place of the new operator in the debug version. This macro tracks
the filename and line number for each object allocated. When you want to see the memory allocations, call DumpAllObjectsSince to view all
objects allocated with the source filename and the line number where they are allocated. You can review this list to check objects allocated
and determine which ones should have been freed and to see if any objects are lost in memory. Use the following macro to define the new
operator to use the DEBUG_NEW macro. You still use the new operator in your code, but it will then use DEBUG_NEW to allocate the
object. This will add debugging information to each allocation. It is only used in the debug version. In the release version, DEBUG_NEW is
resolved to a new operator and there isnt any debugging information saved. Therefore, you dont get a performance penalty in the release
version.
#define new DEBUG_NEW
Other Commands
Some less common MFC macros used for debugging are listed in Table 9-3.
Macro Description
ASSERT_KINDOF
Checks to see if an object is of a specified class or derived from the specified
class
ASSERT_VALID Checks the validity of an object by calling its AssertValid member function
TRACE0 Same as TRACE but the format string has no arguments
TRACE1 Same as TRACE but the format string has one arguments
TRACE2 Same as TRACE but the format string has two arguments
TRACE3 Same as TRACE but the format string has three arguments
VERIFY
Similar to ASSERT but evaluates the expression in the release version of the
library as well as in the debug version
Table 3: Descriptions of MFC Macros
Exercise 9-5 Using the ASSERT Macro
Chapter 09: Testing and Debugging the Solution
1. Create a new Win32 Console Application project named Chap9_5.
2. When asked What kind of Console Application?, select A Hello World Application.
3. Open the Chap9_5.cpp file.
4. Add the following code:
#include "crtdbg.h"
int Func2(int Val)
{
Val += 3;
return Val;
}
int Func1(int Val)
{
_ASSERT((Val = Func2(Val)) != 0);
return Val;
}
5. Add the following code to the main function:
int x = 3;
x = Func1(x);
printf("x = %d\n", x);
getchar();
6. From the Build menu, select Start Debug, and then select Go or press F5 to run the application. Notice that the application displays x =
6.
7. Press Enter to let the application finish executing.
8. Now lets set the application to run in release mode. From the Build menu,. Select Set Active Configuration. Select Chap9_5Win32
Release and click OK.
9. From the Build menu, select Execute Chap9_5.exe or press Ctrl-F5 to run the application. Notice that the application displays x = 3. This
is because the code in the ASSERT macro is not executed and therefore the function Func2 is not executed.
10. Press Enter, and then press any key to allow the application to finish executing.
Elements of a Test Plan
Testing is different from debugging. Debugging is the process of fixing bugs. Testing is the process of finding those bugs. There arent too
many software engineers who enjoy testing. It is also difficult for developers to do extensive testing because the developer already knows how
the application should work. However, testing is crucial to the success of an application. Testing is needed to find bugs in a program. I know,
good programmers wouldnt have any bugs to find.
Testing is also commonly cut short due to delivery deadlines. In todays rapid application development (RAD) environment, testing is even
more necessary. Two important tools needed for testing are source control, such as Visual Source Safe, and a bug tracking system. Bug
tracking tools can be as simple as a spreadsheet or as intricate as some third-party tools. This allows everyone on the team to know what bugs
there are, and the status of those bugs. This is a broad area and we will only cover the areas needed for the exam. There areas of testing we
will cover are Beta testing, Regression testing, Unit testing, Integration testing, and Stress testing.
All software contains bugs when it is released. You want to ensure that you know what those deficiencies are. If you werent able to fix the
bug before release, make sure you have a work-around in place. This should only be done for what is deemed a rare occurrence. This is not
ideal, but it is much better than your customer calling you and you have know idea how to solve the problem. You should include any
work-around in your release notes. You cannot account for everything, but the more you do account for, the better.
Beta Testing
Beta testing of an application allows testing by users who are not part of or do not have any ties to the development process. The testers are
completely independent of the development of the application. You can accomplish beta testing with a test team internal to the company or by
releasing beta software to the general public as Microsoft does. It allows you to receive unbiased feedback on bugs, features, or any other
aspects of your application. This allows a completely independent test environment for your application.
When you beta test your application, choose a group of advanced users who are more competent and knowledgeable. You dont want to be
bombarded with simple questions. Choose users who know what you are trying to achieve with your application. This will also allow your
application to be tested for those unknown, random configurations. For instance, users will have different computer. There will be different
operating systems, processors, motherboards, amounts of memory, hard drives, and so on. You cannot setup a test bed for every possible
computer that your application will be run on unless you are in a very controlled environment.
Evaluating the Need for Beta Testing
When do you need to perform beta testing? Beta testing should always be performed whether you are releasing beta versions of your product
to some of your advanced customers or to a group of employees who will be using your application internally. There are some instances
where beta testing is even more critical. If your application will be used by a wide range of users or different computer configurations, then
beta testing can help you work out problems before your release, instead of after releasing it. These types of applications would need more
extensive beta testing than an internal-use program, although you should perform some level of beta testing on all applications.
Use the following checklist to help determine when to beta test your application. All applications should have some BETA testing.
Different operating systems (Windows 3.1, Windows 95/98 and Windows NT)
Chapter 09: Testing and Debugging the Solution
Different computer configurations (CPU, RAM, hard drive space, CD-ROM, sound, video)
Different levels of users (that is, from the beginner to the expert)
Different languages as necessary
Regression Testing
Regression testing is repeating previous testing to show that a change to the application does not affect other aspects of the application. The
results of testing parts of the application that were not changed should be the same as they were in previous tests. Regression testing is also
important when you have earlier versions of your product released. You will have to test to ensure that you are completely backwards
compatible, as necessary. As an example, if you updated your database structure, you would need to ensure that your new version could still
read the old data and convert it to the new database. Also, if you have more than one version of your application and you update a DLL, you
have to test to ensure that the DLL will work with all versions. Regression testing is commonly performed by a software test engineer.
Unit Testing
Unit testing is testing the smallest part of an application that can be tested. This involves more than making sure that your unit will compile. It
is testing to show functionality that is required has or has not been met. Unit testing is generally performed by the programmer. The testing
should validate that the unit completely meets the requirements for which the unit is designed. Another important area to check is how your
unit handles invalid data.
Unit testing should start at the same time you start writing your code. This will involve writing test code for your unit. When you start creating
your interfaces, you can start testing those interfaces. Then as you add functionality, you can test it along the way. If you wait until you
believe you are done, you might have to redesign some areas to solve unexpected problems. If you had tested along the way, chances are, you
would have discovered the problem much earlier and wouldnt have to re-write any code.
Use the following checklist for areas to check in unit testing:
Meets requirements for which it was designed
Performs the functionality desired
Handles invalid data (data to large, NULL values, user entry)
Handles expected steps being out of sequence
Does not crash
Integration Testing
Integration testing is used to demonstrate that all of the units work together. Just because unit testing is completed, it does not guarantee it will
work correctly with other units of an application. This is especially true of large applications where there are many different programmers
working on it.
Use the following checklist for areas to check in integration testing:
Units can interface with each other correctly
All units meet overall application functionality and requirements
Handles missing modules gracefully
Uses different paths for the application and support files
Stress Testing
Stress testing places the highest possible loads with the lowest possible resources available to an application. This could be a high rate of data
input on a machine with the minimum required resources. This can also help in determining the minimum requirements for an application.
Incorporating Stress Tests
Microsoft Visual Studio comes with a tool to assist in stress testing. It is called Stress! It uses up system resources for low resource stress
testing. It can acquire resources such as the global heap, user heap, GDI heap, disk space, and file handles. You can configure the Stress tool
to allocate resources in fixed, random, and message-dependent allocations. It also provides logging options to help locate and reproduce bugs.
You can preconfigure it by setting the options that you desire in a STRESS.INI file. The Stress tool is shown in Figure 9-21.
Chapter 09: Testing and Debugging the Solution
Figure 21: The Stress tool assists you with stress testing
When stress testing applications, you want to see how your application performs under different types of conditions. If your application gets
an error due to a stress condition, it should notify the user of the problem and either allow the user to fix the problem if possible, or exit
gracefully. Your program should check each memory allocation, check for free disk space before writing to a file, and so forth. This is what
the tester will be looking for. Following is a checklist of items that should be tested during the stress test:
Minimum required CPU
Minimum required RAM
Amount of free disk space
Minimum CD-ROM drive speed
Maximum data load that the application is required to handle
From the Classroom
Don't Undervalue the Process of Debugging Your Application
Throughout this chapter you have learned various debugging techniques and the elements of a test plan. These elements are important to
provide you with the tools you need to thoroughly test your C++ applications. In many projects, software testing can account for 30 to 50
percent of software development costs. But why is testing so important? And how can we ensure that our software is properly tested?
The main goal of testing is to ensure that we deliver a quality software product. Quality software must satisfy user and system requirements in
areas of reliability, functionality, application performance, and system performance. Because software quality has a variety of measures, it is
important to incorporate many different debugging techniques and types of tests into your test plan. Verifying your software's reliability may
include using debugging functions during unit testing of a class to ensure that it does not leak any memory. Test cases can be developed for
each feature in your application's feature set to ensure that all the necessary functionality is included in the application. Stress testing may be
performed at the application and system level to ensure your software performs well under typical and maximum load situations.
Another good reason to test software completely is to reduce the number of errors that you have to fix after the software is deployed. It always
costs more to fix a problem after software deployment than it does to fix the problem before the software is released to the users. This is in
addition to the decrease in user satisfaction that accompanies software products requiring many post-release fixes.
Ensuring that software is thoroughly tested comes down to one thing: planning. As you define the requirements of your application and create
a development plan, you should also be defining your test plan. The first part of the test plan is to perform risk analysis of your system. Use
this analysis to define your test objectives. The highest risk elements of your application should be tested, and verified, early on in the
development cycle.
A good test plan is also one to which you adhere throughout the software development cycle, not just before your software ships. Coding and
testing in incremental fashion will identify defects early, so they can be fixed early, before fixing the error produces a "ripple effect" (you end
up breaking multiple features built on top of the faulty code). Finally, develop a plan for tracking and managing defects. Armed with the
debugging tools and features of Visual C++ 6.0, and a plan, you can deliver quality C++ applications.
Michael Lane Thomas, MCSE+I, MCSD, MCT, MCP+SB, MSS, A+
Certification Summary
Visual C++ contains many features to assist you in debugging and testing your application. Debugging is fixing errors in your code. Testing is
finding those errors in your code.
You can make different versions of your application, a release version and a debug version. For the debug version, Visual C++ comes with
debugging libraries which contain debug versions of memory functions to help find memory leaks. There is debugging support in the run-time
libraries to allow you to step into run-time functions. It also creates .PDB files to hold debugging information for your application. The
debugging overhead is not used in the release version.
Visual C++ provides many debugging features in the IDE. It provides commands for viewing different types of data and controlling the
execution of your program. These include windows for viewing variables, expressions, the stack, memory, registers, and assembly code.
Use the Depends tool to assist you in determining the dependencies of .EXEs, .DLLs, .OCXs, .COMs and other file types. This can be used
for debugging or for finding general information about your application.
The Spy++ tool is a utility that has windows to view the systems processes, threads, windows, and window messages. It also comes with a
Chapter 09: Testing and Debugging the Solution
Finder tool so you can use your mouse to choose an application for which you want to view the properties.
The integrated debugger is a very useful tool in the debugging process. It allows you to set breakpoints for stopping program execution at
specified points in your code and allows you to step through your code to determine if your program is executing correctly. It also has a new
feature called Edit and Continue. This allows you to edit code while your program is stopped and continue execution from where you stopped
without having to rebuild your application and restart it from the beginning.
The MFC library contains some macros that can be used for debugging. The ASSERT macro allows you to check for unwanted conditions in
your code and stop program execution. The TRACE macro allows you to output messages to aid in debugging your application. You can use
it to show program flow and data values.
There are many phases to the testing process. Beta testing allows pre-release testing of your application. Regression testing is used to ensure
backward compatibility and verify that you didnt break other aspects of your application. Unit testing is usually performed by the developer
to make sure the unit fulfills what it was designed for. Integration testing verifies overall application functionality. Integration testing is
normally performed by a tester and it brings all of the units together to see how they operate as a whole. Stress testing sees how your
application performs under adverse conditions.
Two-Minute Drill
Debugging an application allows you to find errors in your application. Errors can be programmatic or logical.
When you create a project, both a debug version and a release version are created.
Visual C++ includes debugging support in the run-time library. This allows you to step into a run-time functions code and contains
functions to help locate memory leaks and other memory problems, and to view the heap.
The debug libraries include debug versions of malloc, free, calloc, realloc, new, and delete. These can be used for finding memory leaks.
The IDE has many debugging features available. Many of the features can be accessed from the Debug, Build, View, and Edit menus.
The most common of these debugging commands can also be accessed by the Debug toolbar.
The IDE has many debugging features available. Many of the features can be accessed from the Debug, Build, View, and Edit menus.
The most common of these debugging commands can also be accessed by the Debug toolbar.
For troubleshooting purposes, the Depends tool can be used to detect files that are required by a module, but cannot be found.
Spy++ is a utility that has windows to view the systems processes, threads, windows, and window messages. To start Spy++, go to the
Tools menu and select Spy++.
The integrated debugger can be used to find bugs in executables, DLLs, and ActiveX controls. One of the ways to check how your code
is executing is stepping through your code one line at a time. If you dont want to step through your entire program, you can set a breakpoint
on a particular line of code.
The MFC library contains macros that can be used for debugging applications during run-time. These macros can be used to display
debugging information during run-time.
Testing is different from debugging. Debugging is the process of fixing bugs. Testing is the process of finding those bugs.
Beta testing of an application allows testing by users who are not part of or do not have any ties to the development process. The testers
are completely independent of the development of the application.
Regression testing is repeating previous testing to show that a change to the application does not affect other aspects of the application.
The results of testing parts of the application that were not changed should be the same as they were in previous tests.
Unit testing is testing the smallest part of an application that can be tested. This involves more than making sure that your unit will
compile. It is testing to show functionality that is required has or has not been met.
Integration testing is used to demonstrate that all of the units work together. Just because unit testing is completed, it does not guarantee
it will work correctly with other units of an application.
Stress testing places the highest possible loads with the lowest possible resources available to an application. This could be a high rate of
data input on a machine with the minimum required resources. This can also help in determining the minimum requirements for an
application.
try
{
Chapter 11: Maintaining and Supporting an Application
res = Func2(x);
}
catch (...)
{
throw;
}
return res;
}
5. Add the following code to the main function. When you type Func1( you will get the Auto Parameter Info as seen in Figure 11-7.
int x, y = 0;
try
{
x = 1 / Func1(y);
}
catch (int err)
{
if (err == 1)
x = 0;
else
x = -1;
}
catch (...)
{
x = -1;
}
return 0;
Figure 8: Use the Auto Parameter Info option to display the parameters that are required for a function
6. Right-click the lines of code in the Func1, Func2, and main functions in the try and catch blocks and select Insert/Remove Breakpoint
from the pop-up menu, or press F9. Notice the red button that appears next to the line. This will stop the application when it executes this line
of code. Also notice the coloring used. By default, the keywords, such as try, would be in blue. Add a comment to your code. By default, it
will be colored green.
7. From the Build menu, select Start Debug and select Go, or press F5.
8. When the debugger stops at the breakpoint in main where Func1 is called, notice it is inside a try block. Hold the mouse over the
variable y to verify that the value is zero.
9. From the Debug menu, select Go, or press F5. The debugger will stop at the breakpoint inside Func1 where Func2 is called. Hold the
mouse over the variable x to verify the value is zero.
10. Press F5. The debugger will stop at the breakpoint inside Func2 where one is divided by x. Hold the mouse over the variable x to verify
the value is zero.
11. Press F5. The debugger will stop at the breakpoint inside the catch block inside Func2 because the code attempted a division by zero.
Press F10 to step to the next line of code. You are now going to throw an exception with a value of one.
12. Press F5. The debugger will stop at the breakpoint inside the catch block inside Func1. The code is now in another exception handler. The
throw statement will throw the current exception, which is an integer value of one, to the next exception handler. If there had been a different
error, it would have thrown an exception with the string Unknown Error.
13. Press F5. The debugger will stop at the breakpoint inside the catch block inside main. The code is now in another exception handler.
Notice it stopped in the catch block that had the integer. Hold the mouse over the variable err to verify it is equal to one. Press F10 to step to
the next line of code. Here, x is set to zero. When execution resumes, the code following the catch blocks will execute.
14. Remove the try and catch blocks in the main function. It should now look like the following code.
int x, y = 0;
x = 1 / Func1(y);
return 0;
15. Remove all the breakpoints in the project. From the Build menu, select Set Active Configuration, verify that the Debug version is
selected, and click the OK button. Press F5 to run the program. A dialog box will pop-up notifying you that some files are out of date. Click
Yes to build them and then a message box similar to the one in Figure 11-9 will appear.
Chapter 11: Maintaining and Supporting an Application
Figure 9: You could see this unhandled exception message in the Debug version
16. From the Build menu, select Set Active Configuration, choose the Release version and click the OK button.
17. From the Build menu, select execute Chap11_1.exe or press Ctrl-F5. A message box will appear. Click the Details button to see a
message box similar to the one in Figure 11-10. This is what users of the program would see. Make sure you handle exceptions rather than
your program displaying this message box.
Figure 10: If you handle exceptions, the users of your program wont see this dialog box
There are some situations where you can save yourself some coding time and decrease the code in an application. Look through your project
for code that is repeated. For example, there may be multiple places where you are opening a file. Consider creating a generic function that
can be used instead of writing the code where files are being opened. Then put exception handling within the function and have the function
return an error code for success or failure of opening the file. This also helps in preventing logic errors because you are not writing the code
over and over. You can test the function and then you dont have to worry about testing the code for each place in which you are opening a
file. This also makes your application smaller.
Another way to implement exception handling is to centralize exception handling. You can create a function that is called from all catch
blocks. The function would be called and then passed the exception. Inside the function, you would parse for different types of exceptions and
handle them appropriately. It is important to remember that this does not preclude you from adding exception handling in your functions. It
does minimize the exception handling code in each function.
Distributing Application Updates
Dont plan on releasing version 1.0 of your application and then thinking you are done. At some point in the future, you will more than likely
need to make an update to it. There are different reasons for needing updates. It might be that because the business rules for your application
have changed you are adding new features, or you might have customers who discover some bugs that werent found during testing. This is
common because you cant test for every possible computer hardware and software configuration. Whatever the reason, plan on the need for
updates.
When deploying updates, it is similar to deploying a full application, which was covered in Chapter 10. You will be placing your update on
some type of media for distribution such as CD-ROMs, floppy disks, or a web site for Internet or intranet downloads. We will be discussing
how to deploy an application update.
The first step to deploy your application is to package it. Files will be compressed and packaged into .CAB files. In an update, you dont
necessarily need to deploy all the files that were deployed in the full installation. You should only deploy the files that have changed. There
are several reasons for this. This will make your update smaller, which is more critical for floppy disk and web site deployment methods.
Another reason is that you can distribute the update freely without worrying about licensing issues because you are only deploying a small
(hopefully its small) subset of your application that cannot be run by itself. The files included in your update will overwrite the files already
on the customers computer. If you made changes to a database file, you have to be careful. You dont want to overwrite the existing database
with the new one that doesnt contain the data in the customers database. This would cause the customer to lose all of their data. If this is the
case, you will need to give the customer a way to convert their data to the new database. You can do this through a utility program or handle it
in your application when the updated application is first run. Files such as database drivers, the MFC DLLs, and controls do not need to be
included unless your update was developed using newer versions of these files.
Visual C++ 6.0 provides the InstallShield Wizard to create an InstallShield setup program which includes the necessary files and
dependencies to install your application, register the COM components, and allow for uninstall, as covered in Chapter 10. To start the
InstallShield Wizard, from the Tools menu select InstallShield Wizard as seen in Figure 11-11, or click the Start button on the desktop, select
Programs, then InstallShield for Microsoft Visual C++ 6.0.
Chapter 11: Maintaining and Supporting an Application
Figure 11: Use the InstallShield Wizard to create an installation program for your application
The InstallShield Wizard will walk you through most of the process of creating an installation program for your application. The basic
procedure for creating an update is described in the following paragraphs.
The first step is to enter some basic information about your application. Include the name of the application and the name of the company that
wrote the application. Choose the development environment. Unless you have the full version of InstallShield, the only option available will
be Microsoft Visual C++ 6. Choose the type of application that you are deploying. The options available are: Database Application, Finance
Application, Internet Application, Software Development Application, and Statistical Application. enter the version of the update. The version
should represent the fact that this is an updated version of the application.
Next you will decide which dialog boxes to display during the installation process. Because this an update, you will generally want to
minimize the dialog boxes that are displayed. Which ones you choose will depend on your application and personal preferences. The
Welcome Message dialog box displays a welcome message and some information about running the installation program. The Software
License Agreement dialog box displays a license agreement for your update. The Readme Information dialog box displays some information
such as what is included in the update or warnings about performing the installation. Generally, you will give the user the option to view
update information when the setup is complete. The User Information dialog box asks the user to enter a Name, a Company, and a Serial
Number. You should have already retrieved this information from the user during the full installation and saved it in the Registry, so it
normally wouldnt be used. The Choose Destination Location dialog box allows the user to specify where to install the application files. This
information should already be in the Registry from the full installation. Normally, you would put code in the script to first check to see if this
information is in the Registry and then automatically install it there. If it is not there, then you could display this dialog box. The Setup Type
and Custom Setup dialog boxes normally wouldnt be used because you shouldnt need to ask the users which options to update. If you have a
large update that has some files that are only used in certain setup types, you could ask the user. However, this could cause problems if the
user didnt remember which option was selected during the full installation and selected the wrong one during the update. For example, say
the user did a Custom setup type during the full installation and then chose compact this time. Your update would only update the compact
files. This could cause problems. It would be better to retrieve the setup type from the Registry and use it if needed. The Select Program
Folder dialog box allows the user to specify in which Program folder on the Start menu a shortcut to the application will be placed. This
should have been done during the full installation and therefore not used during the update. The Start Copying Files dialog box displays the
setup options selected, which is not applicable to an update because you would retrieve this information from the Registry. The Setup
Complete dialog box notifies the user that the setup has completed and gives the user the option to view a Readme file and launch the
program. This is a better place to put information about your update rather than the Readme Information dialog box.
Now you need to choose on which operating systems the update can be installed. You will need to decide between Windows 95/98, Windows
NT 3.51 and Windows NT 4.0. For the Windows NT platforms, you will also decide between the Intel or Alpha platforms. Select the
operating systems that are absolutely necessary to reduce the size of your distributing package and reduce the chance that someone will try to
use your program under the wrong operating system. You can also select one or more languages for which you are running your setup.
You will also decide the components that wil be included in your update. You can group your files into components. Components and
subcomponents give you the flexibility to package your application and related software accessories into logical groups for setup types. These
components will be displayed to the user. Generally you will only need one component, such as the Program Files component, for the
executable and DLLs for your application. You will also decide on File Groups, which are related to the components. These are the actual file
groupings that will be installed.
When you are done, InstallShield will create the installation program using the options youve specified. InstallShield generates several files
including the setup rule (SETUP.RUL) file which is the script for the installation process. The SETUP.RUL file can be modified. It uses a
language similar to the C programming language. This file needs to be compiled when changes are made.
In Exercise 11.2, we will step through the Project Wizard to choose the options for an update. We are going to start InstallShield from the
Start menu because it has more options available than using the wizards.
Exercise 11-2 Choosing Update Options Using the Project Wizard in InstallShield
1. Start the InstallShield for Microsoft Visual C++ 6 from Start | Programs | InstallShield for Microsoft Visual C++ 6. Youll see the
Projects pane in the top window, as seen in Figure 11-12.
Chapter 11: Maintaining and Supporting an Application
Figure 12: The Project Wizard of the InstallShield for Microsoft Visual C++ 6.0 helps you to create an update to your application
2. Double-click the Project Wizard icon to create your update. This will bring up the Project Wizard Welcome window.
3. For the Application name, enter Chapter 11_1 Update.
4. Enter a company name of your choice.
5. Select the development environment. Unless you have the full version of InstallShield, the only option available will be Microsoft
Visual C++ 6.0.
6. In the Application Type field, select Software Development Application
7. For the Application Version field, type 1.1.
8. Click the ellipsis button next to the Application Executable field to find the Chap11_1.EXE application that we created in exercise 11-1.
See Figure 11-13 for an example of how your completed Welcome screen should look.
Chapter 11: Maintaining and Supporting an Application
Figure 13: Enter the information about your application on the Welcome screen
9. Click the Next button. This will bring up the Project WizardChoose Dialogs window. Here we need to decide which dialog boxes will
be displayed to the user. You can preview each of the dialog boxes by selecting one of the dialog boxes and then clicking the Preview button.
10. Select the Welcome Message dialog box.
11. Select the Software License Agreement dialog box.
12. Clear the check box for the Readme Information dialog box.
13. Clear the check box for the User Information dialog box.
14. Select the Choose Destination Location dialog box.
15. Clear the check boxes for the Setup Type and Custom Setup dialog boxes. For our exercise, we are only updating a small application, so
we dont need these dialog boxes.
16. Clear the check box for the Select Program Folder dialog box.
17. Clear the check box for the Start Copying Files dialog box. For our exercise, it is not applicable.
18. Select the Setup Complete dialog box. Your Choose Dialogs screen should look like Figure 11-14.
Chapter 11: Maintaining and Supporting an Application
Figure 14: Choose the dialogs that you want to use in your setup from the Choose Dialogs screen
19. Click the Next button. This will bring up the Project WizardChoose Target Platforms dialog box. You can select the Show only
available platforms option to reduce the available platforms that the InstallShield program supports. We will use the defaults as displayed in
Figure 11-15.
Figure 15: Choose the platforms for your update from the Choose Target Platforms screen
20. Click the Next button. This will bring up the Project WizardSpecify Languages dialog box.
21. Select English. Your Specify Languages screen should look similar to Figure 11-16.
Chapter 11: Maintaining and Supporting an Application
Figure 16: Use the Specify Languages screen to select the languages in which you will create your update setup
22. Click the Next button. Youll see a Project WizardSpecify Setup Types dialog box.
23. Cancel the selection of all of the options. We are not going to use Setup Types for this exercise. Your completed screen should look
similar to Figure 11-17.
Figure 17: Select your setup types from the Setup Types screen
24.Click the Next button. This will bring up the Project WizardSpecify Components dialog box.
25. Delete all of the components except the Program Files component. To delete a component, select the component and then click the Delete
button. We will only need the Program Files component for this exercise. Your completed screen should look similar to Figure 11-18.
Chapter 11: Maintaining and Supporting an Application
Figure 18: You can add or delete components using the Specify Components screen
26. Click the Next button. This will bring up the Project WizardSpecify File Groups dialog box.
27. Delete all of the File Groups except the Program Executable Files. To delete file groups, select the File Group and then click the Delete
Button. In this exercise we will only be installing the executable. Your Specify File Groups screen should look similar to Figure 11-19.
Figure 19: Choose the file groups that you want your update to install from the Specify File Groups screen
28. Click the Next button. This will bring up the Project WizardSummary dialog box. At this point you should check the list of options to
make sure everything is correct.
29. Click the finish button. InstallShield will create the installation program using the options youve just specified. The InstallShield window
should look similar to Figure 11-20.
Chapter 11: Maintaining and Supporting an Application
Figure 20: The InstallShield window after the frame code has been created for the setup program
Now that you have chosen the options for the update, you have some properties to set for the files that will be installed. You have to decide on
when they should be installed. On the Components tab, components have a property called Overwrite. The Overwrite property lets you specify
the conditions under which the files of the component will or will not overwrite existing files on the users computer. The available options
are as follows:
ALWAYSOVERWRITEoverwrites the file no matter what.
NEVEROVERWRITEinstalls the file only if it doesnt exist.
NEWERDATEoverwrites the file only if it has a newer date.
NEWERVERSIONoverwrites the file only if it has a newer version number.
NEWERVERSION/NEWERDATEfirst checks for a newer version, then if necessary, checks for a newer date.
Because we are creating an update, we want to overwrite existing files. Instead of using the default to always overwrite files, use the
Overwrite files by Version option. This way, if a user has run an update newer than the current update, it will not overwrite these files. As an
example, if you had ran Visual Studio Service Pack 3, then for whatever reason you run Service Pack 2, you would not want your files
updated by the older version. This could cause unpredictable results. In the File Groups tab, you will decide which files to include in the
update.
Exercise 11-3 Setting Properties for the Files to be Installed
Click the Components tab and select the Program Files component. The right pane will display the Components-Program Files window,
similar to Figure 11-21.
Chapter 11: Maintaining and Supporting an Application
Figure 21: Use the Components Program Files window to view the current properties of the files that will be installed in the update
Double-click the Overwrite field. This will bring up the Overwrite Properties dialog box. Select the Overwrite files by Version option. The
Overwrite Properties dialog box should look similar to Figure 11-22.
Figure 22: Use the Overwrite Properties screen to specify when the distributed files will overwrite the users existing files
Click the OK button to use this option.
Click the File Groups tab. This will display the File Groups in the right pane. We will accept the defaults. It should look similar to Figure
11-23.
Chapter 11: Maintaining and Supporting an Application
Figure 23: You can access the file group properties from the File Groups tab
Click the plus sign (+) next to the Program Executable Files folder icon. Then click the Links entry under it and youll see the File
GroupsProgram Executable Files\Links dialog box. This is where youll define the executable to include in this file group.
Right-click the File GroupsLinks dialog box and choose Insert Files from the shell extension menu. This will bring up the Insert File
Link(s) into File Group dialog box. This is a standard File Open dialog box.
Browse to the Chap11_1.EXE file, select it, and click OK. This will put the file in the Links window in the right pane, as shown in figure
11-24.
Figure 24: The selected program executable file for your update will appear in the Links window
The last step to deploy our update is to package it and choose the type of media by which our update will be distributed. By default, a
CD-ROM media package is created because the CD-ROM-based distribution is the most typical type. There are other widely used distribution
methods such as floppy disks, network-based, Web-based, and e-mail attachment package distributions.
Because CD-ROMs have a large amount of available space (over 600MB), the CD-ROM is often the medium of choice. To put your update
on a CD-ROM, you need a writeable CD-ROM drive attached to your deployment computer. Floppy disks are still a viable option. Some older
computers may not have a CD-ROM drive, so it is a good idea to have a floppy disk as an option. Also, if your update is less than 1.44Mb,
Chapter 11: Maintaining and Supporting an Application
you might want to consider using floppy disks. The network-based distribution is very similar to the CD-ROM deployment method. If you
select the Folder option of the CD-ROM media type when you build the disk images, you can select a folder on a network server. This makes
deployment easy because you dont have to copy CD-ROMs or floppies and then distribute them. The Internet is an effective way of
distributing an application to the end users. Deploying a package through the Web requires you to have some sort of Internet access and
necessary permissions to a directory on a Web site. You also need to set up your Internet server to perform the user access and security
permission check in the directory. This is also a less expensive deployment method because you dont have to create and distribute CD-ROMs
or floppies. Another option is to attach the setup files to an e-mail message and send it to your users. Be careful about the size of the update.
Some Internet Service Providers will not let their customers receive e-mail attachments larger than 1Mb. In exercise 11-4, we will create a
package for distributing our update using floppy disk media.
Exercise 11-4 Creating Packages for a Floppy Disk distribution
1. Click the Media tab. We are now ready to choose the deployment options for our update.
2. Right-click the Chapter11_1 Update Media icon and select the Media Build Wizard. This will bring up the Media Build WizardMedia
Name screen. Enter Floppy for the Media Name. Notice that the default of CD-ROM is already created. We will create a floppy disk media
distribution type for this exercise because our update will be very small. Your screen should look similar to Figure 11-25.
Figure 25: Choose the media for your update from the Media Name screen
3. Click the Next button. This will bring up the Media Build WizardDisk Type screen. This screen allows you to choose the distribution
media for this media build. You can choose from different floppy disk sizes, CD-ROMs, custom sizes, and an Install From the Web option if
you have the InstallFromTheWeb Internet Setup Tool. This is another tool available from InstallShield to allow users to install your
application over the Internet.
4. Select 3.5 Diskette1.44 Mb and Click the Next button. This will bring you to the Media Build WizardBuild Type screen. Select
Full Build.
5. Click the Next button. This will bring up the Media Build WizardTag File screen. The purpose of tag files is to mark each disk of a
multidisk distribution. You can place application information in them. In the Tag File panel, the data is filled with the data that we entered
earlier. We will accept the defaults.
6. Click the Next button. This will bring up the Media Build WizardPlatforms screen. Select Windows 95 and Windows NT 4.0 (Intel).
7. Click the Next button. This will bring up the Media Build WizardSummary screen. This will display the options you have selected.
Look it over for errors.
8. Click the Finish button. This will generate the setup files needed for this media image. When it is complete, click the Finish button
again. This will bring us back to InstallShield.
9. To see the files that were created, click the plus sign (+) next to the Chapter 11_1 Update media icon. Click the plus sign next to the
Floppy icon. Click the plus sign next to the Disk Images icon. Click the Disk1 icon. The files for this image will be displayed in the right pane
as shown in Figure 11-26.
Chapter 11: Maintaining and Supporting an Application
Figure 26: The setup files for the Floppy media image
10. To put your setup on a floppy disk, from the Build menu, select Send Media To This will bring up the Send Media ToSelect Media
screen. Select the Floppy Media Name as shown in Figure 11-27.
Figure 27: Use the Select Media screen to choose the media for your setup
11. Click the Next button. This will bring up the Send Media ToSelect Type screen. You can choose to put the media in a folder or on a
removable disk. Select Copy each disk in the media to a removable disk, as shown in Figure 11-28.
Chapter 11: Maintaining and Supporting an Application
Figure 28: Use the Select Type screen to choose the location to which your media files will be copied
12. Click the Next button. This will bring up the Send Media ToSelect Removable Drive screen. This will allow you to choose the
removable drive on which the setup program is placed.
13. Select drive A: or the drive of your 3.5-inch floppy disk.
14. Click the Next button. This will bring up the Send Media ToStatus screen.
15. Click the Start button. When a floppy disk is in the drive, click OK on the message box that appears. A progress bar will appear that
shows the status of copying the files. When it is done, the screen will have a message telling you it was successfully copied.
16. Click the Close button. You have now created a setup program for your update and put it on a floppy disk.
Now that you have a better idea of how to fix errors and deploy updates, here are some possible scenario questions and their answers.
What is the difference between logic, syntax, and
run-time errors?
Logic errors occur when the results are not what
was expected, but there werent any syntax or
run-time errors. Syntax errors occur due to the
incorrect use of the programming language.
Run-time errors occur when an application attempts
an invalid action.
What happens if an exception occurs within my
exception handler?
The exception will be passed up the calling chain to
the procedure that called it until it finds an
exception handler. If an exception handler is not
found, your application will quit.
I have fixed some errors and added exception
handling to make my program more robust. How do
I get this update to my users?
Use InstallShield to create a setup program and only
include files that have changed. Create the
appropriate media types and distribute the update.
Certification Summary
There are three basic type of errors: logic, syntax, and run-time. Logic errors are incorrect results without a run-time error. Syntax errors result
from using the programming language incorrectly. Visual C++ has some tools to help prevent syntax errors. Run-time errors are the result of
invalid actions, invalid data, or system conditions that prevent code from executing correctly. Run-time errors can cause your program to quit.
Exception handling is used to prevent run-time errors from stopping your application while it is running. It is important to incorporate
exception handling throughout your code to make it more robust. Both the MFC and the C++ programming language support exception
handling. Both of these methods use the try statement to enable exception handling and catch statements to handle any exceptions that occur
within the try statement block. The MFC provides some exception classes that are derived from the CException class. Exception handlers can
be nested and you must be able to determine the flow of execution through the calling chain.
Once you have fixed the errors, or updated the business rules, you need to create a setup program and deploy it to make it available to your
users. You will be distributing only the files that have changed in your update. You can use InstallShield to step you through the process. You
will determine which dialog boxes are displayed during setup, and which files will be included in the update during this process. You can
deploy your update using CD-ROMs, floppy disks, a network server, or over the Internet from a web site or by using e-mail attachments.
Two-Minute Drill
There are three basic types of errors in programming: logic, syntax, and run-time.
Logic errors are the cause when the results of your program are not what you expected. This situation is commonly referred to as a bug
Chapter 11: Maintaining and Supporting an Application
in the code.
You can find some logic errors through code reviews and walkthroughs, but the best way is to test your program.
Syntax errors are the result of using the programming language incorrectly.
Run-time errors are errors that occur while the application is running.
To prevent errors from happening after you distribute your application, you need to implement error trapping and handling.
For run-time errors that occur because of conditions that are beyond a programs control, you should use exception handling and check
for common problems before executing an action.
The catch handlers are examined in order of their appearance following the try block.
There are different reasons for needing updates. It might be that because the business rules for your application have changed you are
adding new features, or you might have customers who discover some bugs that werent found during testing.
The first step to deploy your application is to package it.
You can deploy your update using CD-ROMs, floppy disks, a network server, or over the Internet from a web site or by using e-mail
attachments.
Visual C++ 6.0 provides the InstallShield Wizard to create an InstallShield setup program which includes the necessary files and
dependencies to install your application, register the COM components, and allow for uninstall.
Chapter 11: Maintaining and Supporting an Application