描述:
正在COM入门,试验中遇到难题--
我用Visual FoxPro9.0将一个项目Project1中的类TEST(类中只有一个自定义方法opentable)编译成一个COM,生成的COM部件名是Project1.TEST,并且在Visual FoxPro9.0中测试,调用类TEST的方法opentable运行正确。
但是,用VC编写的客户程序里不知该怎么创建这个COM对象,好像需要调用API:
WINOLEAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv);
其中有一项参数‘REFIID riid’应该是‘方法opentable’所对应的接口IID吧,那么,如何得到呢?尝试了下面的途径:
首先通过注册表查找:打开注册表,只看到Project1.TEST的接口CLSID,却没有标出其中的‘方法opentable’的接口IID;
然后用VC6的OLE/COM Object View查看:打开VC6的OLE/COM Object View,找到COM部件Project1.TEST,双击打开,内容如下
// Generated .IDL file (by the OLE/COM Object Viewer)
// typelib filename: Project1.dll
[uuid(3472BE1C-760A-4309-B3E6-A64503420B27),
version(1.0),
helpstring("\xFFFFFFCF\xFFFFFFEE目1 Type Libra")]
library \xFFFFFFCF\xFFFFFFEE?
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface Itest;
[odl,
uuid(B39D2C1A-B151-45E5-89C8-82BF55E7869B),
helpstring("Project1.test"),
hidden,
dual,
nonextensible,
oleautomation ]
interface Itest : IDispatch {
[id(00000000), propget, helpstring("指定用户自定义类库的文件名,该类库包含对象的类。")]
HRESULT ClassLibrary([out, retval] BSTR* ClassLibrary);
[id(0x00000001)]
HRESULT opentable([out, retval] VARIANT* RetVal);
[id(0x00000002), propget, helpstring("指定在代码中用以引用对象的名称。")]
HRESULT Name([out, retval] BSTR* Name);
[id(0x00000002), propput, helpstring("指定在代码中用以引用对象的名称。")]
HRESULT Name([in] BSTR Name);
······//有很多类似的,在这里我就省略了。
HRESULT SetAll(
BSTR cProperty,
VARIANT Value,
BSTR cClass,
[out, retval] VARIANT* RetVal); };
[uuid(5CB425B4-DD80-4750-AE5E-D757EAF56947),
helpstring("Project1.test") ]
coclass test {
[default] interface Itest; };};
我想,其中有一句‘opentable([out, retval] VARIANT* RetVal);[id(0x00000002)’中的id(0x00000002)是不是‘方法opentable’的接口IID呢?怎么用呢?我试着将它加上Project1.TEST的接口CLSID作为‘方法opentable’的接口IID放到CoCreateInstance调用,程序如下
#include "windows.h"
#include <stdio.h>
#include <comutil.h>
void main()
{
CoInitialize(NULL);
static const GUID TESTclsid={0x3472be1c,0x760a,0x4309,
{0xb3,0xe6,0xa6,0x45,0x03,0x42,0x0b,0x27}};
//Project1.TEST的接口CLSID
static const GUID TESTopeniid={0x3472be1e,0x760a,0x4309,
{0xb3,0xe6,0xa6,0x45,0x03,0x42,0x0b,0x27}};
//我是用那个id(0x00000002)加上上面的Project1.TEST的接口CLSID,得到TESTopeniid,作为Project1.TEST的‘方法opentable’的接口IID,不知对不?
IUnknown *pUnknown;
CoCreateInstance(TESTclsid, NULL, CLSCTX_INPROC_SERVER,TESTopeniid, (void **)&pUnknown);
printf("%s",pUnknown->opentable );
}
结果有错误提示 error C2039: 'opentable' : is not a member of 'IUnknown'
由于时间较紧张,COM方面的学习只想面向应用,即主要着重于掌握如何在客户程序中创建和使用COM对象,而不是掌握如何开发一个COM组件,很多COM的书都是大篇幅介绍如何开发COM组件,而对创建和使用COM对象的叙述显得有些散乱,特别是VC++中创建和使用COM对象很复杂,要求客户程序中首先#include接口类定义文件,可是Visual FoxPro9.0生成COM部件时只生成了两个文件,一个是Project1.dll,一个是Project1.tlb,哪里有什么接口类定义文件哟,没有接口类定义文件,VC中好像就无法创建COM对象了,
不像VB、VFP那样创建一个COM对象只需一句CREATEOBJECT就搞掂了,所以希望大家在这一方面给予热心指点,非常感谢!
解决方案1:
CLSID是Class ID,就是表示一个COM对象
IID是Interface ID,表示一个COM接口
因此可以某一个CLSID1的对象实现了IID1,CLSID2也实现了IID1
也可以CLSID1实现了IID1,同时也实现了IID2
所以CLSID跟IID没什么关系,体现其关系的仅仅是利用CLSID调用了CoCreateInstance拿到IUnkown接口后,QueryInterface一次就知道它有没有实现IID了没有。
用COM其实很简单的:
Class Wizard->Add Class->From a type library
它就会生成相应的包装类,你直接用就可以了
B39D2C1A-B151-45E5-89C8-82BF55E7869B应该是接口ID。5CB425B4-DD80-4750-AE5E-D757EAF56947是你的clsid,good luck.有些知识还是需要补充的。即使你解决了这个问题。
解决方案3: 1.使用__uuidof(expression),这个宏可以根据导入的类型库,组件,接口的类型,来获得它们的uuid。
导入语句:#import "msxml4.dll"
2.如果你的组件没有实现IDisptach接口:
可以使用
CoCreateInstance得查询接口,然后使用QueryInterface接口查询当前组件的其它。
3.如果你的组件实现了IDispatch接口,可以这么来使用接口:
OleInitialize(NULL); //这个必须的,这样一来,当前的线程只能套间,而不是自由线程。
IDispatch* pIDispatch=NULL;
CLSID clsID;
//将组件的ProgID转化成它的CLSID
HRESULT hr=CLSIDFromProgID(_T("Aggregate221.CA"),&clsID);
您可能想查找下面的文章:
- IWebBrowser2::Navigate的问题
- IWebBrowser2::Navigate的问题
- 请教IWebBrowser2问题~~~~~~~~~在线等
- 如何用IWebBrowser2判断当前窗口是否处于激活状态?
- #import"wmpdll",在wmplib空间找不到对“IID_IWMPPlayer”的定义,怎么办?
- 列集IPicture接口的问题,UP的也有分数
- 通过IWebBrowser2能获得IE中已经载入的其他插件的接口么?
- 根据IID值怎样能实例化一个接口?(不通过QueryInterface来实现)
- 如何在TLB中添加相关的IID_xxxx?
- 给定一个url,如何用IWebBrowser2接口获得该url的源码?