这段代码是msdn例子,我也看过,但我还是不明白,同样是调用COM,
为什么不用你在 
http://www.csdn.net/expert/topic/624/624448.xml?temp=4.009426E-03发那种方法呢

解决方案 »

  1.   

    If you have used the VC++ ClassWizard to import a class from a type library, you will be familiar with the COleDispatchDriver class. This class is typically used as the base class of machine generated wrapper classes for COM objects. Actually, I have never seen it being used for anything else except as the base of wrapper classes (until now, of course). Why do I bother to write an article about COleDispatchDriver? The reason is that I think this class has some unreleased power that will make a C++ developer's life a lot easier. 
    Have you noticed that VB developers can create almost any COM object and call its methods at run-time, and VC++ developers have to use compile-time generated wrapper classes? Anyone understands COM will say that we can do the same thing in C++, but we don't want to bother with writing so much low-level com code to accomplish this. My goal is to derive a utility class from COleDispatchDriver so that we can write code like the following in VC++ without generating any wrapper class at compile-time: // declare a utility object
    MyUtilityClass utility;
    // create a com object with prog id "MyComObj1"
    utility.CreateObject("MyComObj1");
    // call the method "GetData" (no argument) in the com object
    CString strData = utility.CallMethod("GetData");
    // create another com object with prog id "MyComObj2"
    utility.CreateObject("MyComOb2");
    // call the method "GetMsgCount" with one argument
    long nUserID = 3;
    long nCount = utitilty.CallMethod("GetMsgCount", nUserID);
    As you can see later, I came pretty close to achieving this goal. If someone flames me for damaging a developer's brain with VB-style code, then my job is done :-). Please note that this is not meant to replace other existing methods of creating and using a com object. I would like to thank Chris Losinger and Aaron Schaefer for answering my "anonymous" programming questions. XYDispDriver
    XYDispDriver is the name of my utility class. The source code project will build a library XYDispDriver.dll which exports the XYDispDriver class. As usual, you may use and modify the source code anyway you wish, I would appreciate some acknowledgment for my contribution (if possible). Here is the header file of my class. #include <afxdisp.h>class XYDispDriver: public COleDispatchDriver
    {
        // an internal array to store type information
        CPtrArray m_arrayDispInfo;
        // an internal function to get index to stored type information
        int FindDispInfo(const CString strName, const WORD wFlag = DISPATCH_METHOD);
        // clear internal storage
        void Clear();
        // these 3 functions are here to hide functions with the same names in the base class
        BOOL CreateDispatch(REFCLSID clsid, COleException* pError = NULL) { return FALSE; }
        void AttachDispatch(LPDISPATCH lpDispatch, BOOL bAutoRelease = TRUE ) {}
        LPDISPATCH DetachDispatch( ) { return NULL; }
    public:
        XYDispDriver();
        ~XYDispDriver();
        // create a com object with given prog id, this function
        // hide the function with the same name in the base class
        BOOL CreateDispatch(LPCTSTR lpszProgID);
        // get the type of a property
        VARTYPE GetPropertyType(const CString strPropertyName);
        // get the property value
        void* GetProperty(const CString strPropertyName);
        // set the property value
        void SetProperty(const CString strPropertyName, ...);
        // get return type of a method
        VARTYPE GetReturnType(const CString strMethodName);
        // get number of parameters in a method
        int GetParamCount(const CString strMethodName);
        // get the type of a parameter in a method
        VARTYPE GetParamType(const CString strMethodName, const int nParamIndex);
        // invoke a method
        void* InvokeMethod(const CString strMethodName, ...);
    };
    To use the XYDispDriver class, you first need to declare an instance of this class and call the CreateDispatch member function passing the prog id of a com object. This method not only creates an IDispatch pointer, it also retrieves and stores all the necessary type information using the ITypeInfo interface. Then you can call other member functions to either invoke a method in the com object or get/set a property value. Please note that GetProperty and InvokeMethod both return a void pointer. To access the return data, you need to cast the pointer to the appropriate data type and then dereference it. Also, the return data will be over-ridden by the next call to the same method. I know this is cumbersome and un-OO like, but who said the world is perfect? :-) Please also note that methods of XYDispDriver may throw exceptions of type COleException, an MFC class. Sample code
    Here is a sample program that creates an XYMailClient object described in my other article and sends/receives e-mail messages. The code can be written and executed without using any type library at compile-time. /*************** Test.cpp ***********************/#include "XYDispDriver.h"void main()
    {
        XYDispDriver disp;
        try
        {
           if(disp.CreateDispatch("XYMailClient.1"))
            {
               if(*(BOOL*)disp.InvokeMethod("InitSession","MyProfile","")==FALSE)
                {
                    printf("Failed to call InitSession\n");
                    return;
                }
               if(!*(BOOL*)disp.InvokeMethod("SendMsg","[email protected]",
                                             "","","Hello","This is a test",""))
                {
                    printf("Failed to call SendMsg\n");
                }
               long nCount = *(long*)disp.InvokeMethod("FetchMsg");
                printf("Total messages = %d\n",nCount);
               for(int i=0;i<nCount;i++)
                {
                    printf("Message %d: %s\n",i,*(CString*)disp.InvokeMethod("GetMsg",i));
                }
                disp.InvokeMethod("DeleteMsg",0);
                disp.InvokeMethod("EndSession");
            }
           else
            {
                printf("Failed to create com obj\n");
            }
        }
        catch(COleException* e)
        {
            printf("Ole exception\n");
           TCHAR buf[251];
            e->GetErrorMessage(buf,250);
            printf("%s\n",buf);
            e->Delete();
        }
        printf("Done\n");
    }
    /**************** End of Test.cpp ****************/
     
    Using XYDispDriver in your own program
    XYDispDriver is implemented with VC++ 5.0 and MFC. 
    To use XYDispDriver, you need only to add the source files to your project or use it as a dll. You should always use the CString class for string data, although you can pass literal strings as input parameters. I have not done extensive testing with various data types except for strings and numbers. Please let me know if you found or fixed a bug.