Contents
Visual C++ Express, like all the Express versions, offers a free, almost full function implementation IDE for developing C++ applications on Microsoft Windows. While the Express Edition provides a number of skeleton projects, it does not include the ability to create custom wizards; a serious deficiency in my opinion. However, all is not lost, as it is still possible to create a custom wizard by hand which should provide for the needs of the most demanding developer.
This article attempts to demonstrate the steps necessary to 'roll your own' wizard. The details presented here are based on Visual C++ 2008 Express Edition, but with a few modifications, it can be adapted to the 2005 or (I hope) future versions.
The information presented here assumes a knowledge of C/C++ (for obvious reasons), and also HTML and JavaScript; although in depth understanding of the latter two is not essential.
The concept behind the custom wizard is that the developer can create a skeleton project which contains the main source and resource files to build various flavours of a 'standard' application, which can then be modified to the specific needs of the job in hand. The skeleton project is a buildable set of source modules that contains the most common features of a project, thus easing the development cycle. While it is still quite simple to use copy and paste to copy blocks of code from one project to another, the custom wizard is able to generate all the files needed for a project with just a few dialogs. In addition to providing the skeleton source and resource files, the wizard allows for selective generation of files or parts of files, project build options and customized content based on user selected options and wizard variables. The wizard engine contains a number of standard variables, and new ones may be added to the custom wizard as described below.
The source tree for the custom wizard project follows the source tree structure in the $(VCInstallDir) directory, which is at
C:\Program Files\Microsoft Visual Studio 9.0\VC on my system.
The custom wizard files are installed in the VCProjects and VCWizards directories in this tree which look like this:
Visual C++ Express Wizard Directories | |
The Express\VCProjects directory holds the registration files for the custom wizard, and the VCWizards directory holds the control and template files to build a new project.
The first thing we need for a custom wizard is a skeleton project, and I always start by copying the directory tree of the AppWiz\Generic\Application project under the VCWizards directory into my project workspace. I can then edit these files as necessary for my custom wizard without the risk of damaging the Microsoft supplied version. The completed solution is downloadable from the link at the start of this article. The project I am creating here is a fairly basic one which will produce either a simple Win32 application or a dialog based one, but I hope it demonstrates some of the possible options.
The second thing we need is to create the control files that drive the wizard engine dialogs which allow us to select the project type and any optional settings in order to generate our new project.
Finally we need to register our wizard with the Visual C++ Express system so that we can select it from the New Project dialog.
It is not very easy to test the new wizard without having it registered so we will take these steps in the wrong order, which I hope will actually help you understand how it all fits together. In the sample I have created, I have named the wizard CustomWiz
but you are free to name it anything you like as long as it does not conflict with one already registered.
A final note: All the files in the wizard are effectively text files so do not need to be built in the traditional sense. They do, however, need to be copied to the wizard location in the VCWizards
tree, and I use a custom build step similar to the following to achieve this:
- Command Line:
copy "$(InputPath)" "$(VCInstallDir)VCWizards\CustomWiz\Generic\Application\html\1033"
- Description:
copying $(InputFileName) to $(VCInstallDir)VCWizards\CustomWiz\Generic\Application\html\1033
- Outputs:
$(VCInstallDir)VCWizards\CustomWiz\Generic\Application\html\1033\$(InputFileName)
Note that the destination paths will need to point to the correct part of the tree for each group of files; see the sample project for further information. Note also that under Windows 7 (and probably Vista), you will need to run VC++ Express as Administrator the first time you build the project, as it will need to create new directories in $(VCInstallDir)
which is a protected location.
The definition files in the Express\VCProjects directory identify the name and location of the wizard, whose control and template files are stored under the VCWizards directory thus:
- CustomWiz.vsz: identifies the Wizard engine and gives the relative path (under
VCWizards
) to the control and template files.
VSWIZARD 7.0
Wizard=VsWizard.VsWizardEngine.9.0
Param="WIZARD_NAME = Application"
Param="RELATIVE_PATH = VCWizards\CustomWiz\Generic"
Param="WIZARD_ID = 103"
- The
VSWIZARD
and Wizard
version numbers may need to be adjusted for different versions of Visual C++ Express. - The actual path of the wizard control and template files is a composite of
RELATIVE_PATH
and WIZARD_NAME
, which in this case will be VCWizards\CustomWiz\Generic\Application. Note that this path structure should follow the same structure as the Microsoft wizards already installed. - The
WIZARD_ID
field should be unique among all the wizards registered on the system.
- CustomWiz.ico: An icon to display in the New Project dialog.
- CustomWiz\CustomWiz.vsdir: Parameters for the wizard defining the new project and the relative path to the CustomWiz.vsz file; parameters are separated by the '|' pipe symbol.
# Field contents are as follows: see Inside Visual C++ Wizards[<a title=""New" href="%22http://msdn.microsoft.com/en-gb/library/aa730846(VS.80).aspx%22" target=""_blank"">^</a>]
# RelPathName - relative path from here to the .vsz file
# {clsidPackage} - always zero for user defined wizards
# LocalizedName - name that appears in the Add New Project dialog box
# SortPriority - sort order and relative priority of the Wizard,
# with 1 being highest
# Description - A localizable description as it will appear in the
# Add New Project dialog when the item is selected
# DLLPath - always zero for user defined wizards
# IconResourceId - always zero for user defined wizards
# Flags - generally zero
# BaseName - suggested base name for the generated item,
# displayed in the Name field in the Add New Project dialog
#
..\CustomWiz.vsz|0|Custom Windows application|1|Create a
Custom Windows application or dialog|0|0|0|WinApp
Having created the above files, they may now be copied to the Express\VCProjects directory (see notes above for build rules), and the wizard should now show up in response to the following:
- Select File->New->Project from the Visual C++ Express menu; this will display the New Project dialog.
- Select
CustomWiz
in the "Project types:" frame. - Select
Win32 Windows application
from the "Templates:" frame. - Adjust any other parameters as necessary and press OK.
Note that if you actually do press OK on the dialog at this time, you will get an error message as there is no wizard to run yet; that is addressed in the next section.
The wizard control files are stored in the VCWizards\CustomWiz\Generic\Application directory (see CustomWiz.vsz above). Note that in these directory trees 1033
is the numeric representation of the Windows language code for English; check on your own system for the correct value and adjust as appropriate. The actual control files are modified versions of Microsoft's originals, so be careful not to offer your custom wizard for sale, as that would infringe Microsoft's copyright. The actual directory tree structure is as follows:
- html\1033: contains the htm files used by the wizard to display the project options dialogs.
- default.htm: the initial page of the wizard dialog.
- Appsettings.htm: the project selection and options page.
- images: images shown in the dialog by the htm files.
- scripts\1033: additional JavaScript used by the htm files.
- default.js: JavaScript functions to adjust various project settings for the build process.
- The default.htm file
The first page to be displayed by the wizard engine is generated by the default.htm file which can be seen in the section titled "Using the Wizard" below.
The modified markup for this is shown within the file itself, with each change marked by a comment of the form:
and in some cases the original Microsoft code will be enclosed in a HTML comment block. The actual changes are as follows:
- Custom wizard title: The title displayed at the top of the wizard dialog.
- Additional project symbols: add symbols as required in template files (see Templates).
- Symbols defining the project type: Global symbols used in default.htm to identify the currently selected project type. These values are selected from within Appsettings.htm.
- Project Wizard heading and description: Text describing the project types that can be generated with this wizard.
- JavaScript changes
- Ignore Console Apps
- Change Dialog Title
- The AppSettings.htm file
This file contains the markup to select the project type and options for the generated project, and can also be seen in the "Using the Wizard" section below.
It is annotated in the same manner as default.htm with the CustomWiz
tag. The changes are not numbered, but fall into the following categories as shown in the file itself.
- Custom wizard title: our own dialog title.
- Additional image files: additional .GIF files used by the project selection dialog.
- Project type: radio buttons used to select the project type to generate.
- add DLG_APP option: check for one of our project types.
- disable EMPTY_PROJECT and ATL support
* add PRE_COMPILED HEADER: disable options of the Microsoft version, and add option for pre-compiled headers. - disable ATL, MFC options: further Microsoft options.
- JavaScript changes: changes to the JavaScript code necessitated by the removal of some of the Microsoft options. See individual comments for detail.
The individual changes are not listed here but broadly speaking they are used to disable some of the options offered by the Microsoft Win32 wizard, from which this was derived, and to add the options for creating the two project types offered by this wizard; use the Edit->Find option to locate the changes. The addition of other project types and options is left as an exercise for the reader.
- The default.js script file
This file contains further JavaScript which is invoked by the wizard when the user presses the OK button to generate the new project. There is very little information on the functions in this module, so I will list here what I have discovered by trial and (lots of) error; modify to your own needs as required.
OnFinish()
: Sets some common values and calls other functions required to construct the project. SetFileProperties()
: Sets extra compile options for specific files. GetTargetName()
: Returns the name of a module, altered as required by the wizard. GetAppType()
: Returns a string to define which application type is being generated. AddSpecificConfig()
: Adds or modifies build options for specific configurations.
The following changes have been made to the foregoing, and are annotated as described earlier.
- Disable empty project: don't offer the EMPTY PROJECT option here
- add YEAR and DATE wizard variables for use in code templates: q.v.
- disable LIB and CONSOLE types: unsupported in CustomWiz
- disable unsupported project types: remove unused project type selectors
- add the DLG_APP option: add our own extra project type
- disable unsupported types: as above
- disable unsupported options: as above
- disable unsupported types and options: as above
- add Dialog project type: add to config generator
- change DLL type to DLG type: change option type name
- disable console option: as above
- same changes as above for Debug configuration: add similar changes for Release config
The wizard template files are the remaining files that are used to build the skeleton project. In its simplest form, a skeleton project contains one set of source files which will always build into the same basic application. There is little to be gained from such a project being generated by a wizard however. The point of using the wizard is to allow the user to select a different project type, and to customize the project by selecting various options, as described in the following sections. All of the template files are stored in the VCWizards\CustomWiz\Generic\Application directory as follows:
- templates\1033: The project template files as created by the developer.
- The basic source and resource files required to build a project of the selected type (see below)
- Templates.inf: control file that identifies which files are used to create the project
Optional selections made in the wizard dialogs are held as property items within the wizard engine and allow the project control files to amend the project itself, but also allows the template files to contain statements controlling the generation or suppression of parts of the source. This is where the real power of the code wizard lies, as it allows us to start from a single source file which is customizable by the user. The sample code I have provided here will generate two applications as defined earlier, a simple Windows or Dialog application. I have tried to keep both applications as simple as possible to demonstrate the basics of the wizard without the clutter of a sophisticated end product.
The source files for these applications are as follows:
- root.cpp: the main source of the Windows application.
- root.h: header file for either project.
- root.ico: application icon file.
- root.rc: resource scripts for both project types.
- rootDlg.cpp: main source module for the Dialog application.
- StdAfx.cpp: precompiled header source module.
- StdAfx.h: includes for the project.
- Templates.inf: control file for the project wizard.
Note that although the source file names take the form root.xxx or rootXXX.xxx their names are generally changed by the scripts such that 'root' is replaced by the project name. This change is as defined in the GetTargetName()
function in default.js.
In all cases, the source code can be generated or suppressed by control statements in each module, similar to preprocessor directives. However, this source is modified at the time the project is generated rather than at compile time. The format of these statements is:
[!if {expression}]
source line(s) if expression is TRUE
[!else]
source line if expression is FALSE
[!endif]
Other information may be injected into these files by use of the [!output {e}]
directive, for example a line of the form...
#include "[!output PROJECT_NAME].h"
... in a source file whose project name is 'winapp
' would then become...
#include "winapp.h"
... in the generated source file. Further information on template directives may be found in the MSDN on creating wizards, in the Template Directives[^] section.
The Templates.inf file is used to define the source files that will be copied to the new project when the wizard executes. It may contain wizard directives to select certain files based on project type, and will be used by the default.js file. The sample for the CustomWiz
wizard looks like this:
StdAfx.h
StdAfx.cpp
root.h
[!if WIN_APP]
OpenFile | root.cpp
[!else]
OpenFile | rootDlg.cpp
[!endif]
root.rc
CopyOnly | root.ico
The OpenFile
directive means that the referenced file will be opened in the IDE when the project is first created. The CopyOnly
directive indicates that the wizard should not inspect the content for directives; this is useful for icons, bitmaps and other non-source files.
Having created the control and template files, we are now ready to test the wizard. Firstly we need to copy all of the wizard files into the VCWizards directory as defined above. Assuming that we have correctly set the build properties on each of the files, we can simply press the Build CustomWiz
button, and all will be copied to their correct locations.
Using the wizard is simply a matter of selecting File->New->Project form the menu, or Ctl+Shift+N from the keyboard. As we saw above, this will bring up the New Project dialog:
which should still include our CustomWiz option in the Project Types box. Select the appropriate Template type and name for the project and press OK
. This brings up the Custom Wizard dialog:
which shows the base details of the current selection. Pressing Next
forwards to the
page, which allows selection of the project type and additional options. Finally pressing Finish
should cause the wizard to generate the project from the template files as appropriate, and open the new project ready to be modified as required by the user.
The structure of the wizards is moderately complex but once I got to grips with how the different pieces fit together it became slightly easier to make changes. The main problem was the paucity of documentation for the Express versions; I report this as a fact, not a criticism, as I still think the Express editions are excellent products.
If you create a syntax error or misname a variable within the HTML or JavaScript, then the wizard is likely to fail with a very cryptic message box. So you know there is something wrong but there is not likely to be anything as useful as a script line number to help you - good luck!
There are probably more things to learn about this process, but I'm more interested in getting a quick working baseline program to solve whatever problem I am working on.
- 8th November 2009 : Initial version