The MFC class COleDispatchDriver makes calling Automation objects much easier. Further, the Class Wizard can be used to create classes from type library files that derive from COleDispatchDriver and provide C++ classes through which the Automation properties and methods can be called. The Automation parameter data types passed by the VARIANT structure are mapped onto standard C++ data types. You can use these classes even if your application does not otherwise use MFC. Generating these wrapper classes is very convenient, although for large Automation models the wrapper classes may increase the size of your application substantially. For example, the POOM object model adds around 29 KB to the application and also needs to dynamically link to the MFC libraries at run time. Most Windows CE devices have MFC libraries in ROM, but if not, you may consider statically linking to the MFC libraries. Doing so means your executable will only include that part of the MFC library required to support the COleDispatchDriver class. Creating a COleDispatchDriver-Derived ClassYou can create a COleDispatchDriver-derived class from a type library using the Class Wizard. To do this for POOM you should do the following:
You now need to locate a type library for the object model. In the case of POOM, you can select pimstore.dll, since this contains type library information. You can find this DLL, by default, in C:\Windows CE Tools\wce300\MS Pocket PC\emulation\palm300\windows for Pocket PC. It doesn't matter which target device pimstore.dll is built for, as long as it has type library information. Once the type library file is selected, you will get a dialog showing all the interfaces that are defined in the type library file (Figure 14.3). Figure 14.3. Confirming classes
The .h file created by this process ("pimstore.h" in the example above) will contain a class derived from COleDispatchDriver for each interface selected in the "Browse Classes" dialog. These classes will have member functions for each property and method. The member functions for methods will use the same name as the method. For a property, a Put function (for example, "PutMyProperty") and a Get function (for example, "GetMyProperty") function will be created. Note that these classes will need to be regenerated if the Automation interface changes. In general, this does not happen, but it is possible for dispid values to change for property and methods between versions. Take care when regenerating the classes since the old classes are not overwritten new classes are appended to the end of the existing source files. The following code shows some of the member functions declared in the IPOutlookApp class: class IPOutlookApp : public COleDispatchDriver { ... public: ... void Logon(long hWnd); void Logoff(); CString GetVersion(); LPDISPATCH GetDefaultFolder(long olFolder); LPDISPATCH CreateItem(long OlItemType); LPDISPATCH GetItemFromOid(long oid); LPDISPATCH GetHomeCity(); ... The name IPOutlookApp implies that this is a COM interface definition, but it is actually a simple C++ class. The member functions, like Logon, call the IDispatch::Invoke interface function, as the following implementation of Logon illustrates: void IPOutlookApp::Logon(long hWnd) { static BYTE parms[] = VTS_I4; InvokeHelper(0x60020000, DISPATCH_METHOD, VT_EMPTY, NULL, parms, hWnd); } InvokeHelper is declared in COleDispatchDriver and takes a variable number of arguments:
You will need to ensure that the correct MFC header files and defines are used. The following can be added to the header file generated by Class Wizard (for example "pimstore.h"), and this can help reduce conflicts with other header files you may be using: #define _AFXDLL #include <afx.h> #include <afxdisp.h> The define "_AFXDLL" will link your application to the DLL versions of the MFC run time, and this reduces the size of your application. Using the IPOutlookApp ClassA simple example of using these classes is provided in Listing 14.12. This function is located in the source file Chapter 14MFC.CPP, since including the "pimstore.h" MFC-created header file in Chapter 14.cpp will cause class conflicts with the "pimstore.h" standard header file included in Chapter 14.cpp. Both these header files will have IPOutlookApp classes defined. Listing 14.12 Using the IPOutlookApp classvoid Listing14_12(HWND hWnd) { IPOutlookApp pOutlookApp; CString sVersion; if(!pOutlookApp.CreateDispatch( _T("PocketOutlook.Application"))) { cout _T("Could not create dispatch interface") endl; return; } pOutlookApp.Logon((LONG)hWnd); sVersion = pOutlookApp.GetVersion(); cout _T("Version: ") sVersion endl; pOutlookApp.Logoff(); } Listing 14.12 declares a IPOutlookApp class object. Remember that this class IPOutlookApp inherits from COleDispatchDriver and is not the interface definition used in earlier code examples. The COleDispatchDriver ::CreateDispatch member function is called to create the COM component and to request an IDispatch interface pointer. This function is passed the POOM ProgId ("PocketOutlook.Application"), although the CLSID could have been passed instead. Automation property methods and properties can then be accessed through the class member functions. You will notice that GetVersion, for example, returns an MFC CString, which makes the function very easy to use. The MFC classes also look after all issues to do with reference counting. Many Automation methods or properties return IDISPATCH pointers, and these can be used with the MFC classes. In Listing 14.13 the IPOutlookApp member function CreateItem is used to create a new item the type of item is specified using the constant olTaskItem. The MFC Class Wizard does not pick up constants defined in an Automation object, so these are defined in Listing 14.13. You can find out the values assigned to constants from the on-line help, or from the system header file pimstore.h (not pimstore.h created by the Class Wizard). Listing 14.13 Adding a task#define olTaskItem 3 #define olImportanceHigh 2 void AddTask(IPOutlookApp& pOutlookApp) { ITask pTask; LPDISPATCH lpDispatch; lpDispatch = pOutlookApp.CreateItem(olTaskItem); pTask.AttachDispatch(lpDispatch, TRUE); pTask.SetSubject(_T("Task created from POOM")); pTask.SetBody(_T("The body text for task")); pTask.SetImportance(olImportanceHigh); pTask.Save(); } The IDispatch pointer returned from CreateItem is placed temporarily in the LPDISPATCH variable lpDispatch. An ITask class object is declared called pTask, and the COleDispatchDriver::AttachDispatch function is used to associate the IDispatch pointer with pTask. The second parameter TRUE passed to AttachDispatch specifies that the MFC classes will be responsible for reference counting.
|