9.1 Wizard BasicsWizard is the generic name for the VS.NET facilities for creating new projects or items. Each of the project types listed in the New Project (Ctrl-Shift-N) and Add Project dialogs is a wizard, as are each of the items in the Add New Item dialog (Ctrl-Shift-A). Some wizards do nothing more complex than creating a new file, but the more advanced ones create several files and may even present a user interface to allow the user to configure the way in which the files are created. However, all wizards are based on the same underlying mechanisms. Two main types of wizards are available in all languages: project wizards and item wizards. (C# and VC++ support a third wizard type: context wizards. However, unlike project and item wizards, you cannot write your own custom context wizard without writing a package, as only packages allow you to extend VS.NET context menus. See the next chapter for information on writing packages.) Each type of wizard uses the same underlying infrastructure, but each serves different purposes.
9.1.1 Implementation ChoicesVS.NET supports three main wizard implementation styles. You can write a one-file item wizard with no code, you can use the VS.NET wizard engine, or you can write your own custom wizard engine. The simplest style is the one-file wizard, but this is the least flexible. You will not be able to display a user interface nor will you be able to customize the file. The most popular approach is to use the VS.NET wizard engine. The majority of the built-in wizards use this technique. The wizard engine allows you to build a user interface for your wizard in HTML and to control its operation with script files. It also supplies a mechanism that lets your wizard modify parts of the files that it adds to the project. For example, if your wizard adds a class definition to a project, you can write a template file that contains the class definition but allows features such as the class name to be set dynamically. Instead of using the built-in wizard engine, you can also write your own custom engine. This lets you use any language capable of implementing a COM component, rather than being limited to scripting languages. It also lets you use any UI technology, rather than having to use HTML. However, it does require more effort to implement than the other two techniques, since very little is automated for you. Regardless of which of these implementation styles you use, the way in which you add new wizards to VS.NET is the same. 9.1.2 Adding WizardsIn order for a wizard to be available to the user, you must copy certain files into the correct directories. VS.NET also needs to know which language your wizard supports—for project wizards, this indicates the project type under which your wizard should appear in the New Project and Add Project dialogs. For item wizards, VS.NET must know which language the wizard supports in order to know when to make the wizard available—when the Add New Item dialog is displayed, it should contain only items appropriate to the current project's language. (This dialog must not offer to add C#-based items to a VB.NET project, for example.) Each language uses a different set of directories for wizards and their configuration files. The VS.NET install directory (typically C:\Program Files\Microsoft Visual Studio .NET 2003) has four subfolders: VC#, VB7, VC7, and VJ#, and each of these in turn has subdirectories that contain the wizard files and wizard configuration information. To indicate to VS.NET what kind of wizard yours is, and the language it is designed for, you copy one or more files into an appropriate directory. Table 9-1 shows which directories you should use for each language, according to whether you are creating a project wizard or an item wizard.
Each of the directories listed in Table 9-1 contains one or more .vsdir files. The .vsdir files contain lists of wizards. For example, the .vsdir files in the VC#\CSharpProjects folder contain entries for all of the items listed in the Visual C# Projects section of the New Projects dialog. If you are using the Professional edition (or better) of VS.NET, this particular directory will contain three .vsdir files—CSharp.vsdir, CSharpEx.vsdir, and DevApp.vsdir, which contain the basic, advanced, and Smart Device project types, respectively. There can be any number of .vsdir files in a particular directory—VS.NET will just concatenate them. To add new wizards, you can therefore simply add your own .vsdir files—there is no need to modify the existing ones. For each wizard there must be a corresponding line in a .vsdir file. These entries consist of a series of fields separated by a | character, and they look like this: Path|PackageID|Name|Order|Description|IconPath|IconID|Flags|BaseName The first field, Path, is usually the relative path to the wizard's .vsz file, which contains the information needed to run the wizard (more on this in a minute). However, for item wizards, you can instead just specify the relative path of any file—if the specified file does not have the .vsz extension, VS.NET will automatically copy that file into the project when the item is selected. This is useful for simple item templates in which the contents of the new item are always the same. (This is how you implement the one-file wizards mentioned earlier.) The second item in a .vsdir entry, PackageID, can be either 0 or the GUID of a VS.NET package. (See Chapter 10 for more information on VS.NET packages.) When a GUID is supplied, it is used for localization—the wizard's name and description can be stored as resources in the package. In this case, the third and fifth items in the .vsdir entry (Name and Description) are resource IDs. The Name will be displayed in the template list on the right of the relevant New/Add dialog, underneath the icon for the template. The Description will appear in the middle of the dialog when the template is selected. When these fields contain resource IDs, VS.NET will display appropriately localized strings in the dialog. Example 9-1 shows an entry that uses this technique—this is the entry for the C# Class Library project. (.vsdir entries are quite long, so this one has been split across multiple lines to make it fit. In the .vsdir file itself, each entry is on its own line.) Example 9-1. .vsdir entry with package IDCSharpDLL.vsz|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}| #2322|20|#2323|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|4547| |ClassLibrary Localization of the name and description requires a package ID, so unless you are a Visual Studio Integration Partner (VSIP—see Chapter 10) and are writing your own package, you will not be able to use this feature for your own wizards. If you are not writing a package, you can just put strings in the Name and Description fields, specifying 0 for the package ID, as Example 9-2 shows. Example 9-2. .vsdir entry with raw stringsMyWizard.vsz|0|My Project|0|My customized project|0|0|0|MyProject The fourth field, Order, determines this item's position in the list in the relevant dialog. The lower the number, the earlier it will appear. Example 9-2 has specified an Order of 0. Since none of the built-in wizards have an Order lower than 1, this guarantees that the new wizard will appear first. The sixth and seventh items, IconPath and IconID, indicate the icon to be used for this wizard in the New Project and Add New Item dialogs. The IconPath can be either another package ID or a string containing the relative path to the DLL. The IconID is the resource id of the icon in the DLL specified by IconPath.
The eighth field, Flags, controls certain features of the New/Add Project/Item dialogs when the template is selected. The supported flag values are:
The last item in the .vsdir entry, BaseName, is used by VS.NET to provide a default suggested name for the new item or project. As with all the other text fields, this can be either a resource ID or a string. (Again, to use a resource ID, you must supply a package ID, so only those signed up for VSIP will be able to use this. The rest of us must supply a raw text string, as Example 9-2 does.) 9.1.2.1 Item wizard .vsdir filesItem wizards are a little more complex than project wizards, because they are subdivided into multiple categories. If you look at the .vsdir file in one of the project item directories listed in Table 9-1, such as CSharpItems.vsdir in the VC#\CSharpProjectItems directory (shown in Example 9-3), you will see that it doesn't actually hold references to wizards. It contains just two lines, both of which are references to folders: WebProjectItems and LocalProjectItems. This is because the set of project items available in the Add New Item dialog is different for local projects and web projects. Moreover, these two folders are divided into more folders, which correspond to the structure that the Add New Item dialog presents in its Categories tree on the left. This means that if you look in the .vsdir files in the WebProjectItems or LocalProjectItems, you will see that these too contain references to other directories. Example 9-3. CSharpItems.vsdirLocalProjectItems|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|#2339|10 WebProjectItems|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|#2340|20 In order for an item wizard to show in the appropriate folders in the Add New Item dialog, you will add .vsdir files in at least two places. Even if you want the item to appear only in local projects, you will still need to add a .vsdir entry in the LocalProjectItems subdirectory and the relevant subcategory (e.g., the Utility directory). If you add it to just the subcategory directory but not the LocalProjectItems subdirectory, your item will not appear when the user selects the top-level Local Project Items category. (All of the VS.NET item templates appear twice—once in the top-level category and once in the more specific category.) Although you need to create or modify .vsdir files in at least two directories, everything else remains the same as it was for a project wizard. Most of the information in the .vsdir file is concerned with how the template will be presented in the New/Add Project or Add Item dialog. However, when the user elects to run the wizard by clicking OK in the relevant dialog, VS.NET will refer to the first field in the .vsdir entry, Path. As already mentioned, for simple item wizards, this can be just the path of a source file that will get copied and added to the project. However, for project wizards or more sophisticated item wizards, Path will refer to a .vsz file that tells VS.NET what to do next. 9.1.3 .vsz FilesWhen the user creates a new project or adds a new item to a project, VS.NET loads the .vsz file for the corresponding wizard, as specified in a .vsdir file. The .vsz file it uses is determined by the first field in the wizard's .vsdir file entry. Example 9-1 specifies the CSharpDLL.vsz file, which is shown in Example 9-4. Example 9-4. The C# class library .vsz fileVSWIZARD 7.0 Wizard=VsWizard.VsWizardEngine.7.1 Param="WIZARD_NAME = CSharpDLLWiz" Param="WIZARD_UI = FALSE" Param="PROJECT_TYPE = CSPROJ" The first line of the .vsz file indicates what version of VS.NET this .vsz file is designed for. (VS.NET 2003 will accept Versions 6.0, 7.0, and 7.1. Although 7.1 is technically the version number for VS.NET 2003, in practice, all of the built-in templates specify 7.0, as this example does.) The second line is the ProgID of the COM coclass that VS.NET will create in order to execute this wizard. Most wizards just specify the wizard engine that ships with VS.NET—VsWizard.VsWizardEngine.7.1. (In VS.NET 2002, the built-in wizards all specified just VsWizard.VsWizardEngine.) The wizard engine is described in the next section.
The remainder of the file is used to supply parameters to the wizard class. If a custom wizard class were in use, you could pass whatever parameters you like here. However, since Example 9-4 is using the wizard engine, all of the parameters that it passes are standard wizard engine parameters. |