Implement your own factory class in MFC

Source: Internet
Author: User
Tags flock
In CoCreateInstance, call CoGetClassObject to obtain IClassFactory (IClassFactory2), and IClassFactory2 call its own CreateInstance or CreateInstanceLic to create a control instance. Here, IClassFactory plays a very important role. Especially in MFC, all controls are derived from COleControl (COleControl and csf-target ), COleControl itself does not implement any interfaces, including IUnknown. All interfaces are implemented in the COleControl package class. Therefore, the class factory also needs to call the correct function to return the correct IUnknown pointer (here, the InternalQueryInterface of csf-target is generally called instead of the normal QueryInterface, because the newly created COleControl instance pointer is not an interface pointer, the QueryInterface method is not provided ).

In MFC, IClassFactory is implemented by COleObjectFactory (or COleObjectFactoryEx. In fact, COleObjectFactory itself is also derived from CCmdTarget, and does not directly implement IClassFactory, but is implemented by its package class XOleObjectFactory.

After CoGetClassObject finds the correct Dll in the registry, it calls the DllGetClassObject of the Dll to obtain the corresponding class factory. Here, MFC implements DllGetClassObject, it searches for the COleObjectFactory list in the current Dll module, finds the COleObjectFactory corresponding to the required class ID (CLSID), and then calls COleObjectFactory (c1_target) internalQueryInterface of returns the corresponding IClassFactory2 interface pointer.

In theory, we should be able to completely put aside the class factory mechanism of MFC, build a class factory from the ground up, and implement the DllGetClassObject. But it seems that there is no need. We can derive our own class factory from the COleObjectFactory. You only need to implement IClassFactory in your own factory class.

1. Create a control
2. Create a New CMyObjectFactory class derived from COleObjectFactory and add a macro defining the IClassFactory interface to implement the Code and interface ing table of the IClassFactory interface, as shown below:

// MyObjectFactory. h
Class CMyObjectFactory: public COleObjectFactoryEx
{
Public:
Void CreateErrorInfo ();
CMyObjectFactory (REFCLSID clsid, CRuntimeClass * pRuntimeClass,
BOOL bMultiInstance, LPCTSTR lpszProgID ):
COleObjectFactory (clsid, pRuntimeClass, bMultiInstance, lpszProgID)
{
}
Virtual ~ CMyObjectFactory ();

BEGIN_INTERFACE_PART (MyClassFactory, IClassFactory2)
INIT_INTERFACE_PART (CMyObjectFactory, ClassFactory)
STDMETHOD (CreateInstance) (LPUNKNOWN, REFIID, LPVOID *);
STDMETHOD (LockServer) (BOOL );
STDMETHOD (GetLicInfo) (LPLICINFO );
STDMETHOD (RequestLicKey) (DWORD, BSTR *);
STDMETHOD (CreateInstanceLic) (LPUNKNOWN, LPUNKNOWN, REFIID, BSTR,
LPVOID *);
END_INTERFACE_PART (MyClassFactory)

DECLARE_INTERFACE_MAP ()

};

// MyObjectFactory. cpp

BEGIN_INTERFACE_MAP (CMyObjectFactory, COleObjectFactoryEx)
INTERFACE_PART (CMyObjectFactory, IID_IClassFactory, MyClassFactory)
INTERFACE_PART (CMyObjectFactory, IID_IClassFactory2, MyClassFactory)
END_INTERFACE_MAP ()

//////////////////////////////////////// //////////////////////////////
// Construction/Destruction
//////////////////////////////////////// //////////////////////////////

CMyObjectFactory ::~ CMyObjectFactory ()
{

}

STDMETHODIMP _ (ULONG) CMyObjectFactory: XMyClassFactory: AddRef ()
{
METHOD_PROLOGUE_EX _ (CMyObjectFactory, MyClassFactory)
Return pThis-> InternalAddRef ();
}

STDMETHODIMP _ (ULONG) CMyObjectFactory: XMyClassFactory: Release ()
{
METHOD_PROLOGUE_EX _ (CMyObjectFactory, MyClassFactory)
Return pThis-> InternalRelease ();
}

STDMETHODIMP CMyObjectFactory: XMyClassFactory: QueryInterface (
REFIID iid, LPVOID * ppvObj)
{
METHOD_PROLOGUE_EX _ (CMyObjectFactory, MyClassFactory)
Return pThis-> InternalQueryInterface (& iid, ppvObj );
}

STDMETHODIMP CMyObjectFactory: XMyClassFactory: CreateInstance (
IUnknown * pUnkOuter, REFIID riid, LPVOID * ppvObject)
{
Return CreateInstanceLic (pUnkOuter, NULL, riid, NULL, ppvObject );
}

STDMETHODIMP CMyObjectFactory: XMyClassFactory: LockServer (BOOL fLock)
{
METHOD_PROLOGUE_EX (CMyObjectFactory, MyClassFactory)
ASSERT_VALID (pThis );

SCODE SC = E_UNEXPECTED;
TRY
{
If (fLock)
AfxOleLockApp ();
Else
AfxOleUnlockApp ();
SC = S_ OK;
}
END_TRY

Return SC;
}

STDMETHODIMP CMyObjectFactory: XMyClassFactory: GetLicInfo (
LPLICINFO pLicInfo)
{
METHOD_PROLOGUE_EX (CMyObjectFactory, MyClassFactory)
ASSERT_VALID (pThis );

BSTR bstr = NULL;
PLicInfo-> fLicVerified = pThis-> IsLicenseValid ();
PLicInfo-> fRuntimeKeyAvail = pThis-> GetLicenseKey (0, & bstr );
If (bstr! = NULL)
SysFreeString (bstr );

Return S_ OK;
}

STDMETHODIMP CMyObjectFactory: XMyClassFactory: RequestLicKey (
DWORD dwReserved, BSTR * pbstrKey)
{
METHOD_PROLOGUE_EX (CMyObjectFactory, MyClassFactory)
ASSERT_VALID (pThis );

ASSERT (pbstrKey! = NULL );

* PbstrKey = NULL;

If (pThis-> IsLicenseValid ())
{
If (pThis-> GetLicenseKey (dwReserved, pbstrKey ))
Return S_ OK;
Else
Return E_FAIL;
}
Else
Return CLASS_E_NOTLICENSED;
}

STDMETHODIMP CMyObjectFactory: XMyClassFactory: CreateInstanceLic (
LPUNKNOWN pUnkOuter, LPUNKNOWN/* pUnkReserved */, REFIID riid,
BSTR bstrKey, LPVOID * ppvObject)
{
METHOD_PROLOGUE_EX (CMyObjectFactory, MyClassFactory)
ASSERT_VALID (pThis );

If (ppvObject = NULL)
Return E_POINTER;
* PpvObject = NULL;

If (bstrKey! = NULL )&&! PThis-> VerifyLicenseKey (bstrKey) |
(BstrKey = NULL )&&! PThis-> IsLicenseValid ()))
Return CLASS_E_NOTLICENSED;

