带命名空间选择的新类(C++)向导






3.50/5 (15投票s)
本文向您展示了一些关于编写向导的有用技巧。它包含 JScript 格式的脚本,并为您提供了一个已编辑的“新建类”向导,该向导支持命名空间。
引言
我正在规划一个类框架(到目前为止,我只尝试过一些想法是否可行),它使用命名空间。每次我需要在命名空间中添加一个类时,我都必须选择“新建项”->“新建类”,然后在文件的开头和结尾手动编辑类文件,以添加“namespace NamespaceName {”然后是“}”。手动完成这些操作很烦人,所以我决定编辑原始向导,加入命名空间字段(以及一个用于选择基类的类似选择的控件),正如您在图片中看到的(我使用了 WTL 示例项目来拍摄截图,我不用 WTL,但我手边有)。
我之前已经处理过向导(在 CodeProject 上,有我另一篇关于向导的文章),创建向导文件没有遇到任何问题。语法简单且统一,MS Visual Studio 2005 提供了一个新的项目向导……用于向导;我心想,太棒了。但是,处理向导的问题不在于了解文件格式,而在于了解如何使用脚本。事实上,MSDN 关于这方面的文档非常分散,即使您需要编写 JScript 文件,MSDN 示例绝大多数都是 VB 或 C#。我对 JScript 不是很了解,仅仅是因为我根本不使用它(除了在向导中),所以找到我需要的东西以及如何使用它非常枯燥。最后,我选择发布不仅是新的类向导(这对于一篇文章来说太少了),还包括一些关于使用 JScript 和 JScript DOM 类以及项目访问类(classes)的技巧。我认为没有多少严肃的程序员在任何严肃的项目中使用 JScript,这就是为什么很多人和我一样处于无知状态,所以我会给您一些信息和链接。对于 JScript 专家来说,这篇文章可能没什么用。
关于 JScript 的一些内容
好的,我们将从基础开始;示例中的字符串数组等是 Java 语法(显然)。您可以在 这个 MSDN 页面 上找到所有您可以使用的函数(以及其他函数)。在左侧的目录中,还有两个其他有用的部分(JScript Functions 和 JScript Objects)。但我链接的那个部分,包含了所有对象方法。您也可以在那里找到 JScript 语法。
JScript DOM 类
- 通用的 EnvDTE 命名空间
- CodeModel 接口,用于访问 Visual Studio 内的代码模型
- 高级的
VCCodeModel
接口,用于访问 Visual Studio 8 内的代码模型
关于 CodeModel 的一些内容
如果您使用 VCCodeModel
功能,您将在访问 CodeDOM 方面获得优势。事实上,例如,您可以这样做:
function OnFinish(selProj, selObj)
{
//Get the Global-Namespace collection in the project.
//That is, namespace not inside other namespace or CodeElement
var nss = selProj.CodeModel.Namespaces;
//Get Namespace collection of first global namespace
var nss2 = nss.Item(1).Namespaces;
//Get Firs class in first sub-namespace
var cl1 = nss2.Classes.Item(1);
}
正如您在 Visual Studio (8) 的新版本中可以看到的,DOM 提供了更友好的方式来访问代码模型。在早期版本中,您需要检索 CodeModels
集合,然后检查每个 CodeModel
的类型。需要注意的一点是,CodeModel
的组织方式与普通 DOM 类似,因此每个节点都有子节点,并且有一个主集合,通过它可以访问子节点,如上例所示,其中 selProj.CodeModel.Namespaces
并不是一个通用的列表,而是所有命名空间,每个命名空间都包含子节点(即命名空间内部包含的 CodeModels
),这些子节点可以是类、接口,也可以是其他命名空间。
在每个向导中,您可能已经知道,都有一个实现界面的 HTML 文件和一个 .js JScript 文件(两者都命名为 default.ext)。您可以通过全局变量 'window' 在 htm 文件中调用 window.external
来访问向导,并在 js 文件中通过 'wizard' 来访问。
由于我在编辑向导时找不到其他有用的资源或链接,因此我无法提供更多帮助,因为我不记得它们了。但如果您好奇,下面是我用来搜索的代码,以及一个命名空间和类的列表,尽管它不是很好的代码(如我所说,我根本不了解 JScript)。而且因为我写得很快,想着“哦,请完成你的工作吧,脚本”,所以您可能会发现一些行对您有用(或者至少有趣)。
function InitDocument(document)
{
/*
VS generated code
.
.
.
*/
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;
}
}
}
排序函数还不完美,但对我来说已经足够了。
结论
我知道这不是一篇很棒的文章,也没有提供任何新内容,但我认为下载部分提供的改进的向导对某些人来说会很有用。
所以,我想就这些了。希望您觉得有用,再见!