First, the preface
Finally wrote the tenth time, I have been looking forward to writing this back content Yes, why? Because automation (automation) is a very common, very useful, very exciting one of the COM features. As WORD, EXCEL and other OFFICE software provides a "macro" function, even we use the VC development environment also provides the "macro" function, more because of HTML, ASP, JSP, etc. to rely on scripting (script) support, but also reflects the importance of automation interface.
If you use the vc6.0 development environment, please read the previous one.
If you use Vc.net 2003, please continue ...
Second, IDispatch interface
If it is a compiled language, then we can have the compiler load the type library at compile time, which is the description of the loading interface. In the seventh article, we used the #include method and #import method respectively to achieve. Once the type library is loaded, the compiler knows how to compile the call to the interface function---this is called "forward binding." However, if you want to use components in a scripting language, the problem is large, because the scripting language is interpreted to execute, it does not know the specific function address, how to do? The Automation interface was born---"post-binding."
The automation component is actually the component that implements the IDispatch interface. The IDispatch interface has 4 functions that interpret the language's executor to perform the functions provided by the component through the only 4 functions. The IDispatch interface is described in IDL form as follows: (note 1)
[
Object
UUID (00020400-0000-0000-c000-000000000046),//IDispatch Interface IID = IID_IDispatch
Pointer_default (Unique)
]
Interface Idispatch:iunknown
{
typedef [UNIQUE] IDispatch * LPDISPATCH; Convert IDispatch * to Lpdispatch
HRESULT GetTypeInfoCount ([out] UINT * pctinfo); We'll talk about the two functions of the type library.
HRESULT GetTypeInfo ([in] UINT Itinfo,[in] LCID lcid,[out] ITypeInfo * * pptinfo);
HRESULT GetIDsOfNames (///By function name, get function sequence number (DISPID)
[In] REFIID riid,
[In, Size_is (cnames)] LPOLESTR * Rgsznames,
[In] UINT CNAMEs,
[In] LCID LCID,
[Out, Size_is (cnames)] DISPID * Rgdispid
);
[Local]/native version function
HRESULT Invoke (////function by function
[In] DISPID Dispidmember,
[In] REFIID riid,
[In] LCID LCID,
[In] WORD wflags,
[In, out] Dispparams * pDispParams,
[out] VARIANT * Pvarresult,
[out] Excepinfo * Pexcepinfo,
[out] UINT * Puargerr
);
[Call_as (Invoke)]//Remote version function
HRESULT Remoteinvoke (
[In] DISPID Dispidmember,
[In] REFIID riid,
[In] LCID LCID,
[In] DWORD dwflags,
[In] Dispparams * pDispParams,
[out] VARIANT * Pvarresult,
[out] Excepinfo * Pexcepinfo,
[out] UINT * Pargerr,
[In] UINT Cvarref,
[In, Size_is (CVARREF)] UINT * Rgvarrefidx,
[In, Out, size_is (CVARREF)] VARIANTARG * Rgvarref
);
}
The above IDispatch interface function's explanation, we leave to carry on the introduction in the back. How do I implement these functions in a component program? Okay, okay, just like IUnknown, MFC and ATL have all done for us. We'll focus on the compilation of the components, and the next time we'll introduce the method of calling the components.