Introduction
I'm projecting a class framework (so far I have tried only if some ideas I'd got were feasible) which uses namespaces. Every time I needed to add a class inside a namespace, I have to select "New Item" -> "New class" and edit the class file manually at the beginning and at the end of the file to add "namespace NamespaceName {" and then "}". It was annoying doing it manually so I decided to edit the original wizard to include the namespace field (and a select-like choice for base class selection) as you can see in the image (I used a WTL sample project for the example shot, I don't use WTL, but I got it handy).
I have already worked with wizards (on the CodeProject, there's another of my article on it) and there have been no problems in creating wizard files. The syntax is simple and even, and the MS Visual Studio 2005 offers a new project wizard.. for wizards; wonderful, I thought. But the problem when working with wizards is not in knowing the file format, but knowing how to use the scripts. In fact, MSDN documentation on this is very dispersive, and even if you need to script a JScript file, a vast majority of the MSDN examples are in VB or C#. I don't know JScript well, simply because I don't use it at all (except in wizards), so it was very boring to find what I needed and how to use that then. Finally, I chose to publish not only the new class wizard (which was too little for an article) but also some tips about using JScript and JScript DOM code and project access classes. I think not many serious programmers use JScript in any serious project, and that's why a lot of people are in my condition of ignorance, and so I'll give you some info and links. For JScript experts, this article might not be very useful.
Something on JScript
OK, we will start from the basics; the strings array and so on in the example are in Java syntax (obviously). You can find all functions the you can use on them (and others) on this MSDN page. In the TOC on the left, there are two other useful sections (JScript Functions and JScript Objects). The section I linked to, however, includes all object methods as well. You can find JScript syntax too there.
JScript DOM classes
Something on CodeModel
If you use the VCCodeModel
feature, you will have advantages in accessing the CodeDOM. In fact, for example, you can do something like:
function OnFinish(selProj, selObj)
{
var nss = selProj.CodeModel.Namespaces;
var nss2 = nss.Item(1).Namespaces;
var cl1 = nss2.Classes.Item(1);
}
As you can see in the new version of Visual Studio (8), the DOM has more user friendly ways to access code models. In previous versions, you retrieve the CodeModels
collection and then check the type for each CodeModel
. A thing to keep in mind is that the CodeModel
is organized as a normal DOM, so each node has subnodes and there's a main collection of nodes through which you access the children, as you can see in the example above, where the selProj.CodeModel.Namespaces
is not a generic list of all namespaces but only the global namespaces and each of them contains sub-nodes (that is CodeModels
contained inside the namespace) which can be classes or interfaces or also other namespaces as well.
In each wizard, as you probabily already know, there's an HTML file which implements the interface and the .js JScript file (both named default.ext). You have access to the wizard with the global var 'window' calling window.external
in the htm file and with 'wizard' inside the js file.
Because I didn't save in my bookmarks other useful resources or links I found while editing the wizard, I can't be more useful than this because I don't remember them. But if you are curious, there's the code below I used to search, and a list of namespaces and classes, even if it's not a very good code (as I said, I don't know JScript at all). Also because I wrote it very fast thinking, "oh please do your job script", probably you'll find some lines useful for your purposes (or at least interesting).
function InitDocument(document)
{
if (window.external.ProjectObject) {
var proj = window.external.ProjectObject;
var codeModel = proj.CodeModel;
var nssArr, nsArr = new Array();
GetNamespaces(codeModel.Namespaces,nsArr,"");
nssArr = nsArr.sort();
for (var i = 0; i < nssArr.length; i++) {
var oOption = document.createElement("OPTION");
oOption.value = nssArr[i];
oOption.text = nssArr[i];
NAMESPACE.add(oOption);
}
var oOption = document.createElement("OPTION");
oOption.value = "<new>";
oOption.text = "<new>";
NAMESPACE.add(oOption);
var cllArr, clArr = new Array();
GetClasses(codeModel.Classes,clArr,"");
GetNamespaceClasses(codeModel.Namespaces,clArr,"");
clArr = clArr.sort();
cllArr = clArr.sort(SortClasses);
for (var i = 0; i < cllArr.length; i++) {
var oOption = document.createElement("OPTION");
oOption.value = cllArr[i];
oOption.text = cllArr[i];
BASE_CLASSES.add(oOption);
}
var oOption = document.createElement("OPTION");
oOption.value = "<new>";
oOption.text = "<new>";
BASE_CLASSES.add(oOption);
}
}
function GetNamespaces(nss,nsArr,name)
{
for (var i = 1; i <= nss.Count; i++) {
var ns = nss.Item(i);
var l = 0;
var nname = ns.Name;
if (name != "")
{
nname = name + "::" + nname;
}
for (l = 0; l < nsArr.length; l++) {
if (nsArr[l] == nname) {
break;
}
}
if (l == nsArr.length)
{
nsArr[l] = nname;
}
GetNamespaces(ns.Namespaces,nsArr,nname);
}
}
function GetClasses(cls,clArr,name)
{
for (var i = 1; i <= cls.Count; i++) {
var cl = cls.Item(i);
var l = 0;
var nname = cl.Name;
if (name != "")
{
nname = name + "::" + nname;
}
for (l = 0; l < clArr.length; l++) {
if (clArr[l] == nname) {
break;
}
}
if (l == clArr.length)
{
clArr[l] = nname;
}
GetClasses(cl.Classes,clArr,nname);
}
}
function GetNamespaceClasses(nss,clArr,name)
{
for (var i = 1; i <= nss.Count; i++) {
var ns = nss.Item(i);
var l = 0;
var nname = ns.Name;
if (name != "")
{
nname = name + "::" + nname;
}
GetClasses(ns.Classes,clArr,nname);
GetNamespaceClasses(ns.Namespaces,clArr,nname);
}
}
function SortClasses(arr1,arr2)
{
var arr = arr1.split("::");
var arrs = arr2.split("::");
if (arr.length > arrs.length)
{
return 1;
}
else if (arrs.length > arr.length)
{
return -1;
}
else
{
var i;
for (i = 0; i < arr.length-1; i++)
{
if (arrs[i] != arr[i])
{
break;
}
}
if (i == (arrs.length-1))
{
var l = 0;
while (arr[i][l] == arrs[i][l] && l <
arr[i].length && l < arrs[i].length)
{
l++;
}
if (l < arr[i].length || l < arrs[i].length)
{
if (arr[i][l] > arrs[i][l])
{
return 1;
}
else
{
return -1;
}
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
The sort function is not perfect yet, but it was enough for me.
Conclusions
I know this is not a great article and it says nothing new, but I think the improved wizard in the setup in the download section would be useful to someone.
So, that's all, I think. I hope you'll find it useful, bye!