Creating a Wizard for Developing Web Applications Using Managed C++
In this section, we'll look at how to create a custom application wizard that generates a Web application using ASP.NET and managed C++. We'll look at the details involved in writing a Web Forms applications using ASP.NET and managed C++ in the second half of the book. For now, we'll create an application wizard that can generate Web Forms applications. A Web Forms application involves several different kinds of files to be generated. In addition, we can add several options such as tracing/debugging options and include several kinds of controls to see how the application wizard works. The files included in the Web Forms application include source code for a Managed C++ DLL, an ASP.NET (ASPX) file, a

The three other check boxes are for managing debug options: one for page tracing, one for request tracing, and one to turn on debugging. The check boxes have IDs of UsePageTracing, UseRequestTracing, and UsePageDebugging. As with the user interface page, the wizard will look for these symbols to add the right code to the generated project.Figure 4-1 shows


Figure 4-1: Default of the ManagedCWebFormWizard application in the finished wizard.
Once the controls are on the page, they need to be associated with symbols that the wizard can use to make substitutions. The wizard's default user interface page (

<SYMBOL NAME="UseCheckBox" TYPE="checkbox" VALUE="false"></SYMBOL>
<SYMBOL NAME="UseTextBox" TYPE="checkbox" VALUE="false"></SYMBOL>
<SYMBOL NAME="UseLabel" TYPE="checkbox" VALUE="false"></SYMBOL>
<SYMBOL NAME="UsePageTracing" TYPE="checkbox" VALUE="false"></SYMBOL>
<SYMBOL NAME="UseRequestTracing" TYPE="checkbox" VALUE="false"></SYMBOL>
<SYMBOL NAME="UsePageDebugging" TYPE="checkbox" VALUE="false"></SYMBOL>
Notice that each of these symbols is associated with a check box on the wizard user interface page.The next step is to take the original source code and insert annotations where you want the wizard to add replacement code. Once we have the original boilerplate code, all the original boilerplate source code for the wizard will live under the Templates directory for that wizard. The final ManagedCWebForm will need to include three files: the header file containing the C++ class, the ASPX file containing the Web page layout information, and the

// ManagedCWebForm.h
#pragma once
using namespace System;
#using <System.Dll>
#using <System.Web.dll>
using namespace System;
using namespace System::Web;
using namespace System::Web::UI;
using namespace System::Web::UI::WebControls;
using namespace System::Collections;
using namespace System::ComponentModel;
namespace ProgVSNET_ManagedCWebForm
{
public __gc class ManagedCWebPage : public Page
{
public:
Button* m_button;
[!if UseLabel]
Label* m_label;
[!endif]
[!if UseTextBox]
TextBox* m_text;
[!endif]
[!if UseCheckBox]
CheckBox* m_check;
[!endif]
ManagedCWebPage()
{
// To do: Construction code here...
}
void SubmitEntry(Object* o, EventArgs* e)
{
// Called when Submit button pressed
// To do: insert Page Loading code here...
String* str;
str = new String("Hello ");
str = str->Concat(str, m_text->get_Text());
str = str->Concat(str, new String(" you pushed Submit"));
[!if UseLabel]
m_label->set_Text(str);
[!if UseLabel]
}
void Page_Load(Object* o, EventArgs* e)
{
// To do: insert Page Loading code here...
[!if UsePageTracing]
Trace->Write("Custom", "Inside Page_Load");
[!endif]
if(!IsPostBack) {
}
}
};
}
When the wizard generates the final code, it looks for the key symbol contained in the square brace to see whether it is in the symbol table. In our example, the expressions are simply Boolean tests. If the check boxes are selected, the controls or debugging features are turned on. Otherwise, they're turned off, and the specific code will be omitted from the generated source code. The same principle applies to every file that needs to be generated. For example, the wizard will take the following boilerplate code for the ASP.NET page and examine the UseRequestTracing, UseTextBox, UseLabel, and UseCheckBox symbols to figure out what code to include:
<%@ Page Language="C#"
[!if UseRequestTracing]
Trace=true
[!endif]
Inherits="ProgVSNET_ManagedCWebForm.ManagedCWebPage"
%>
<html>
<body>
<form runat=server>
<h2>ASP.NET Web Form</h2>
<br><br><br>
<asp:Button Text="Sumit Entry" id="m_button"
OnClick="SubmitEntry" runat=server /><br/>
<asp:Label Text="Type your name here" runat=server />
[!if UseTextBox]
<asp:TextBox id="m_text" runat=server /><br/>
[!endif]
[!if UseCheckBox]
<asp:CheckBox id="m_check" runat=server /> <br/>
[!end]
[!if UseLabel]
<asp:Label id="m_label" runat=server />
[!endif]
</form>
</body>
</html>
The last file that needs to be created is the

