|
2006年7月28日
C++使用COM自动化组件时,通过获取IDispatch接口,然后通过Invoke方法对COM组件的方法进行调用。在对Office组件的编程中,我们会经常性的使用这一方法。 在VBA中,存在一种命名参数的调用法。如Word的Documents对象中的Open方法:
Documents.Open(FileName, ConfirmConversions, ReadOnly, AddToRecentFiles, PasswordDocument, PasswordTemplate, Revert, WritePasswordDocument, WritePasswordTemplate, Format, Encoding, Visible, OpenConflictDocument, OpenAndRepair, DocumentDirection, NoEncodingDialog)
其中只有FileName参数为必须的参数,其他参数都为可选的参数。在进行调用时,VBA中可通过指定可选参数名称来向Documents传输任意的可选参数,如下
'
以只读方式打开文档 MyDoc.doc。
Sub
OpenDoc() Documents.Open FileName:
=
"
C:\MyFiles\MyDoc.doc
"
,
ReadOnly
:
=
True
End Sub
那么,在C++中,我们应该如何进行这种调用?先看看Invoke方法的声明
HRESULT Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR
*
pDispParams,
VARIANT FAR
*
pVarResult,
EXCEPINFO FAR
*
pExcepInfo,
unsigned
int
FAR
*
puArgErr
);
其中的pDispParams用于方法的参数传递,声明如下
typedef
struct
FARSTRUCT tagDISPPARAMS{
VARIANTARG FAR
*
rgvarg;
//
Array of arguments.
DISPID FAR
*
rgdispidNamedArgs;
//
Dispatch IDs of named arguments.
unsigned
int
cArgs;
//
Number of arguments.
unsigned
int
cNamedArgs;
//
Number of named arguments.
} DISPPARAMS;
通过rgdispidNamedArgs可指定传入的命名参数,因此可以将上述VBA代码转化为下面的C++代码(这里使用了ATL),实现命名参数的调用
CComPtr<Word::Documents> qpDocuments; m_qpApplication->get_Documents(&qpDocuments); CComDispatchDriver qpDocsDisp = qpDocuments; CComVariant varFilename(L"C:\MyFiles\MyDoc.doc"); CComVariant varTrue(true); CComVariant varDisp; DISPID dispids[3]; LPOLESTR names[] = {L"Open", L"FileName", L"ReadOnly"}; hr = qpDocsDisp->GetIDsOfNames(IID_NULL, names, 3, LOCALE_USER_DEFAULT, dispids); DISPPARAMS dispParams; dispParams.cArgs = 2; dispParams.cNamedArgs = 2; dispParams.rgdispidNamedArgs = &dispids[1]; VARIANT varParam[2]; ::VariantInit(&varParam[0]); ::VariantInit(&varParam[1]); varParam[0] = varFilename; varParam[1] = varTrue; dispParams.rgvarg = varParam; hr = qpDocsDisp->Invoke(dispids[0], IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispParams, &varDisp, NULL, NULL);
2006年7月11日
DS_CONTROL属性保证当使用TAB键在窗体中切换输入焦点时,如果遇到子窗体,则自动切换到子窗体的控件。 当在TabControl中加入了带有DS_CONTROL属性的子窗体时,如果将焦点切换到子窗体,会出现应用程序挂起的问题。 主要原因在于DS_CONTROL需要与WS_EX_CONTROLPARENT同时使用,而TabControl默认没有设置WS_EX_CONTROLPARENT。 此时需要使用SetWindowLongPtr(GWL_EXSTYLE, dwExStyle)设置TabControl的WS_EX_CONTROLPARENT属性。
|