Automation Programming Choices

Suppose you're writing an Automation component in C++. You've got some choices to make. Do you want an in-process component or an out-of-process component? What kind of user interface do you want? Does the component need a user interface at all? Can users run your EXE component as a stand-alone application? If the component is an EXE, will it be SDI or MDI? Can the user shut down the component program directly?

If your component is a DLL, COM linkage will be more efficient than it would be with an EXE component because no marshaling is required. Most of the time, your in-process Automation components won't have their own user interfaces, except for modal dialog boxes. If you need a component that manages its own child window, you should use an ActiveX control, and if you want to use a main frame window, use an out-of-process component. As with any 32-bit DLL, an Automation DLL is mapped into the client's process memory. If two client programs happen to request the same DLL, Windows loads and links the DLL twice. Each client is unaware that the other is using the same component.

With an EXE component, however, you must be careful to distinguish between a component program and a component object. When a client calls IClassFactory::CreateInstance to construct a component object, the component's class factory constructs the object, but COM might or might not need to start the component program.

Here are some scenarios:

  1. The component's COM-creatable class is programmed to require a new process for each object constructed. In this case, COM starts a new process in response to the second and subsequent CreateInstance calls, each of which returns an IDispatch pointer.

  2. Here's a special case of scenario 1 above, specific to MFC applications. The component class is an MFC document class in an SDI application. Each time a client calls CreateInstance, a new component process starts, complete with a document object, a view object, and an SDI main frame window.

  3. The component class is programmed to allow multiple objects in a single process. Each time a client calls CreateInstance, a new component object is constructed. There is only one component process, however.

  4. Here's a special case of scenario 3 above, specific to MFC applications. The component class is an MFC document class in an MDI application. There is a single component process with one MDI main frame window. Each time a client calls CreateInstance, a new document object is constructed, along with a view object and an MDI child frame window.

There's one more interesting case. Suppose a component EXE is running before the client needs it, and then the client decides to access a component object that already exists. You'll see this case with Excel. The user might have Excel running but minimized on the desktop, and the client needs access to Excel's one and only Application object. Here the client calls the COM function GetActiveObject, which provides an interface pointer for an existing component object. If the call fails, the client can create the object with CoCreateInstance.

For component object deletion, normal COM rules apply. Automation objects have reference counts, and they delete themselves when the client calls Release and the reference count goes to 0. In an MDI component, if the Automation object is an MFC document, its destruction causes the corresponding MDI child window to close. In an SDI component, the destruction of the document object causes the component process to exit. The client is responsible for calling Release for each IDispatch interface before the client exits. For EXE components, COM will intervene if the client exits without releasing an interface, thus allowing the component process to exit. You can't always depend on this intervention, however, so be sure that your client cleans up its interfaces!

With generic COM, a client application often obtains multiple interface pointers for a single component object. Look back at the spaceship example in Chapter 24, in which the simulated COM component class had both an IMotion pointer and an IVisual pointer. With Automation, however, there's usually only a single (IDispatch) pointer per object. As in all COM programming, you must be careful to release all your interface pointers. In Excel, for example, many properties return an IDispatch pointer to new or existing objects. If you fail to release a pointer to an in-process COM component, the Debug version of the MFC library alerts you with a memory-leak dump when the client program exits.

The MFC IDispatch Implementation

The component program can implement its IDispatch interface in several ways. The most common of these pass off much of the work to the Windows COM DLLs by calling the COM function CreateStdDispatch or by delegating the Invoke call to the ITypeInfo interface, which involves the component's type library. A type library is a table, locatable through the Registry, which allows a client to query the component for the symbolic names of objects, methods, and properties. A client could, for example, contain a browser that allows the user to explore the component's capabilities.

The MFC library supports type libraries, but it doesn't use them in its implementation of IDispatch, which is instead driven by a dispatch map. MFC programs don't call CreateStdDispatch at all, nor do they use a type library to implement IDispatch::GetIDsOfNames. This means that you can't use the MFC library if you implement a multilingual Automation component—one that supports English and German property and method names, for example. (CreateStdDispatch doesn't support multilingual components either.)

Later in this chapter you'll learn how a client can use a type library, and you'll see how AppWizard and ClassWizard create and maintain type libraries for you. Once your component has a type library, a client can use it for browsing, independent of the IDispatch implementation.



Programming Microsoft Visual C++
Programming Microsoft Visual C++
ISBN: 1572318570
EAN: 2147483647
Year: 1997
Pages: 332

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net