随笔 - 2, 文章 - 0, 评论 - 2, 引用 - 0
数据加载中……

2006年7月28日

C++进行COM 自动化调用时的命名参数调用方法

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);
        

posted @ 2006-07-28 09:58 菠萝蜜多 阅读(1376) | 评论 (2)编辑 收藏

2006年7月11日

解决在TabControl中加入带有DS_CONTROL属性的对话框子窗体后应用程序挂起的问题

DS_CONTROL属性保证当使用TAB键在窗体中切换输入焦点时,如果遇到子窗体,则自动切换到子窗体的控件。
当在TabControl中加入了带有DS_CONTROL属性的子窗体时,如果将焦点切换到子窗体,会出现应用程序挂起的问题。
主要原因在于DS_CONTROL需要与WS_EX_CONTROLPARENT同时使用,而TabControl默认没有设置WS_EX_CONTROLPARENT。
此时需要使用SetWindowLongPtr(GWL_EXSTYLE, dwExStyle)设置TabControl的WS_EX_CONTROLPARENT属性。

posted @ 2006-07-11 15:32 菠萝蜜多 阅读(1707) | 评论 (0)编辑 收藏