<configuration>
<system.web>
[!if UsePageDebugging]
<compilation debug='true'></compilation>
[!endif]
[!if UsePageTracing]
<trace enabled='true'></trace>
[!endif]
</system.web>
</configuration>
In addition to the code boilerplate, the wizard also needs to know which files to include when it generates the application. The Templates directory for the wizards includes a file named








function GetTargetName(strName, strProjectName)
{
try
{
var strTarget = strName;
if (strName.substr(0, 15) == "ManagedCWebForm")
{
var strlen = strName.length;
strTarget = strProjectName + strName.substr(15, strlen - 15);
}
return strTarget;
}
catch(e)
{
throw e;
}
}
After the wizard generates the files, it creates a project out of those files. The scripts for creating the project are found in the scripts subdirectory for the wizard project. The default scripts generated by the Custom Wizard include a method named AddConfig. Visual Studio .NET includes a project object model that lets you change the project configuration of the generated project. Following is the source code that flips the DLL switch on and generates a managed assembly. (We'll cover managed code in the last part of the book.)
function AddConfig(proj, strProjectName)
{
try
{
var config = proj.Object.Configurations('Debug');
config.IntermediateDirectory = 'Debug';
config.OutputDirectory = 'Debug';
config.ConfigurationType = typeDynamicLibrary;
var CLTool = config.Tools('VCCLCompilerTool');
// TODO: Add compiler settings
CLTool.CompileAsManaged = managedAssembly;
var LinkTool = config.Tools('VCLinkerTool');
// TODO: Add linker settings
config = proj.Object.Configurations('Release');
config.IntermediateDirectory = 'Release';
config.OutputDirectory = 'Release';
var CLTool = config.Tools('VCCLCompilerTool');
// TODO: Add compiler settings
CLTool.CompileAsManaged = managedAssembly;
var LinkTool = config.Tools('VCLinkerTool');
// TODO: Add linker settings
}
catch(e)
{
throw e;
}
}
Once the wizard has been created, you need to let Visual Studio .NET know of its existence. In order for Visual Studio .NET to pick up on the wizard, the wizard needs its own directory under \Program Files\Microsoft Visual Studio .NET\VC7\VCWizards. The user interface files go into the HTML directory underneath the wizard directory, the template files (boilerplate code) go into the Templates directory underneath the wizard directory, the images go in the Images directory under the wizard directory, and the scripts go under the Scripts directory underneath the wizard directory. Both the user interface files and the template files can be localized. The VSDIR file, the VSZ file, and the icon file go under \Program Files\Microsoft Visual Studio .NET\VC7\VCProjects. As mentioned earlier, the VSDIR and VSZ files are generated by the Custom Wizard.The application wizard model within Visual Studio .NET is rich and flexible. We only looked at substitutions that use the state of a check box to determine whether to include code. There are many other ways to set up the application wizard to generate any kind of application. In fact, this wizard architecture is also how Visual Studio .NET implements its other wizards— including the ATL Simple Object Wizard, the Generic C++ Class Wizard, and the Add Member Variable Wizard.
Each of these wizards can reach into Visual Studio .NET and access the entire Visual Studio object model, which is how the environment seems to understand the classes and other code within your application.Be sure to check out \Program Files\Microsoft Visual Studio .NET\VC7\VCWizards for more examples—you'll find all of Visual Studio .NET's wizards there.