n 编写Visual C++组件
确定创建服务器组件的最有效的工具
当你着手创建COM组件时,你可以选择与Visual Basic、Delphi、MFC和ATL不同的工具。让我们比较一下每个工具,来揭露它们各自的优点和缺点。
当着手写COM类时,你可以有几种选择,你可以选择用C++满足COM。这种选择提供了最大的灵活性但是很枯燥。另外,你可以选择Visual C++提供的两种主要的框架来写COM:MFC和ATL。
MFC使用文档视图体系结构设计良好的开发基于Windows的应用程序。使用MFC设计基于Windows应用程序要求运行时间库MFC42.DLL来执行。当用于开发确定类型的应用程序时,MFC遇到要求大的运行时间库开销。MFC有利于像基于Windows的单层应用程序、请求许多GUI客户端的应用程序、ActiveX控件和OLE文档的开发。对COM的支持是后来增加的并且依靠它的文档视图体系结构。虽然Visual C++向导使得用MFC创建组件容易很多,但于框架结构先天设计缺陷,所以它并不是一种灵活的方法。而且,组件以体积大和要求扩展DLL而告终。
相反,ATL是针对COM来设计的。此外,ATL提供像聚合和包容不同的类合成技术的完全支持。ATL使用C++模板类的多继承技术来实现COM类。ATL允许COM组件、自动化服务器和ActiveX控件的创建。使用ATL创建的COM更小更快。ATL提供许多COM接口的本地支持和由Windows NT服务器支持的新线程模型。由于ATL主要使用模板的概念,创建的组件大小很小,并且运行期DLL很小并可动态加载。
所以,你应用ATL创建COM。
组件功能:同上(编写Visual Basic组件)。
组件将包含以下函数:ValidateCreditCard、PrefixCheck、LengthCheck、LuhnCheck。仅ValidateCreditCard可以被应用程序调用来封装组件的工作方式。
为了创建验证信用卡的服务器组件,你需要执行以下步骤:
1. 创建应用程序框架
启动VC++6.0,从File菜单选项选中 New 菜单项,在出现的 New 对话框中选中 Projects 卡片,从显示的工程类型中选中 ATL COM AppWizard。指定工程工作空间名,即在 Project Name 编辑框中输入项目名ValidateCreditCardServer,以区别于Visual Basic组件工程ValidateCardServer。选择合适的 Location 后,按确认按钮进入下一个对话框:ATL COM Appwizard - step 1 of 1,在 Server Type 中选择 Dynamic Link Library [ DLL ],即进程内服务器组件。选中 Support MFC 选项。在按下 Finish 和 Ok 按钮后,一个组件的框架已经建立。现在让我们来看一下生成的文件的清单
n stdafx.h
n stdafx.cpp
n ValidateCreditCardServer.idl
n ValidateCreditCardServer.rc
n Resource.h
n ValidateCreditCardServer.def
n ValidateCreditCardServerps.def
n ValidateCreditCardServer.h
n ValidateCreditCardServer.cpp
n ValidateCreditCardServer.dsp
n ValidateCreditCardServer.dsw
n ValidateCreditCardServer.ncb
n ValidateCreditCardServerps.mk
n ValidateCreditCardServer.clw
ValidateCreditCardServer.cpp清单
// ValidateCreditCardServer.cpp : Implementation of DLL Exports.
// Note: Proxy/Stub Information
// To build a separate proxy/stub DLL,
// run nmake -f ValidateCreditCardServerps.mk in the project directory.
#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "ValidateCreditCardServer.h"
#include "ValidateCreditCardServer_i.c"
#include "ValidateCard.h"
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_ValidateCard, CValidateCard)
END_OBJECT_MAP()
class CValidateCreditCardServerApp : public CWinApp
{
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CValidateCreditCardServerApp)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
//{{AFX_MSG(CValidateCreditCardServerApp)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CValidateCreditCardServerApp, CWinApp)
//{{AFX_MSG_MAP(CValidateCreditCardServerApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CValidateCreditCardServerApp theApp;
BOOL CValidateCreditCardServerApp::InitInstance()
{
_Module.Init(ObjectMap, m_hInstance, &LIBID_VALIDATECREDITCARDSERVERLib);
return CWinApp::InitInstance();
}
int CValidateCreditCardServerApp::ExitInstance()
{
_Module.Term();
return CWinApp::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return (AfxDllCanUnloadNow()==S_OK && _Module.GetLockCount()==0) ? S_OK : S_FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
return _Module.GetClassObject(rclsid, riid, ppv);
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
return _Module.UnregisterServer(TRUE);
}
2. 创建框架中的组件
从Insert菜单中选中 New ATL Object…菜单项,出现 ATL Object Wizard 对话框。
在ATL Object Wizard中,在左边的 Category 中选择 Objects,右边的 Objects 中选中 Simple Object 项。按 Next 按钮。
在出现的 ATL Object Wizard 属性对话框中 Names 卡片中的八个编辑框中左上方的 Short Name 编辑框中输入短名ValidateCard ,其他七个编辑框的内容会自动生成。在这里我们也对这一对话框的其他七个编辑框的内容作一个详细地剖析:
C++块
Short Name:ValidateCard//用户输入
Class:CValidateCard//产生组件类的实现类的类名
.H File:ValidateCard.h//产生组件类的实现类的头文件
.CPP File:ValidateCard.cpp//产生组件类的实现类的实现文件
COM块
CoClass:ValidateCard//产生的组件类,区别于组件类的实现类
Interface:IValidateCard//创建组件类时,同时创建一个此组件类的一个用户接口
Type:ValidateCard Class//组件类的类型
ProgID:ValidateCreditCardServer.ValidateCard// CLSIDFromProgID调用,用它得到CLSID
然后按确认按钮退出。这将生成如上的信息并且在需要的文件中同样地作一个登陆,特别是IDL文件。在这里我们比较一下创建组件前后的两个版本的IDL文件。
创建组件前的ValidateCreditCardServer.idl文件,即创建应用程序框架后的IDL文件。
// ValidateCreditCardServer.idl : IDL source for ValidateCreditCardServer.dll
//
// This file will be processed by the MIDL tool to
// produce the type library (ValidateCreditCardServer.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
uuid(B3404054-C33E-4931-B737-5783CEEFECDB),
version(1.0),
helpstring("ValidateCreditCardServer 1.0 Type Library")
]
library VALIDATECREDITCARDSERVERLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
};
(篇幅所限,未完,待续)