How to use single or multiple instances of an OLE object in MFC by using Visual C++ (141154)



The information in this article applies to:

  • The Microsoft Foundation Classes (MFC), when used with:
    • Microsoft Visual C++ for Windows, 16-bit edition 1.0
    • Microsoft Visual C++ for Windows, 16-bit edition 1.5
    • Microsoft Visual C++ for Windows, 16-bit edition 1.51
    • Microsoft Visual C++ for Windows, 16-bit edition 1.52
    • Microsoft Visual C++, 32-bit Editions 2.0
    • Microsoft Visual C++, 32-bit Editions 2.1
    • Microsoft Visual C++, 32-bit Editions 2.2
    • Microsoft Visual C++, 32-bit Editions 4.0
    • Microsoft Visual C++, 32-bit Enterprise Edition 5.0
    • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
    • Microsoft Visual C++, 32-bit Professional Edition 5.0
    • Microsoft Visual C++, 32-bit Professional Edition 6.0
    • Microsoft Visual C++, 32-bit Learning Edition 6.0
    • Microsoft Visual C++ .NET (2003)
    • Microsoft Visual C++ .NET (2002)
    • Microsoft Visual C++ 2005 Express Edition

This article was previously published under Q141154
Note Microsoft Visual C++ NET (2002) supported both the managed code model that is provided by the .NET Framework and the unmanaged native Windows code model. The information in this article applies to unmanaged Visual C++ code only.

Note Microsoft Visual C++ 2005 supports both the managed code model that is provided by the .NET Framework and the unmanaged native Windows code model.

SUMMARY

This article explains how class factories are registered in an OLE local server created using MFC. This topic is discussed with respect to whether a single instance of an application can service multiple clients or whether a separate instance will be launched for each request made by a client.

The class factory specifically attached to the document template behaves differently based on whether it's a default SDI (single document interface) or an MDI (multiple document interface) application. Other generic class factories behave according to how they are registered with OLE.

MORE INFORMATION

MFC provides an interface implementation for the class factory (IClassFactory) in a class called COleObjectFactory, which serves as a generic type of factory. In addition, MFC also provides a specific class factory called COleTemplateServer, derived from COleObjectFactory, to create documents using the framework's document/view architecture.

In the case of a local server, the class factories have to be registered with OLE so that other applications can connect to them. In MFC, all the class factories of a server are typically registered in CWinApp::InitInstance by calling the static function COleObjectFactory::RegisterAll(). This function calls COleObjectFactory::Register() for each of the class factories, which in turn calls CoRegisterClassObject in the case of a local server. In the case of an inproc server, there is no need to register the class factories with OLE because COM loads the DLL (that is, the server) and invokes a well- known entry-point, called DllGetClassObject, to retrieve an IClassFactory interface.

When a client requests that a server create an instance of an object, the decision to use a running instance of the server, if one is available, or to launch another instance of the server is made by OLE depending on how the class factory for the object is registered. The determining factor is the fourth parameter to CoRegisterClassObject, which specifies how many objects can be created using this class factory. If REGCLS_SINGLEUSE is specified, OLE will launch another instance of the application each time a client requests an instance of an object class. If REGCLS_MULTIPLEUSE is specified, one instance of the application can service any number of objects.

MDI applications use the same main frame window (that is, the same instance of the application) and create a new MDI child window for each request made by a client to create an object instance. When a client calls CoCreateInstance to create a document window object exposed by COleTemplateServer, a new MDI child window is created using the same MDI frame window. MFC implements this concept by passing in FALSE as the m_bMultiInstance parameter to the ConnectTemplate function of COleTemplateServer. This registers the class factory as single instance by passing REGCLS_MULTIPLEUSE to CoRegisterClassObject.

SDI applications, on the other hand, can manage only one document window at a time. Hence, SDI applications are by default single use only; that is, a separate instance (or a document window) is created for each call to CoCreateInstance made by a client. This is implemented in an MFC application by passing in TRUE as the m_bMultiInstance parameter to COleTemplateServer::ConnectTemplate, which registers the class factory as multiple instance by passing REGCLS_SINGLEUSE to CoRegisterClassObject.

Generic class factories that are used to create any C++ object are registered as single- or multiple-use based on how the constructor for COleObjectFactory is invoked. The constructor takes a bMultiInstance parameter that specifies whether the class factory is registered as REGCLS_SINGLEUSE (bMultiInstance == TRUE) or REGCLS_MULTIPLEUSE (bMultiInstance == FALSE).

When ClassWizard is used to add OLE-creatable classes to an MFC application, it adds the DECLARE_OLECREATE and IMPLEMENT_OLECREATE macros. DECLARE_OLECREATE declares a static object of type COleObjectFactory, and IMPLEMENT_OLECREATE creates this object by invoking the constructor of COleObjectFactory with the bMultiInstance parameter set to FALSE. In other words, ClassWizard registers the generic class factory as REGCLS_MULTIPLEUSE. Hence by default, a single instance of an OLE-creatable class generated by ClassWizard can serve multiple requests to create an instance of this object class.

This behavior can be altered by replacing IMPLEMENT_OLECREATE with a custom macro, say MY_IMPLEMENT_OLECREATE, which invokes the COleObjectFactory constructor with the bMultiInstance parameter set to TRUE, which will then register a REGCLS_SINGLEUSE class factory. For example:
#define MY_IMPLEMENT_OLECREATE(class_name, external_name, l, w1, w2,
        b1, b2, b3, b4, b5, b6, b7, b8) \ 
        COleObjectFactory class_name::factory(class_name::guid, \ 
        RUNTIME_CLASS(class_name), TRUE, _T(external_name)); \ 
        const GUID CDECL class_name::guid = \ 
        { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \ 


MY_IMPLEMENT_OLECREATE(CMyClass, "Test", 0xc9c99ae0, 0xad41, 0x101b,
                       0x83, 0xea, 0x0, 0x0, 0x83, 0x78, 0xac, 0x8b)
				
The CLSID used in this macro call should be replaced with the actual CLSID assigned for this particular object, which can be found in the original IMPLEMENT_OLECREATE macro.

REFERENCES

Inside OLE 2.0, Second Edition.

Visual C++ Books Online and the MFC source code for the functions mentioned in the article.

Modification Type:MajorLast Reviewed:12/10/2005
Keywords:kbArchitecture kbinfo kbLocalSvr KB141154 kbAudDeveloper