VC调用OCX COM组件

纯C/C++中调用OCX的方法

首先,接口就是vTable

 

#import "c:/ITDetector.ocx" \

no_namespace no_smart_pointers raw_interfaces_only \

raw_native_types no_implementation named_guids

加入这句第一次Build之后会生成ITDetector.tlh在你的Debug或者Release目录下,把ITDetector.tlh Include进来你就可以使用ITDetector.ocx中包含的接口了。

 

ITDetector.ocx会包含tlb的资源,.tlb文件中是保存了接口的名字、规范及其他信息等(也就是idl文件的描述信息)。#import这句会用工具读取ITDetector.ocx中的tlb资源,然后翻译成C++的接口版本生成到ITDetector.tlh文件,事实上就是接口定义而已,因为你需要调用某个方法只需要知道类GUID、接口GUID、接口方法的偏移、接口方法的参数及返回值类型就可以了。

 

1、import你的OCX库 //想办法弄到接口的定义,如果你有或者自己写可以跳过该步

2、CoInitialize(0) //初始化COM库,干些什么事我不太清楚,反正就是告诉系统你的这个线程要开始用COM组件了(有计数器)

3、CoCreateInstance取得一个实例 

//获得一个COM实例,实际工作是根据CLSID去注册表找到模块路径(就是c:/ITDetector.ocx)

//然后LoadLibrary,把c:/ITDetector.ocx装入进程

//再用GetProcAddress获取DllGetClassObject的方法地址

//再调用DllGetClassObject,把CLSID传进去,它会返回这个类的工厂接口(组件需要自己写代码实现工厂)

//再调用工厂接口的CreateInstance把对象创建起来,并返回这个接口,同时调用一次AddRef

4、调用 //虚方法调用而已

5、Release() //减少引用计数,当引用计数为0是,对象被释放(组件需要自己实现)

6、CoUninitialize() //告诉系统,你这个线程不再使用COM组件了(有计数器)

 

int CWebServiceBridge_PayWebS::DisplayOCX(char* szUrlPath)
{
	HRESULT   hr   =   NULL;  
	IDispatch*   pIDispatch   =   NULL;  
	wchar_t   progid[]   =   L"WRITINGPAD.WritingPadCtrl.1";   //组件名  
	CLSID   clsid;    
	hr   =   ::CLSIDFromProgID(progid,&clsid);    //根据组件ID获取clsid
	hr   =   ::CoInitialize(NULL);
	_DWritingPad *pID;		//接口指针,可以在tlh头文件中获取
	hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,__uuidof(_DWritingPad),(LPVOID *)&pID); // 根据Clsid和IID创建相应的实例对象。
	if(SUCCEEDED(hr)) 
	{
		DISPID dispid;
		OLECHAR FAR* szMember = L"OpenURL";   //Add为OCX中的被调函数,函数原型为:OpenURL("http://www.bing.com")
		hr = pID->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
		DISPPARAMS param;
		memset(&param, 0, sizeof(param));
		param.cArgs = 1;		//参数个数
		VARIANTARG* pArg = new VARIANTARG[param.cArgs];
		param.rgvarg = pArg;
	    memset(pArg, 0, sizeof(VARIANT) * param.cArgs);			
		_bstr_t bstrUrlPath = _bstr_t(szUrlPath);
		param.rgvarg[0].vt = VT_BSTR;
		param.rgvarg[0].bstrVal = bstrUrlPath;
		VARIANT result;
		VariantInit(&result);
		EXCEPINFO exInfo;
		memset(&exInfo, 0, sizeof(exInfo));
		UINT argE = -1;
		hr = pID->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &param, &result, 0, NULL);//返回值在result中保存
		pID->Release();
		if(SUCCEEDED(hr))
		{
			CoUninitialize();
			return result.lVal;
		}
	}
	CoUninitialize();
	return -1;
}

WIN7系统VC6中添加OCX出现“不支持此接口” 问题的解决方法

在WindowsXP系统中,VC6可以通过  工程-》添加到工程-》。。。。。。添加OCX,

但是到了Windows7系统中,无法添加,就算用Administrator,也只是仅仅可以看到OCX,但是添加

的时候提示 “不支持此接口”;

还有人说 可以尝试重新注册所有DLL来解决此问题:

for /r C:/ %i in (*.dll) do regsvr32.exe /s "%i"  或 FOR /R C:/ %G IN (*.dll) DO "%systemroot%/system32/regsvr32.exe" /s "%G"  但是一样的问题。

解决方法:1:在对话框上直接右键 “Insert ActiveX Control。。。”, 这个时候类视图中还没有所添加OCX的类文件,

2:然后选中所添加的OCX,用向导添加变量,这样VC6会为程序添加这个OCX对应的类文件了;

3: 删除刚添加的OCX关联的变量也没问题了;

在XP系统VC6中,如果ocx添加新的接口了,重新导入ocx就可以了;

但是在win7系统VC6中,目前我只好,重新注册号添加接口的ocx,然后新建一个工程导入,然后将生成的.h 和 .cpp 复制到原工程中;

 

参考

  1. How to Call COM Object from Visual Studio C++?

  2. IDispatch接口- GetIDsOfNames和Invoke - zj510的专栏- CSDN博客

  3. DLL中加载OCX - 程序园

  4. com.cpp