话说回来,vb易用的一个主要领域是,对COM组件的调用。用vb调用COM组件的属性和方法,就像调用本地的一样,代码书写很自然。因为vb不仅支持一般的接口方法调用,还支持通过IDispatch接口进行自动化调用。
vc++针对COM组件编程,提供了两组类库:(_com_ptr_t,_variant_t,_bstr_t)和(CComPtr,CComVariant,CComBSTR),使用起来也很方便。但对IDispatch接口没有提供直接的支持,进行调用就非常繁琐了。
IDispatch接口是自动化领域最重要的接口。IDispatchEx接口是对IDispatch接口的扩展,是javascript等动态语言内部实现的基础。如果我们要在VC++中访问javascript中的对象,如果我们要进而对AJAX库进行二进制封装,就必须有一个简单易用的辅助类库作支撑。当然,如果要给PIMShell开发plugin,vb般的VC++开发也是最常用的编程范式。
总之,一个编程语言既要强大、灵活,又要简单易用,不仅需要编译器本身的支持,还需要辅助库的支持。接下来的文章,我们就通过一系列的设计,来实现vb般的vc++开发。
例如:网页中的javascript有一个函数Test,我们通过调用Test来对比不同语言不同范式的区别。(Test可通过window对象访问,具体细节我们以后再讨论。)
javascript
function Test(sMessage) { alert(sMessage); } //执行 window.Test("Hello World!");
vb(不是vbscript)
dim oMethod as Object Set oMethod=window.Test oMethod("Hello World!")
vb般的vc++
IDispatchPtr pMethod=CVB::get(window,L"Test"); CVB::Invoke1(pMethod,NULL,L"Hellow World!");
一般的vc++,(代码已简化,未检测必要的异常)
//get DISPID of "Test" DISPID dispID; LPCTSTR szName=L"Test"; window->GetIDsOfNames( IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID); //get property of "Test" _variant_t vResult; DISPPARAMS dp = { NULL, NULL, 0, 0 }; window->Invoke( dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, &vResult, NULL, NULL); //ready IDispatchPtr pMethod=vResult; //invoke "Test" _variant_t vParam=L"Hello World!"; dp.cArgs=1; dp.rgvarg=&vParam; pMethod->Invoke( NULL, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dp, NULL, NULL, NULL);