正在处理您的请求...
<script language="javascript" type="text/javascript">
</script>
element block and removes
// previous instances of the identical script.
var found = false;
for (var child = 0; child < head.childNodes.length; child++) {
var control = head.childNodes[child];
if (control.tagName.toUpperCase() == "SCRIPT") {
if (script.src.length > 0) {
if (script.src == control.src) {
found = true;
break;
}
} else if (script.innerHTML.length > 0) {
if (script.innerHTML == control.innerHTML) {
found = true;
break;
}
}
}
}
if (found) {
head.removeChild(control);
}
// Now we append the new script and move on to the next script.
// Note that this is a recursive function. It stops when the
// index grows larger than the number of scripts.
document.getElementsByTagName('head')[0].appendChild(script);
if (typeof script.readyState != "undefined") {
script.onreadystatechange = function() {
if (script.readyState != "complete" && script.readyState != "loaded") {
return;
} else {
Anthem_LoadPageScript(result, index + 1);
}
}
} else {
Anthem_LoadPageScript(result, index + 1);
}
}
} catch (e) {
Anthem_DebugError("Error adding page script to head. " + e.name + ": " + e.message);
}
}
}
function Anthem_EvalClientSideScript(result) {
if (result.script) {
for (var i = 0; i < result.script.length; ++i) {
try {
eval(result.script[i]);
} catch (e) {
alert("Error evaluating client-side script!/n/nScript: " + result.script[i] + "/n/nException: " + e);
}
}
}
}
function Anthem_DebugRequestText(text) {
}
function Anthem_DebugResponseText(text) {
}
function Anthem_DebugError(text) {
}
//Fix for bug #1429412, "Reponse callback returns previous response after file push".
//see http://sourceforge.net/tracker/index.php?func=detail&aid=1429412&group_id=151897&atid=782464
function Anthem_Clear__EVENTTARGET() {
var form = document.getElementById(Anthem_FormID);
Anthem_SetHiddenInputValue(form, "__EVENTTARGET", "");
}
function Anthem_InvokePageMethod(methodName, args, clientCallBack, clientCallBackArg) {
Anthem_Clear__EVENTTARGET(); // fix for bug #1429412
return Anthem_CallBack(null, "Page", null, methodName, args, clientCallBack, clientCallBackArg, true, true);
}
function Anthem_InvokeMasterPageMethod(methodName, args, clientCallBack, clientCallBackArg) {
Anthem_Clear__EVENTTARGET(); // fix for bug #1429412
return Anthem_CallBack(null, "MasterPage", null, methodName, args, clientCallBack, clientCallBackArg, true, true);
}
function Anthem_InvokeControlMethod(id, methodName, args, clientCallBack, clientCallBackArg) {
Anthem_Clear__EVENTTARGET(); // fix for bug #1429412
return Anthem_CallBack(null, "Control", id, methodName, args, clientCallBack, clientCallBackArg, true, true);
}
function Anthem_PreProcessCallBack(
control,
e,
eventTarget,
causesValidation,
validationGroup,
imageUrlDuringCallBack,
textDuringCallBack,
enabledDuringCallBack,
preCallBackFunction,
callBackCancelledFunction,
preProcessOut
) {
preProcessOut.Enabled = !control.disabled;
var preCallBackResult = true;
if (preCallBackFunction) {
preCallBackResult = preCallBackFunction(control);
}
if (typeof(preCallBackResult) == "undefined" || preCallBackResult) {
var valid = true;
if (causesValidation && typeof(Page_ClientValidate) == "function") {
valid = Page_ClientValidate(validationGroup);
}
if (typeof(WebForm_OnSubmit) == "function") {
valid = WebForm_OnSubmit();
}
if (valid) {
var inputType = control.getAttribute("type");
inputType = (inputType == null) ? '' : inputType.toUpperCase();
if (inputType == "IMAGE" && e != null) {
var form = document.getElementById(Anthem_FormID);
if (e.offsetX) {
Anthem_SetHiddenInputValue(form, eventTarget + ".x", e.offsetX);
Anthem_SetHiddenInputValue(form, eventTarget + ".y", e.offsetY);
} else {
Anthem_SetHiddenInputValue(form, eventTarget + ".x", e.clientX - control.offsetLeft + 1);
Anthem_SetHiddenInputValue(form, eventTarget + ".y", e.clientY - control.offsetTop + 1);
}
}
if (imageUrlDuringCallBack || textDuringCallBack) {
if (control.nodeName.toUpperCase() == "INPUT") {
if (inputType == "CHECKBOX" || inputType == "RADIO" || inputType == "TEXT") {
preProcessOut.OriginalText = GetLabelText(control.id);
SetLabelText(control.id, textDuringCallBack);
} else if (inputType == "IMAGE") {
if (imageUrlDuringCallBack) {
preProcessOut.OriginalText = control.src;
control.src = imageUrlDuringCallBack;
} else {
preProcessOut.ParentElement = control.parentElement ? control.parentElement : control.parentNode;
if (preProcessOut.ParentElement) {
preProcessOut.OriginalText = preProcessOut.ParentElement.innerHTML;
preProcessOut.ParentElement.innerHTML = textDuringCallBack;
}
}
} else if (inputType == "SUBMIT") {
preProcessOut.OriginalText = control.value;
control.value = textDuringCallBack;
}
} else if (control.nodeName.toUpperCase() == "SELECT") {
preProcessOut.OriginalText = GetLabelText(control.id);
SetLabelText(control.id, textDuringCallBack);
} else {
preProcessOut.OriginalText = control.innerHTML;
control.innerHTML = textDuringCallBack;
}
}
control.disabled = (typeof enabledDuringCallBack == "undefined") ? false : !enabledDuringCallBack;
return true;
} else {
return false;
}
} else {
if (callBackCancelledFunction) {
callBackCancelledFunction(control);
}
return false;
}
}
function Anthem_PreProcessCallBackOut() {
// Fields
this.ParentElement = null;
this.OriginalText = '';
this.Enabled = true;
}
function Anthem_PostProcessCallBack(
result,
control,
eventTarget,
clientCallBack,
clientCallBackArg,
imageUrlDuringCallBack,
textDuringCallBack,
postCallBackFunction,
preProcessOut
) {
if (postCallBackFunction) {
postCallBackFunction(control);
}
control.disabled = !preProcessOut.Enabled;
var inputType = control.getAttribute("type");
inputType = (inputType == null) ? '' : inputType.toUpperCase();
if (inputType == "IMAGE") {
var form = document.getElementById(Anthem_FormID);
Anthem_RemoveHiddenInput(form, eventTarget + ".x");
Anthem_RemoveHiddenInput(form, eventTarget + ".y");
}
if (imageUrlDuringCallBack || textDuringCallBack) {
if (control.nodeName.toUpperCase() == "INPUT") {
if (inputType == "CHECKBOX" || inputType == "RADIO" || inputType == "TEXT") {
SetLabelText(control.id, preProcessOut.OriginalText);
} else if (inputType == "IMAGE") {
if (imageUrlDuringCallBack) {
control.src = preProcessOut.OriginalText;
} else {
preProcessOut.ParentElement.innerHTML = preProcessOut.OriginalText;
}
} else if (inputType == "SUBMIT") {
control.value = preProcessOut.OriginalText;
}
} else if (control.nodeName.toUpperCase() == "SELECT") {
SetLabelText(control.id, preProcessOut.OriginalText);
} else {
control.innerHTML = preProcessOut.OriginalText;
}
}
if (clientCallBack) {
clientCallBack(result, clientCallBackArg);
}
}
function Anthem_FireCallBackEvent(
control,
e,
eventTarget,
eventArgument,
causesValidation,
validationGroup,
imageUrlDuringCallBack,
textDuringCallBack,
enabledDuringCallBack,
preCallBackFunction,
postCallBackFunction,
callBackCancelledFunction,
includeControlValuesWithCallBack,
updatePageAfterCallBack
) {
var preProcessOut = new Anthem_PreProcessCallBackOut();
var preProcessResult = Anthem_PreProcessCallBack(
control,
e,
eventTarget,
causesValidation,
validationGroup,
imageUrlDuringCallBack,
textDuringCallBack,
enabledDuringCallBack,
preCallBackFunction,
callBackCancelledFunction,
preProcessOut
);
if (preProcessResult) {
Anthem_FireEvent(
eventTarget,
eventArgument,
function(result) {
Anthem_PostProcessCallBack(
result,
control,
eventTarget,
null,
null,
imageUrlDuringCallBack,
textDuringCallBack,
postCallBackFunction,
preProcessOut
);
},
null,
includeControlValuesWithCallBack,
updatePageAfterCallBack
);
}
}
function AnthemListControl_OnClick(
e,
causesValidation,
validationGroup,
textDuringCallBack,
enabledDuringCallBack,
preCallBackFunction,
postCallBackFunction,
callBackCancelledFunction,
includeControlValuesWithCallBack,
updatePageAfterCallBack
) {
var target = e.target || e.srcElement;
if (target.nodeName.toUpperCase() == "LABEL" && target.htmlFor != '')
return;
var eventTarget = target.id.split("_").join("$");
Anthem_FireCallBackEvent(
target,
e,
eventTarget,
'',
causesValidation,
validationGroup,
'',
textDuringCallBack,
enabledDuringCallBack,
preCallBackFunction,
postCallBackFunction,
callBackCancelledFunction,
true,
true
);
}
function GetLabelText(id) {
var labels = document.getElementsByTagName('label');
for (var i = 0; i < labels.length; i++) {
if (labels[i].htmlFor == id) {
return labels[i].innerHTML;
}
}
return null;
}
function SetLabelText(id, text) {
var labels = document.getElementsByTagName('label');
for (var i = 0; i < labels.length; i++) {
if (labels[i].htmlFor == id) {
labels[i].innerHTML = text;
return;
}
}
}
//]]> </script> <script type="text/javascript" src="http://blog.csdn.net/WebResource.axd?d=1wkz58Z1rsBL-eFHJPld5ERhyO-4qXtUzHp7Q1KwrOE1&t=632963535947587500"></script> <script type="text/javascript">
</script>
<script type="text/javascript">function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>
WTL 开发者指南
注:本文是袁晓辉根据 Eamon O’ Tuathail 的 WTL Developer’s Guide(www.clipcode.biz ) 翻译而来,发布在 www.farproc.com 和 blog.csdn.net 。作者翻译本文仅仅是为自己和其他 WTL 爱好者学习之用,请勿用于商业用途。你可以转载本文,但必须保证本文的完整性,并保留该声明!
第 1 章 WTL 概述
目标
该章的目标为:
Ÿ WTL 在整个 VC++ 开发中所处的位置
Ÿ WTL 的目标
Ÿ WTL 和其他用户界面( UI )开发技术的对比
Ÿ 介绍 WTL 的安装
Ÿ 介绍 WTL 安装了什么
Ÿ 列举可用的开发资源
Ÿ 对后面各章的介绍
概述
以前 Visual C++ 开发者往往选择 MFC ,因为它提供的功能涵盖了非常广的编程技术领域而模板库所涉及的领域相对狭窄。
最近模板库涉足的领域和质量都有很大发展,因而越来越多的人选择了模板库。
ATL 设计的目标是提供快速紧凑的 COM 组件, ISO C++ 的 STL 提供集合( collections ), VC++ OLE DB Data Consumer and Provider 模板提供数据库支持。与之相对应, MFC 提供了一个 C++ 类库,这个类库包含对 COM 创建、集合类( collection class )、数据库和用户界面的普遍支持。
大部分的高级开发人员更喜欢较新的模板开发方式。 MFC 很庞大、臃肿、对线程不友好,并且,基本上已经过时了!模板的方法既快速(当正确设计时)、有弹性而且涵盖了所有最新的技术,拿来应对新的开发需要是再好不过的了。
到目前为止,让模板狂热分子头疼的主要问题在于如何创建图形用户界面( GUI )。 ATL 确实提供了一个轻量级的 Win32/64 windowing 包装类,但是它并没有涵盖所有的 UI 需求。 ATL 开发者为了琐碎的用户界面处理不得不重操 MFC UI 编程或者用 VB 给自己的 ATL COM 做前端,这两种方法都不能完全令人满意。
进入正题,开始说窗口模板库( Windows Template Library )。 WTL 是一个居于 Win32/64 API 之上的一个包装类和方便易用的增强模板的高级集合,它对图形用户界面提供了广泛的支持。 WTL 不但保持着模板库的真正血统,小巧,快速,不具侵入性而且包括了最新的 UI 理念,非常好地支持多线程。你可以单独使用 WTL 或和 ATL 、 STL 、 VC++ Data Templates 、第三方类库,以及你自己的类库一起使用以便利用他们各自的优点。 WTL 通常不依赖外部的 DLLs ,如果你用 WTL 开发程序的话,你提供给最终用户的可以只有一个 EXE 文件。
WTL 的目标
WTL 之于用户界面就像 ATL 之于 COM 、 STL 之于 collection 。和它的堂兄一样, WTL 需要一段时间来学习,但是一旦掌握了,就没有比它更好的开发高级程序的途径了。从本质上说, WTL 完成了三个重大任务:
提供了一个应用程序框架( framwork )
集合了 UI 功能
包装了 windows 控件、系统对话框和 GDI 对象
让我们逐个来看。
提供了一个应用程序框架
WTL 提供了一个轻量级的广泛的应用程序框架,这个框架为基于它的程序提供了非常有价值的工具。它的目标既不是像 MFC 框架那样难以理解也不像手工写 WinMain 那样原始。
WTL 包含了一系列的 C++ 模板和一个 WTL AppWizard , AppWizard 向程序开发者提出几个问题,然后据此生产 VC++ 工程和程序源代码,源代码里多数是 WTL 模板类的实例或继承类。一般来说,开发者仅仅需要改变 AppWizard 生产的代码,而那些很少需要改动的“样板”式的代码都被 WTL 模板封装了。
WTL 中有一个管理整个模块(一个 DLL 或 EXE )的类,这个类在 AppWizard 生成的代码中实例化,在自动生成的 WinMain 中被初始化和终结。一个 WTL 程序也可以作为 COM server ,支持可编程的应用程序。 WTL 提供了消息处理机制,支持消息过滤和空闲( on-idle )功能, WM_SETTINGCHANGE 引发的改变通知也可以被截获。
MFC 提供了一个“文档 - 框架 - 视图”结构, WTL 也提供框架(比如一个包括菜单条、工具条和状态条的顶层窗口)和视图,但是根本不支持文档。 MFC 的那套方法往往妨碍高级的开发者,它的文档是基于二进制数据的序列化( serialize ),在当今互联网的世界里,基于 XML/XSL 的文档格式越来越流行,对于弹性化存储机制的需求也越来越多(可能根本就不是存储在本地磁盘上的),文档可能需要运用大量的远程机制,比如 WebDAV , FTP 等,进行存储。 WTL 没有提供任何关于数据或存储格式的功能和机制,程序开发者可以自己编写代码,比如利用高效的 Win32 API WriteFileGather/ReadFileScatter 或 XML 解析器来根据需要做这些工作。
WTL 支持基于对话框的程序,单文档界面( SDI )和多文档界面( MDI )。对于 SDI 它同样支持多线程 SDI ,每个 SDI 窗口一个线程,多数高级的应用程序很有可能用到这种构架(比如,模仿 Word2000 的方法)。 WTL 不支持多线程 MDI 构架,即不支持一个 MID 子窗口一个线程,但这是可以理解的,比如这样可以避免线程和 MDI 父子窗口之间交互的许多问题。
集合了 UI 功能
WTL 提供了一组实现现代的用户界面所必不可少的特性。
WTL 提供了一个框架窗口用于管理一个包含了命令条(增强的菜单条)、工具条的 rebar ,一个状态条,一个或多个视图( views )。视图可以基于一个普通的空窗口 RechEidt , ListView , TreeView 之类的控件。如果使用了多个视图, WTL 的分割功能就派上用场了,视图也支持滚动,状态条可以是一个 pane 或多个 panes 。
WTL 也支持传统的菜单条和工具条,但是它的主菜单表现概念是基于命令条的。一个命令条可以容纳菜单和工具条图标,可以放在一个 rebar 里显示并四处移动。如果一个菜单项目和一个工具条按钮拥有同样的命令 ID 的话,菜单项目旁边会自动显示对应的图标。 WTL 支持可停泊或浮动的命令条, WTL 的命令条和 Internet Explorer 中的很像但和 Word2000 或 Visual Studio 的(更令人向往)不一样, WTL 不支持可以隐藏不常用的项目的菜单(比如 Word2000 的)。动态数据交换的概念允许数据在可见的 UI 控件和 C++ 数据成员之间双向传递,和 MFC 的 DDX 很相近。可以用 ATL 生成对话框,包括那些支持 ActiveX 控件和窗口容器,利用 Visual C++ 的 Resource View 可以用来在对话框资源上布局标准控件、通用控件和 ActiveX 控件,利用 ATL Window Message Handler Wizard 来映射这些控件的消息。
WTL 提供了用来管理属性薄、属性页创建和向导创建的模板创建。
打印机设备场景、打印预览、 devmode 处理和打印作业管理功能可以用来实现文档打印。
使用特殊的设备场景、文件管理器和增强 metafile 信息类可以支持增强的 metafile 。
包装了 windows 控件、系统对话框和 GDI 对象
ATL 提供了对普通窗口的控制但是没有提供对基于不同窗口类的窗口的特殊支持,开发者不得不根据需要手工编写 SnedMessage 调用。对于和 Edit 或 TreeView 的通讯他们不得不使用 ATL 的 CWindow 并且调用 Win32 的 SendMessage 以 EM_LIMITTEXT 或 VM_SETITEM 还得担心消息的参数是否正确( SendMessage 没有类型检查,全部为 WPARAM , LPARAM )。当程序接收到它们时也是“裸数据” - wParam 和 lParam 被送到了消息队列,必须通过代码来转换数据为合适的类型,这时还得保证转换对于每个消息是正确的
一些 ATL 开发者都使用从 ATLCON 例程中提取出的代码,这些代码提供了对 Windows UI 元素的一些封装封装。 WTL 现在以及进化出了一整套的广泛的封装类,这些类实现了对所有标准和通用窗口控件、系统对话框和所有 GDI 对象以及其他的封装。 WTL 中无论是对 edit , button , listbox , treeview , listview 等还是对通用文件对话框、颜色对话框、字体对话框等还是对 DC , pen , brush , region , font 等都有对应的包装类。
另外, WTL 还提供了一整套的 message crackers ,进入窗口的消息被映射到指定的处理函数。使用 ATL 时,消息处理函数收到的是 lParam 和 wParam ,而使用 WTL 的 message cracker ,消息处理函数的参数都是具体消息的具体类型。比如: WM_LBUTTONDOWN 消息有一个 CPoint 类型的参数( CPoint 是 WTL 对 Win32 POINT 结构的包装- WTL 包装了每一个通用的结构)。注意, ATL Windows Message Handler Wizard 使用 ATL 的原始消息映射,非 WTL 的 message crackers , VC++ 下一版可能对向导支持会好一些。
许多的开发者选择 MFC 仅仅是为了使用 CString , WTL 自己也提供了对 CString 的实现,并且是几乎和 MFC 一样的实现。 WTL 的 CString 支持 ASCII , MBCS , UNICODE 和自动化的 BSTR ,支持这些类型间的相互转换,支持字符串连接、截断、和比较,支持 printf 一样的格式化处理,支持弹性的内存管理。
WTL , ATL 和 Win32/64 API 之间的关系
WTL 是基于 ATL 和 Win32 、 64API 的, ATL 是基于 Win32/64 API 的,当谈到它们之间的关系时,我们应该从源代码和二进制两个视角来讨论。
源代码
Win32/64 API 是成千上百的 C 函数的集合,涵盖了相当大的范围,包括我们感兴趣的 COM 和 windowing 。
ATL 是 C++ 模板的集合,几乎就是为 COM 编程量身定做的,但是也包括广泛的底层 windowing 功能的支持。
WTL 是 C++ 模板的集合,它的关注点在高层的 windowing 功能, WTL 不依赖于 COM ,但是可以和 COM 一起使用。只要你不在 WTL 中选择支持“ Com Server ”, CoInitialize 就不会被调用。
WTL 使用 ATL 的 windowing 服务,所以要使用 WTL ,你必须访问 ATL 模板。
ATL 调用 Win32/64 API , WTL 调用 ATL 模板和 Win32/64 API ,你的程序代码调用 WTL , ATL 和 Win32/64 API 。
当你运行了 WTL AppWizard ,他给你生成一些源文件,这些源文件将成为你程序代码的一部分,这些生成的代码调用 WTL ,构建程序框架。
WTL 支持 Windows 2000 , Windows Me , Windows NT4 , Windows 98 , Windows95, OSR 2 和“经典” windows 95 , WTL 并不是只支持它们 “最小公分母”,而是提供 #define (比如 _RICHEDIT_VER, _WIN32_IE, _WIN32_WINNT and WINVER )来决定使用那些 Win32/64 的特性。 WTL 不会自动判别被安装到的操作系统的版本或 IE 的版本(比如,它不使用 LoadLibrary /GetProceAddress 或 GetVersionEx APIs 来判别)。程序开发者必须指定 #define 宏,而且在编译期间已经假定程序在正确版本的客户机上可以正常运行,否则不能。
举个例子,菜单中的“ >> ”符号( v 型符号),当一个命令条因为窗口大小改变而被截短时如果不使用 v 型符号,超出窗口边界的那部分命令条就别直接“剪掉”了。
V 型符号是一个包含两个大于号的标志,当被按下时,就弹出一个菜单菜单上包含由于窗口大小改变而被从命令条尾部截去的那些项目。如果包含了 IE5 , v 型符号就被支持,反之不支持。
在 WTL 程序中,如果 _WIN32_IE 别定义为 0x0500 或更高(比如,在 stdafxh 里)那么 v 型符号在必要时就会显示。
二进制
ATL 和 WTL 是作为一组包含 C++ 模板的头文件的形式发布的。 ATL 中有少数的类可以作为一个独立的 DLL 来使用,但是多数的程序员也把它们的源代码包含到自己的工程里面去,对于 WTL 程序来说,这也是被推荐的。 WTL 没有可以作为独立的 DLL 的东西,所以 WTL 的 C++ 类(并非全部)将被包含进每个程序。当你编译 WTL 程序,你最终会得到一个 EXE 或 DLL ,这就是你唯一需要交付最终用户的程序,不依赖外部库,当然除去操作系统自带的 DLL ,比如 kernel32.dll ,但是这些库基本上都存在(如果不存在, windows 本身也许就无法正常工作了)。一个例外:如果你需要使用浮点数,你不得不使用 C 语言运行库( CRT )。
WTL-ATL , MFC , VB , Java , DHTML 等的抉择
……(省略废话数百字)
为什么选择 WTL ?
WTL 不像 MFC 那样笨重,最终的应用程序也比较小巧。对于高级程序, WTL 给你使用 API 的机会,但是比纯粹的 API 编程节省时间。
Win32 API 可以直接使用,但是有时候它们看起来相当独立,很难决定如何将它们结合起来使用。
WTL 提供了更多的可以完成同样操作的功能。
由于被调用的方法是在编译期而不是运行期决定的,这就是它在效率和代码规模方面占有优势,模板库正在变得越来越流行。
安装 WTL
WTL 的发展很快,它的发行机制也在时常变化。
未来的发行模式
很可能下一版 VC++ 发布时将会整合进 WTL,因此 ,它可能会和 ATL , STL , Data Templates 一起自动安装。
现在的安装机制
当前, WTL 是作为 Microsoft Platform SDK ( January 2000 或更高)的一部分发布的,需要手动分三步安装,未来可能会自动完成。
第一步-取得文件
可以从 MSDN 光盘的第三张或 http://msdn.microsoft.com 得到安装文件。你可以选择全部安装这个 SDK 或仅仅安装包含 Windows Template Library 的部分。(译者注: 你也以在 www.farproc.com下载 WTL7.1安装包 )
注意: WTL7.1 安装的后面步骤与作者原文有出入,所以下面关于安装的就没有安装原文翻译
第二步- WTL Appwizard
安装后打开 WTL 的安装目录(比如 c:/Program Files/Microsoft Platform SDK )进入对应的 AppWizXX 目录,其中 XX 为你的 VC 的版本号,比如你用的是 VC6.0 的话就进入 AppWiz60 ,你会看到一个 setup.js 文件,点击运行它就可以为你自动安装 WTL 的 AppWizard 了。如果你无法运行这个文件或想手工安装,就复制这个目录下的 AtlApp60.awx 到“…… /Microsoft Visual Studio/Common/MSDev98/Template ”目录下也可以的。
然后打开 vc ,在 new 对话框中就可以看到“ ATL/WTL AppWizard ”选项了。
第三步-更新路径
第三步是设置路径以便让编译器找到 WTL 头文件。 WTL 是一个包含 C++ 头文件(没有 .cpp 文件)的模板库,当编译时,编译器需要找到这些文件,这些文件在 WTL 安装目录 /Src/WTL/include 下,你可以在你的源文件里包含这个全路径(不推荐,但也可以),或把这个路径添加到 VC 的“ Include Files ”里,如下图
WTL 安装了什么
WTL 安装后,会有一个或若干个 AppWizXX 目录,这是 WTL AppWizard 文件的所在地;一个 Include 目录为 WTL 的头文件(也就是源文件)所在;还有一个 samples ,一些 WTL 程序的例子。
<待续>
接下篇:http://blog.csdn.net/uoyevoli/archive/2005/05/30/384357.aspx
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=381808
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1542424
<script type="text/javascript">function hide(){showComment();}</script>
<script type="text/javascript">document.write("
");</script>
<script language="javascript" type="text/javascript"> ad_width=468; ad_height=60; adcss=2; unionuser=19; ad_type='j'; count=5; </script> <script type="text/javascript" src="http://tagegg.csdn.net/showads.js" language="javascript"></script> <script src="http://tagegg.csdn.net/b.aspx?action=displayad&unionuser=19&unionurl=http%3A%2F%2Fblog.csdn.net%2Fwangweixing2000%2Farchive%2F2007%2F03%2F27%2F1542424.aspx&adcss=2&ad_type=j&width=468&height=60&ad_color=&ad_color_border=&count=5" language="JavaScript1.1" type="text/javascript"></script> <script type="text/javascript" src="http://blog.csdn.net/js/showgm.js" language="javascript"></script>
<script src="http://www.csdn.net/common/counter.js" type="text/javascript"></script>
width="0" scrolling="no" height="0" frameborder="no" src="http://www.csdn.net/ggmm/dd333.htm" border="0" name="myframe" id="myframe"> <script type="text/javascript">
</script>
<script type="text/javascript">
</script>
<script language="javascript" type="text/javascript">
</script>