// Outer objects must ask for IUnknown only
ASSERT (pUnkOuter = NULL | riid = IID_IUnknown );

// Add a message box to indicate that this is my factory
MessageBox (NULL, "hello", NULL, MB_ OK );
// Attempt to create the object
Csf-target * pTarget = NULL;
SCODE SC = E_OUTOFMEMORY;
TRY
{
// Attempt to create the object
PTarget = pThis-> OnCreateObject ();
If (pTarget! = NULL)
{
// Check for aggregation on object not supporting it
SC = CLASS_E_NOAGGREGATION;
If (pUnkOuter = NULL | pTarget-> m_xInnerUnknown! = 0)
{
// Create aggregates used by the object
PTarget-> m_pOuterUnknown = pUnkOuter;
SC = E_OUTOFMEMORY;
If (pTarget-> OnCreateAggregates ())
SC = S_ OK;
}
}
}
END_TRY

// Finish creation
If (SC = S_ OK)
{
DWORD dwRef = 1;
If (pUnkOuter! = NULL)
{
// Return inner unknown instead of IUnknown
* PpvObject = & pTarget-> m_xInnerUnknown;
}
Else
{
// Query for requested interface
SC = pTarget-> InternalQueryInterface (& riid, ppvObject );
If (SC = S_ OK)
{
DwRef = pTarget-> InternalRelease ();
ASSERT (dwRef! = 0 );
}
}
If (dwRef! = 1)
TRACE1 ("Warning: object created with reference of % ld/n", dwRef );
}

// Cleanup in case of errors
If (SC! = S_ OK)
Delete pTarget;

Return SC;
}
The implementation code here is basically copied from the COleObjectFactory of MFC. Only a MessageBox is added to the CreateInstanceLic method.

3. Now we need to use our CMyObjectFactory to replace the default COleObjectFactory.
A. We need to define several macros first. Of course we can use them without macros. This is just a convenient place to look.
# Define BEGIN_MYOLEFACTORY (class_name )/
Protected :/
Class class_name # Factory: public CMyObjectFactory/
{/
Public :/
Class_name # Factory (REFCLSID clsid, CRuntimeClass * pRuntimeClass ,/
BOOL bMultiInstance, LPCTSTR lpszProgID ):/
CMyObjectFactory (clsid, pRuntimeClass, bMultiInstance ,/
LpszProgID ){}/
Virtual BOOL UpdateRegistry (BOOL );

# Define END_MYOLEFACTORY (class_name )/
};/
Friend class class_name # Factory ;/
Static AFX_DATA class_name # Factory factory ;/
Public :/
Static AFX_DATA const GUID guid ;/
Virtual HRESULT GetClassID (LPCLSID pclsid );

# Define DECLARE_MYOLECREATE_EX (class_name )/
BEGIN_MYOLEFACTORY (class_name )/
END_MYOLEFACTORY (class_name)

In MFC, BEGIN_OLEFACTORY (class_name) and END_OLEFACTORY (class_name) are matched ), because these macros in MFC have fixed the control's class factory, they must be derived from the COleObjectFactory (the list we mentioned earlier on the module is the COleObjectFactory pointer list, therefore, it is obvious that the COleObjectFactory must be derived from the COleObjectFactory. The COleObjectFactory implementation IClassFactory is in its package class. We cannot directly inherit the COleObjectFactory to implement IClassFactory on our own, if we define our own IClassFactory implementation in the middle of the in_olefactoryt and END_OLEFACTORY macros, it will become the package class. The whole awkwardly, so we have to change its macro, fortunately, these macros are not complex.

B. Comment out DECLARE_OLECREATE_EX (COfCtrl) and change it
DECLARE_MYOLECREATE_EX (COfCtrl)

As for IMPLEMENT_OLECREATE_EX, you don't need to change it. How can this problem be solved.

4. Compile and test it.
Change DECLARE_MYOLECREATE_EX back to DECLARE_OLECREATE_EX. After compilation, the default COleObjectFactory is used again, which is easy enough.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.