-
c语言入门之用C++Builder写COM版的Hello world
前几日用 OICQ 联系上一位快有两年不见的朋友,闲聊中得知他在用 BCB 做 COM ,碰上一些麻烦,我便自告奋勇要教他,刚讲了没几句便被同事拉去吃饭,便和朋友约好发 e-Mail 给他。第二天我便开始做一个 COM 版的 Hello world! ,仗着用 Delphi 写过几个简单的 COM ,以为用 BCB 也差不多,给果碰到不少问题(幸好没有当时教他,不然一定出丑)。弄了半天才成功,于是把那个发给他的 Mail 整理了一下贴到这里来。
开始本来想写个 EXE 的(即 Out of process 的) COM object ,但发现很多 COM 做成 EXE 都有问题,而我又不知道我那朋友熟不熟 DLL (即 In process ),而且 DLL 又不好调试,只好改为 EXE 型的 Automation ,这是最容易的 COM 类型了吧。
开始做 Automation :
1.File|New Application (做 Automation 要有 Form ,即使是个空的也不要拿掉);
2.File|New... 选 ActiveX 页上的 Automation Object;
在对话框中输入 COM 名: AutoTest ,其它就用默认值。
3.在打开的 Type Library Editor (就是那个标题为 Project1.tlb 东东)中,左边的树中的 IAutoTest 上点右键, New 一个 Property ,会产生两个同名的东东,分别用于 Get 和 Set ,取名为 Hello (两个会自动变为一样的),然后在右边找到 Parameters 页,将 Type 改为 BSTR(Set) 和 BSTR *(Get ,注意,列表中的 BSTR 没有*,要自已输入一个)。
4.然后点顶上那个 Refresh Implementation 的按钮(按钮上的小图片是一张纸,里面有两个绿色的箭头成环绕状),这一步很重要,每次修改完 TLB 文件都要点这个按钮再存盘,它将产生相应的代码。
5.在 AutoTestImpl.h 文件中找到如下内容:
// IAutoTest
public:
STDMETHOD(get_Hello(BSTR* Value));
STDMETHOD(set_Hello(BSTR Value));
这是 Refresh Implementation 时自动产生的代码,在后面加上:
private :
WideString FData;
Type Library Editor 产生的 CPP/H 文件除了这个以 Impl (即 Implementation )结尾的以外,还有两个,分别是以 _ATL 和 _TLB 结尾的: _ATL 是自动产生的,通常不用变它,当然如果你有特别的要求并且你对 ATL 又很熟,也可以改改它; _TLB 是由 Type Library Editor 自动维护,无须修改,改了也没用,你的任何修改都会在 Refresh Implementation 时被改回来的。
再看 AutoTestImpl.cpp 文件,找到如下内容:
STDMETHODIMP TAutoTestImpl::get_Hello(BSTR* Value)
{
try
{
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IAutoTest);
}
return S_OK;
};
这也是自动产生的东东,在这个 try 中输入:
try
{
*Value = FData; // 加在这里
}
在 Set 的 Try 中输入:
FData = Value;
注意一定要用 try..catch 括起来,否则..。 Delphi 就不用,这没办法,因为 BCB 是用 ATL 的嘛,而 Delphi 是用 Borland 自已搞的 DAX(Delphi ActiveX Extension) , BCB 就是在这点上和 Delphi 有很大不同。
6.Save All ,编译。
7.在命令行下运行:
Project1 /regserver
注册这个 COM ,注销则用:
Project1 /unregserver
记得删除 COM 之前一定要先注销,不然你只好到注册表里慢慢找了。
使用 Automation (前期联编用法):
1.File|New Application
2.在 Project2 中加入 Project1_TLB.CPP
3.在 Unit2.h 中加入:
#include "Project1_TLB.h"
和:
private: // User declarations
TCOMIAutoTest MyTest; // 加入的
4.在 Form 上放一个 Label 和一个 Button 。双击BUTTON,在事件响应中输入:
try {
if ( !MyTest )
{
MyTest = CoAutoTest::Create( );
MyTest.Hello = WideString( "Hello world!" );
}
Label1->Caption = MyTest.Hello;
}
catch ( EOleSysError &e )
{
ShowMessage( e.Message );
}
5.Save All ,编译。
6.运行后,点 Button ,你会看到 Project1 也运行起来,同时 Label1 显示 "Hello world!" 。
当 Project2 退出时, Project1 也自动退出。会了吧。
另一种使用 Automation 的方法(后期联编用法):
1.File|New Application
2.在Unit3.cpp中加入:
#include <vcl/ComObj.hpp>
3.在 Form 上放一个 Label 和一个 Button 。双击BUTTON,在事件响应中输入:
Variant v = CreateOleObject( "Project1.AutoTest" );
v.Exec( PropertySet( "Hello" ) << "Hello world!" );
Label1->Caption = v.Exec( PropertyGet( "Hello" ) );
4.Save All ,编译。
5.运行后,点 Button ,你会看到 Project1 也运行起来,同时 Label1 显示 "Hello world!" ,然后 Project1 就退出了。
这就是COM,有意思吧。用 BCB+ATL 写 COM 就是这么简单。
栏目列表
最新更新
C#基于接口设计三层架构Unity篇
C#线程 入门
C#读取静态类常量属性和值
C# 插件式编程
C# 委托与事件有啥区别?
C#队列学习笔记:队列(Queue)和堆栈(Stack
linq 多表分组左连接查询查询统计
C#队列学习笔记:MSMQ入门一
C# 基础知识系列- 1 数据类型
二、C#入门—基础语法
C# 在Word中添加Latex 数学公式和符号
inncheck命令 – 检查语法
基于UDP的服务器端和客户端
再谈UDP和TCP
在socket编程中使用域名
网络数据传输时的大小端问题
socket编程实现文件传输功能
如何优雅地断开TCP连接?
图解TCP四次握手断开连接
详细分析TCP数据的传输过程
SqlServer 利用游标批量更新数据
BOS只读状态修改
SQL Server等待事件—PAGEIOLATCH_EX
数据库多行转换为单一列
获取数据表最后最后访问,修改,更新,
计算经历的时间
SQL查询结果自定义排序
修改数据库默认位置
日期简单加或减
从日期获取年,月或日