第一部分
AppWizard
及其工作原理
|
AppWizard即应用程序向导,它是Visual Studio开发环境中强大的编程工具之一,用它可以创建各种不同类型的程序。比如Win32应用、ATL、MFC应用等等。在Windows的术语中,向导(wizard)一词指得是一个应用程序,它的一个主要特点就是提供一系列对话框引导用户进行必要的选择来完成给定的任务。VC中的应用程序向导——AppWizard提供一系列特定工程类型对话框来让程序员定义各种类型的新工程。其中每一个对话框都显示一些用来指定工程类型的选项。例如,用AppWizard创建Windows DLL的时候,第一个对话框让程序员指定诸如要创建什么类型的DLL,是常规类型还是MFC扩展类型,是否要包括自动化支持,以及要不要源代码注释等等。
根据程序员所填充的对话框,
AppWizard会自动创建构造工程所需的框架文件,它们包括:工程文件、工作间文件、源代码文件、头文件、资源文件等等。AppWizard是Visual Studio
开发环境中使用最多的工具之一
。尽管如此,AppWizard也有它的不足之处。那就是常用的工程类型都是内建在Visual Studio
中,无法创建自己的
AppWizard。自从有了Custom AppWizard
(Visual C++ 4.0
)以后,这个问题得到了解决。Custom AppWizard
也就是定制的AppWizard
。在创建类似的多个工程时,Custom AppWizards
显得特别有用。例如你创建的工程都是SDI
,并且都支持自动化(automation
),那么你就可以创建一个自己定制的 AppWizard
,将SDI
自动化设为默认选项。这样可以提高工作效率。此外,利用Custom AppWizard
也可以创建具有个性化的工程。例如你想要所有工程都有一个“关于”对话框,并且在这个对话框中显示个人信息或者公司的标徽及其它专有信息,每个源代码文件中都加上自己的专门注释。那么通过创建一个Custom AppWizard
很容易实现这个需求。你甚至可以定义并显示自己定制的对话框来收集工程类型所需的信息和选项。本文的第一部分我们将讨论AppWizard
的工作原理,然后在后续部分中循序渐进地学习如何创建Custom AppWizard
。最终我们将创建一个在实际编程中非常实用的Custom AppWizard
。并提供全部源代码。
在学会使用Custom AppWizard
之前,首先必须了解AppWizard
的工作原理,理解 AppWizard
是如何根据不同的用户选择来创建工程的。
AppWizard
有一个管理装置(manager
),它不是一个单独的应用程序。Custom AppWizard
运行于Visual Studio
框架之中。AppWizard
的这个所谓的“管理器”,实际上就是MFCAPWZ.DLL
,它控制不同的AppWizard
执行。在创建新工程的对话框中,“Project
”标签是默认的选项,列表框中显示出内建的工程类型。此外,这个列表框中还列出用户定制的AppWizard
,如图一所示。
|
![]() |
图一
|
这些定制AppWizard
文件扩展名为*.awx
,它们存放在一个特定的目录中。如果安装VC6.0
时是按照默认的路径安装的,则定制的AppWizard
文件在成功编译后都会被存放到\Program Files\Microsoft Visual Studio\Common\MSDev98\Template
文件夹中。注意列表框中此新的列表项“MFC AppWizard (exe) – VC
知识库”,这就是我们后面要定制的AppWizard
。从这里可以看出,只要产生了*.awx
文件,那么它就会与标准的(或者说内建的)Visual C++ AppWizard
一起自动显示在这个列表框中。
|
——CCustomAppWiz
类和Dictionary
字典
|
CCustomAppWiz
基类提供了MFCAPWZ.DLL
和Custom AppWizard
之间的通讯服务。CCustomAppWiz()
成员函数的实现就在MFCAPWZ.DLL
中。为了实现特定应用的行为,你只要从CCustomAppWiz
派生一个类,改写相应的虚拟函数,然后在MFCAPWZ.DLL
运行时调用SetCustomAppWizClass()
函数注册派生类即可。
通常,AppWizard
显示一系列对话框获取创建新工程所需的设置。每一个步进对话框显示不同的选项。AppWizard
将这些选项的值存储在一个串映射中。这个串映射就叫做Dictionary
字典。Dictionary
字典实际上是一个CCustomAppWiz
类的成员变量(m_Dictionary
),其类型为CMapStringToString
。Dictionary
将AppWizard
宏映射到相关联的值。这里所说的宏是指工程选项或设置的名称。例如,在创建MFC
的时候,你可以选择应用程序为SDI
,那么,Dictionary
中就会有一个名为PROJTYPE_SDI
的宏。Dictionary
中这个项目的值就是1
,否则这个与这个宏关联的值为0
。
m_Dictionary
成员变量可以被用于创建宏,删除宏或者更新宏的值。因为m_Dictionary
是一个CMapStringToString
对象,肯定有相应的成员函数存取不同宏的值。下面的代码返回PROJTYPE_SDI
宏的值,它被用于判断这个工程是不是一个SDI
应用。
m_Dictionary.Lookup("PROJTYPE_SDI", m_strProjType);
if (_T("1") == m_strProjType)
{
// SDI
类型应用
}
else //
其它类型的程序
{
}
MFCAPWZ.DLL
提供了一些标准宏,任何其它定制AppWizard
所需要的宏都可以用SetAt
函数添加到Dictionary
字典中。你从在线文档中可以找到六十多个标准宏
当你创建Custom AppWizard
并按下Finish
按钮后,MFCAPWZ.DLL
用Dictionary
创建新的工程文件。每一个AppWizard
(不论是标准的还是定制的)都有一套模板文件用于创建AppWizard
生成的工程源文件。Dictionary
中的值被用于与模板文件相连接来创建最终的输出(新的工程文件)。下面是一个例子,中文的基于对话框程序的模板资源文件名叫DlgLoc_chs.rc
。下面是从中摘录出的一段:
...
IDD_ABOUTBOX DIALOGEX 0, 0, 160, 129
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "
关于$$ROOT$$"
...
注意这里 $$ROOT$$
串的用法。当MFCAPWZ.DLL
创建新工程文件时,它首先扫描每一个模板,查找以$$
开始并以$$
结尾的串。在这两个前缀和后缀之间的文本串叫做占位苻。每一个占位符是Dictionary
中一个宏的名字。MFCAPWZ.DLL
在Dictionary
中查询占位符的值并用这个值替换占位符。当所有的占位符都被Dictionary
中相应的值替换之后,工程文件也就产生了。
——用MFCAPWZ.DLL
替代占为符
为了理解MFCAPWZ.DLL
用Dictionary
中宏的值替换模板文件的占位符。我们来做一个实验:
1、
用AppWizard
创建一个基于对话框的应用程序,将工程取名为MyTestDlgApp
。
2、
创建完工程之后,以文本方式打开MyTestDlgApp.rc
文件。
3、
找到IDD_ABOUT
的对话框模板资源。
4、
你应该看到原来模板文件中$$ROOT$$
占位符已经被工程的名字(MyTestDlgApp
)替换掉了。这是因为Dictionary
有一个ROOT
宏,其缺省值被设置为工程的名字。
宏即可被用于定义模板文件中指定的占位符的替换值,有时AppWizard
也用宏来协助步进对话框的显示,或者确定用哪个模板来创建新的工程文件。例如,如果Dictionary
中PROJTYPE_SDI
宏的值为1
,则创建的应用程序是SDI
类型。但是,如果PROJTYPE_DLG
宏的值为1
的话,创建的应用程序是基于对话框的。根据宏的值是否为1
,MFCAPWZ.DLL
使用不同的模板文件来创建工程文件。
大多数AppWizard
都由一系列固定的对话框组成。其中后一个对话框的显示完全依赖于前一个对话框所选择的选项来决定。这种多步进对话框形式称为轨迹。创建MFC
应用程序的AppWizard
是一个多轨迹的AppWizard
。
——多轨迹AppWizard
多轨迹AppWizard
提供了更为复杂的应用程序设置。为了理解多轨迹AppWizard
概念,请做一个如下实验:
1、
按下Ctrl+N
创建新工程
2、
单击“Project
”标签,然后选中“MFC AppWizard (exe)
”。
3、
注意对话框的标题条内容为“MFC AppWizard - Step 1
”,没有指明总共有几步,这是因为总共的步进数在你决定要创建的MFC
工程类型前时未知的。
4、
看一下不同类型工程的选项有何差别:single document (SDI)
,multiple document (MDI)
,和 dialog-based
。选择multiple document (MDI)
类型,然后单击Next
按钮。
5、
注意标题条的内容中指定了总共的步进数——“MFC AppWizard - Step 2 of 6
”。由于你选择了MDI
类型,这个类型总共有六个步进对话框,每一个步进对话框包含特定的基于文档的MFC
应用程序选项。
6、
单击Back
按钮,选择基于对话框的工程类型,然后单击Next
按钮。这一次标题条的内容指定的步进总数是——“MFC AppWizard - Step 2 of 4
”。这说明创建基于对话框的应用程序共有四个步进对话框。
以上是对AppWizards
及其工作原理的讨论。在下一部分我们将尝试创建一个简单的Custom AppWizard
。
|
第二部分
创建一个简单的
AppWizard
|
在第一部分中我们介绍了Custom AppWizard
的概念及其工作原理。在这一部分,我们将尝试用Custom AppWizards
来创建一个最简单的Custom AppWizard
。
首先,我们先创建一个什么事情也不做的Custom AppWizard
,主要是了解它的创建过程和步骤。按Ctrl+N
打开New
对话框,新建一个Custom AppWizards
工程。填入工程名字后单击OK
,从步进对话框的标题中,我们可以了解到总共有两个步骤,在第一个步的对话框中包含三个输入域。
第一个输入域是新Custom AppWizards
的起点。它有三个单选按钮:
|
l Existing project
——这个选项是以一个现存的工程作为蓝本来创建Custom AppWizards
。使用这个选项有两个缺点。第一,AppWizards
创建的是一个已经存在的工程。第二,AppWizards
创建的工程文件名和类名必须与现存工程的文件名和类名一致。
l Standard MFC AppWizard steps
——这个选项是最常用的选项,它创建的AppWizard
模板可用于每一种MFC
支持的工程类型。从修改各种MFC
工程模板文件的灵活性方面,这个选项也是最灵活的。因为这是最通用的一种定制AppWizard
类型,所以我们将以它为例。
l Your own customized steps
——这个选项全新定制一组步进对话框和选项。例如,假设你需要一个定制的AppWizard
来自动创建一个非MFC
应用程序。这时你就得用这个选项创建所有自己定制的对话框。
第二个输入域让你命名新建的定制AppWizard
。这个名字将被用于显示在New Project List
对话框中.
最后一个输入域用来指定定制步进的数目或者对话框的数目,它将被添加到新的定制AppWizard
中。有时候我们不需要额外的步进对话框,比如我们即将创建的简单AppWizard
就不用任何步进。但在第三部分中,我们将会学习如何定制步进对话框。
接下来,按Next
按钮继续到定制AppWizard
的第二步(对话框),也是最后一步。这个对话框中有两个域都是自解释的。第一个域定义新定制的AppWizard
是个可执行程序还是一个DLL
。第二个域指定语言支持选项。
|
设置工程的缺省选项
|
前面我们讲过用AppWizard
创建工程时可以有多种类型可以选择。这一部分我们创建的AppWizard
名字叫SDIAutomationWiz
,在默认情况下,用这个AppWizard
创建的工程类型是支持自动化的SDI
工程。
打开工程的New
对话框,在Project List
中选择Custom AppWizard
,在Project Name
编辑框中输入SDIAutomationWiz
,单击OK
进入第一个步进对话框,选择“Standard MFC AppWizard steps
”,然后指定一个它在Project List
中显示的名字。因为这个AppWizard
没有额外的步进对话框,因此步进数编辑框中填写0
,单击Next
按钮到下一步。选择“MFC AppWizard Executable
”,语言支持为中文,单击Finish
按钮,出现确认对话框。单击OK
后便开始创建新的AppWizard
工程。
——定义CCustomAppWiz
类
虽然编译后的Custom AppWizard
文件扩展名都是.awx
,但是它实际上就是一个通常我们使用的Windows
动态链接库(DLL
)文件。如果你打开SDIAutomationWiz.cpp
文件,你就会看到如下的DLLMain()
函数代码:
// Defining the DLLMain() Function
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason,
LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("SDIAUTOMATIONWIZ.AWX Initializing!\n");
// Extension DLL one-time initialization
AfxInitExtensionModule(SDIAutomationWizDLL, hInstance);
// Insert this DLL into the resource chain
new CDynLinkLibrary(SDIAutomationWizDLL);
// Register this Custom AppWizard with MFCAPWZ.DLL
SetCustomAppWizClass(&SDIAutomationWizaw);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("SDIAUTOMATIONWIZ.AWX Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(SDIAutomationWizDLL);
}
return 1; // ok
}
除了常规的CDynLinkLibrary MFC
扩展动态链接库例程之外,还有一个对SetCustomAppWizClass()
函数的调用。这个函数是从MFCAPWZ.DLL
输出的,用于传递定制AppWizard
中CCustomAppWiz
派生类的指针。因为MFCAPWZ.DLL
通过调用CCustomAppWiz
的成员函数来控制所有AppWizard
的执行,因此它必须用这个指针来调用CCustomAppWiz
派生类中重载的成员函数。
有一点必须牢记在心,那就是尽管你创建了定制的AppWizard
,但MFCAPWZ.DLL
仍然控制着一切。换句话说,你定制的AppWizard
只是用于显示步进对话框,确定对话框以什么顺序显示,以及设置新工程的模人选项。一些重要的工作,诸如解析模板文件,合并Dictionary
中的宏和模板文件中的占为符,创建工程文件等等还是要MFCAPWZ.DLL
来做。
前面我们讲过,CCustomAppWiz
类负责AppWizard
与MFCAPWZ.DLL
之间的通讯。实际上这种通讯是单边的。MFCAPWZ.DLL
告诉你的CCustomAppWiz
对象什么时候需要调用相应的虚拟成员函数。
CCustomAppWiz
类中大约有十来个函数,其中只有五个函数是可以看到并使用的常用例程。通过这些函数的命名你基本上就能了解其主要作用。例如,InitCustomAppWiz()
函数是进行初始化,包括初始化宏。除此之外,ExitCustomAppWiz()
函数的作用是卸载AppWizard
。
另外,还有两个函数用来控制步进对话框的显示顺序。Next()
和Back()
。不说肯定你也知道,这两个函数与AppWizard
对话框中的Next
和Back
按钮是关联的。
最后一个很重要的函数是CustomizeProject()
,一旦程序员完成工程选项的设置,AppWizard
便创建工程的make
文件并定义工程缺省的debug
和release
配置。然后AppWizard
调用CustomizeProject()
函数,以便定制的AppWizard
能在存储工程之前修改make
文件设置。
——宏指令的处理
我们已经知道了宏的初始化是在InitCustomAppWiz()
中进行的,我们也知道了CCustomAppWiz
类有一个成员变量m_Dictionary
,它存储宏名及其值。因为这个成员变量是CMapStringToString
类型的,用标准的MFC
映射函数就能get
或者set
不同的宏,请看下列代码:
// retrieve value for Automation
CString strValue;
m_Dictionary.Lookup(_T("AUTOMATION"), strValue);
// Include support for context sensitive help
m_Dictionary.SetAt(_T("HELP"), strValue.Compare("1"));
现在打开SDIAutomationWizAW.cpp
文件,在InitCustomAppWiz()
函数末尾敲入:
m_Dictionary.SetAt(_T("PROJTYPE_SDI"), _T("1"));
m_Dictionary.SetAt(_T("PROJTYPE_MDI"), _T("0"));
m_Dictionary.SetAt(_T("AUTOMATION"), _T("1"));
然后构造(build
)定制的AppWizard
工程。如果没有出错的话,AppWizard
的.awx
文件会被自动拷贝到专门的目录中,以便MFCAPWZ.DLL
能找到它。
现在按下Ctrl+N
,新定制的AppWizard
应该出现在New
对话框的Project
清单中。如果你使用新的AppWizard
,你会看到工程的默认选项是SDI
程序并支持自动化。通过这个简单的Demo
,我们基本上了解了如何通过定制AppWizard
来设置默认的工程选项。
如果要分发你创建的AppWizard
,只要分发.awx
文件就可以了,把它拷到Visual Studio
的模板文件目录即可。
在这一部分,我们定制了一个简单的AppWizard
,通过一个例子示范了如何处理宏字典。在第三部分中,我们将涉及更多定制AppWizard
的内容,并且还要制作一个实用价值很高的AppWizard
。包括新增加一个步进对话框,获得新步进对话框中的输入信息。用这个定制的AppWizard
创建的所有工程都会在其“关于”对话框中显示在步进对话框输入的信息,并通过静态控制和图像建立URL
链接。此外,用这个AppWizard
创建的每一个源文件都会自动建立程序员自己的专用注释。
|
我们在第二部分中示范的AppWizard例子很简单,没有任何实用性。在这一部分我们将讨论几个关于制作AppWizard的高级话题。然后利用VC提供的Custom AppWizard来创建一个在编程中非常实用的AppWizard。与MFC AppWizard(exe) 产生的常规应用程序相比,用这个定制的AppWizard所创建的工程构造出来的应用程序有两个定制特点:
一是所有程序都会有一个定制的“关于”对话框,在这个对话框中显示自己或公司的有关信息,对话框中还有一个将用户定向到Web站点的静态文字控制或图像(icon和bmp)。
二是工程中每一个源代码文件(*.h和*.cpp)的最上面都会有程序编写着的名字及程序创建日期以及简单的程序说明和注释。
一是所有程序都会有一个定制的“关于”对话框,在这个对话框中显示自己或公司的有关信息,对话框中还有一个将用户定向到Web站点的静态文字控制或图像(icon和bmp)。
二是工程中每一个源代码文件(*.h和*.cpp)的最上面都会有程序编写着的名字及程序创建日期以及简单的程序说明和注释。
这一部分要介绍的主要技术包括:
1、 如何定义和添加AppWizard要用到步进对话框。
2、 如何将Custom AppWizard的专用宏添加到字典中。
3、 如何修改定制AppWizard要用到的模板文件,包括inf文件,资源模板文件等。
4、 将输入信息存储到注册表中,使得每一个工程的公共信息都不用重复输入。
下面我们就开始吧: 进入Visual C++开发环境,如图一:

图一
选择“Project”标签,工程名字可以随便取。这里我取的名字是“VckbaseWiz”,其它选项都默认。
然后单击OK。进入下一个对话框。如图二:

图二
因为我们要建一个标准的MFC AppWizard,所以选择“Standard MFC AppWizard steps”单选按钮。AppWizard的命名最好规范一些,这样便于记忆和辨认。与AppWizard的工程名不同,这个名字要在Project类型清单中列出。我们把它命名为“MFC AppWizard(exe)——VC知识库”。因为在我们创建的这个Custom AppWizard中有一个额外的对话框,所以在设置步进步骤的数目时输入1。单击“Next”进入下一个对话框。如图三:

在注册表中存储宏 通过前面的努力,我们已经创建了一个自己定制的AppWizard,用它创建的每一个MFC应用程序,不论是SDI还是MDI,或是基于对话框,都包含一个特制的“关于”对话框,在这个对话框中可以显示关于作者的信息,程序说明,以及静态超链接。另外这个AppWizard还会在每个源代码文件中加上专门定制的注释说明。但美中不足的是每次创建新工程的时候都要程序员重新输入信息。而这些信息对于每一个新的应用程序都是一样的。为了在可用性方面使我们的程序更加完美,下面将针对这个问题对我们定制的AppWizard进行改进,将工程的公共信息存储在注册表中,当创建新的工程时,AppWizard会首先从注册表中读取这些公共信息,不需要重新输入,除非你确实要改变这些公共信息。 ——在CCustomAppWiz派生类中引入注册表的操作 为了存取注册表信息,我们在定制的AppWizard工程中使用了一个封装类CRegistry。这个类封装了针对注册表的常用操作。我们要对CVckbaseWizAppWiz实现进行修改。以便能在它的实现中使用CRegistry类存取注册表。方法如下:
1、 打开VckbaseWizAw.cpp,在“#include "chooser.h"” 包含语句后面加上“#include "registry.h"”
2、 在InitCustomAppWiz成员函数前面加上如下注册表键值定义:
#define VCKBASEWIZ_KEY "Software\\VCKBASE\\VckbaseWiz"
3、 在VCKBASEWIZ_KEY #define指令之后,定义下列静态结构,其中包含:宏名、注册表值名、宏的缺省值。注册表值名被用来在注册表中查找VCKBASEWIZ_KEY指定的键。如果没有找到键值(例如第一次运行程序时),则会使用宏的缺省值:
static struct { char szMacroName[50]; char szRegistryValueName[50]; char szMacroDefaultValue[1024];//512个汉字 } macroPairs[] = { "PROGRAMMER", "Programmer", "程序员", "WEB_PAGE", "Web Page", "网站", "GENERAL_INFO", "General Info", "程序描述", "COMMENT_INFO", "Comment Info", "程序注释" };
4、 将下列代码添加到CVckbaseWizAppWiz::InitCustomAppWiz()函数末尾,其作用是在堆栈创建CRegistry对象,然后遍历上一步定义的静态结构。对于这个宏结构数组每一个元素,程序都会在注册表中找对应值,如果找到则取注册表中的值,否则取缺省值。不论哪一种情况,宏的值一旦建立,Dictionary字典的值就被更新为当前宏的值:
CRegistry registry(HKEY_LOCAL_MACHINE, VCKBASEWIZ_KEY); CString strValue; for (int i = 0; i < sizeof macroPairs / sizeof macroPairs[0]; i++) { if (registry.ReadString(macroPairs[i].szRegistryValueName, strValue.GetBuffer(strValue.GetLength()))) { m_Dictionary.SetAt(macroPairs[i].szMacroName, strValue); } else { m_Dictionary.SetAt(macroPairs[i].szMacroName, macroPairs[i].szMacroDefaultValue); if (m_Dictionary.Lookup(macroPairs[i].szMacroName, strValue)) { registry.WriteString(macroPairs[i].szRegistryValueName, strValue.GetBuffer(strValue.GetLength())); } } }5、 将下列代码添加到CVckbaseWizAppWiz::ExitCustomAppWiz()函数末尾,其作用是当卸载定制的AppWizard DLL时程序会调用这个函数存储数据。 CRegistry registry(HKEY_LOCAL_MACHINE, VCKBASEWIZ_KEY); CString strValue; for (int i = 0; i < sizeof macroPairs / sizeof macroPairs[0]; i++) { if (m_Dictionary.Lookup(macroPairs[i].szMacroName, strValue)) { registry.WriteString(macroPairs[i].szRegistryValueName, strValue.GetBuffer(strValue.GetLength())); } }大功告成,现在构造定制的AppWizard。如果没有出错的话,则编译生成的.awx文件会被自动拷贝到Visual Studio的Template目录。 接下来测试一下我们定制的AppWizard,New一个新工程,在工程类型列表中选择“MFC AppWizard (exe) – VC知识库”,创建一个基于对话框的应用程序,最后一个对话框是我们在Custom AppWizard工程中定制的对话框,如图五: ![]() 图五 输入相应的信息后,单击“Finish”按钮,显示确认对话框,你在定制对话框中输入的信息也应该在此确认对话框中显示。单击“OK”按钮创建工程。然后编译并运行。对话框中可以见到三个按钮:“确定”、“取消”、“关于”。单击“关于”按钮,弹出对话框如图六: ![]() 图六 这就是我们定制的“关于”对话框。这个对话框中有带URL链接的静态文字、icon和Bitmap图像。 我真的觉得它很酷! [全文完] |
![]() | ![]() ![]() ![]() |
![]() ![]() #import "devbld.pkg" #include <bldauto.h> #include <blddefs.h> #include <bldguid.h> 在cpp文件中修改CustomizeProject函数 CustomizeProject(IBuildProject* pProject) { using namespace DSProjectSystem; long lNumConfigs; IConfigurationsPtr pConfigs; IBuildProjectPtr pProj; CString sTemp; // Needed to convert IBuildProject to the DSProjectSystem namespace pProj.Attach((DSProjectSystem::IBuildProject*)pProject, true); pProj->get_Configurations(&pConfigs); pConfigs->get_Count(&lNumConfigs); //Get each individual configuration for (long j = 1 ; j < lNumConfigs+1 ; j++) { _bstr_t varTool; _bstr_t varSwitch; IConfigurationPtr pConfig; _variant_t varj = j; pConfig = pConfigs->Item(varj); varTool = "link.exe";//修改链接选项 varSwitch = "yourlib.lib"; pConfig->AddToolSettings(varTool, varSwitch, varj); } } ( liuke716 发表于 2003-12-29 14:32:00) |
转载自:[url]http://www.vckbase.com/document/viewdoc/?id=276[/url]
毕业以后想从事计算机的大学生必须去一个网站: [url]http://www.RuPeng.com[/url]
转载于:https://blog.51cto.com/cownew/136570