在MFC中实现自己的类厂
来源:互联网 发布:买苹果电脑装windows 编辑:程序博客网 时间:2024/04/28 05:57
CoCreateInstance中调用CoGetClassObject获得IClassFactory(IClassFactory2),IClassFactory2又调用自己的CreateInstance或CreateInstanceLic建立控件实例。这里面类厂(IClassFactory)起到了非常重要的作用,特别是在MFC中,所有的控件都派生自COleControl(COleControl又派生自CCmdTarget),而COleControl本身却没有实现任何的接口,包括IUnknown。所有的接口都在COleControl的包裹类中实现。因此这里的类厂还需要调用正确的函数来返回正确的IUnknown指针(这里一般会调用CCmdTarget的InternalQueryInterface而不是通常的QueryInterface,因为新建的COleControl实例指针本身并不是一个接口指针,不提供QueryInterface方法)。
在MFC中,IClassFactory由COleObjectFactory(或者COleObjectFactoryEx,其实是一样的)实现。其实COleObjectFactory本身也派生自CCmdTarget,也没有直接实现IClassFactory,而是由其包裹类XOleObjectFactory来实现的。
CoGetClassObject在注册表中找到正确的Dll后,就调用该Dll的DllGetClassObject来获得相应的类厂,在这里,MFC实现了DllGetClassObject,它搜索存在当前Dll模块中的COleObjectFactory列表,找到与所要求的类ID(CLSID)相对应的COleObjectFactory后,就调用COleObjectFactory(CCmdTarget)的InternalQueryInterface返回相应的IClassFactory2接口指针。
理论上讲应该可以完全撇开MFC的类厂机制,自己从头建一个类厂,自己实现DllGetClassObject。不过好象是没有什么必要的,我们完全可以从COleObjectFactory派生自己的类厂。只要在自己的这个类厂类(真别扭)中实现IClassFactory就可以了。
1.新建控件of
2.新建派生自COleObjectFactory的类CMyObjectFactory,并加入定义IClassFactory接口的宏,实现IClassFactory接口的代码和接口映射表,如下:
//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);
//这里加入消息框,以表示这是我的类厂
MessageBox(NULL, "hello", NULL, MB_OK);
// attempt to create the object
CCmdTarget* 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;
}
这里的实现代码基本上都是从MFC的COleObjectFactory中拷过来的。只是在CreateInstanceLic方法中加了一个MessageBox。
3.现在要用我们的CMyObjectFactory来代替缺省的COleObjectFactory了。
a.我们先要定义几个宏,当然不用宏也可以,这里只是贪图方便罢了
#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)
在MFC中对应的是BEGIN_OLEFACTORY(class_name)和END_OLEFACTORY(class_name),因为MFC中的这些宏已经定死了控件的类厂必须派生自COleObjectFactory(前面我们提到在模块上存放的列表就是COleObjectFactory指针列表,所以必须派生自COleObjectFactory是很显然的),而COleObjectFactory实现IClassFactory是在它的包裹类中,我们并不能直接继承COleObjectFactory就可以轻松的自己实现IClassFactory了,如果在由BEGIN_OLEFACTORYT和END_OLEFACTORY宏对中间定义我们自己的IClassFactory实现,那就变成包裹类的包裹类了,整个别扭的很啊,只好改它的宏了,幸好这几个宏并不复杂。
b.注释掉DECLARE_OLECREATE_EX(COfCtrl),改成
DECLARE_MYOLECREATE_EX(COfCtrl)
至于IMPLEMENT_OLECREATE_EX就不用改了,该怎样还怎样吧。
4.编译,测试吧。
将DECLARE_MYOLECREATE_EX改回DECLARE_OLECREATE_EX,再编译的话,就又用回缺省的COleObjectFactory,够省事的了。
在MFC中,IClassFactory由COleObjectFactory(或者COleObjectFactoryEx,其实是一样的)实现。其实COleObjectFactory本身也派生自CCmdTarget,也没有直接实现IClassFactory,而是由其包裹类XOleObjectFactory来实现的。
CoGetClassObject在注册表中找到正确的Dll后,就调用该Dll的DllGetClassObject来获得相应的类厂,在这里,MFC实现了DllGetClassObject,它搜索存在当前Dll模块中的COleObjectFactory列表,找到与所要求的类ID(CLSID)相对应的COleObjectFactory后,就调用COleObjectFactory(CCmdTarget)的InternalQueryInterface返回相应的IClassFactory2接口指针。
理论上讲应该可以完全撇开MFC的类厂机制,自己从头建一个类厂,自己实现DllGetClassObject。不过好象是没有什么必要的,我们完全可以从COleObjectFactory派生自己的类厂。只要在自己的这个类厂类(真别扭)中实现IClassFactory就可以了。
1.新建控件of
2.新建派生自COleObjectFactory的类CMyObjectFactory,并加入定义IClassFactory接口的宏,实现IClassFactory接口的代码和接口映射表,如下:
//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);
//这里加入消息框,以表示这是我的类厂
MessageBox(NULL, "hello", NULL, MB_OK);
// attempt to create the object
CCmdTarget* 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;
}
这里的实现代码基本上都是从MFC的COleObjectFactory中拷过来的。只是在CreateInstanceLic方法中加了一个MessageBox。
3.现在要用我们的CMyObjectFactory来代替缺省的COleObjectFactory了。
a.我们先要定义几个宏,当然不用宏也可以,这里只是贪图方便罢了
#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)
在MFC中对应的是BEGIN_OLEFACTORY(class_name)和END_OLEFACTORY(class_name),因为MFC中的这些宏已经定死了控件的类厂必须派生自COleObjectFactory(前面我们提到在模块上存放的列表就是COleObjectFactory指针列表,所以必须派生自COleObjectFactory是很显然的),而COleObjectFactory实现IClassFactory是在它的包裹类中,我们并不能直接继承COleObjectFactory就可以轻松的自己实现IClassFactory了,如果在由BEGIN_OLEFACTORYT和END_OLEFACTORY宏对中间定义我们自己的IClassFactory实现,那就变成包裹类的包裹类了,整个别扭的很啊,只好改它的宏了,幸好这几个宏并不复杂。
b.注释掉DECLARE_OLECREATE_EX(COfCtrl),改成
DECLARE_MYOLECREATE_EX(COfCtrl)
至于IMPLEMENT_OLECREATE_EX就不用改了,该怎样还怎样吧。
4.编译,测试吧。
将DECLARE_MYOLECREATE_EX改回DECLARE_OLECREATE_EX,再编译的话,就又用回缺省的COleObjectFactory,够省事的了。
- 在MFC中实现自己的类厂
- 在MFC中实现自己的类厂
- 在MFC中注册自己的窗口类名
- MFC实现自己的串口
- 【框架-MFC】CView(chenlu1):MFC在CView的派生类中实现打印和打印预览
- MFC 学习---05(在已有类中增加自己的类)
- 在MFC中实现 EventSink
- 在MFC中使用一个单独的类实现数据在各个类之间的传递
- 如何在MFC中实现工具条按钮的互斥
- 如何在MFC的SDI程序中实现多视图
- 在MFC中实现自定义的消息发送
- 在MFC编程中怎么实现对话框的伸缩
- 如何在MFC的SDI程序中实现多视图
- VTK在MFC中实现的小实例
- 如何在MFC的SDI程序中实现多视图
- 在MFC中实现对象之间数据的传递。
- 在MFC中实现打开文件的功能
- 自己的Ping程序(MFC实现)
- 与RSS的第一次亲密接触
- Master页面中的路径设置
- 人
- RSS:让思想凝聚在一起
- Tips_SystemC
- 在MFC中实现自己的类厂
- 25岁以上程序员单身手册
- 怎么让你朋友变笨
- 重新抛出异常与 public Throwable fillInStackTrace()
- AJAX相关资源
- 最近
- 安装和注册激活 SWT Designer
- 初学者如何开发出一个高质量的J2EE系统
- 我想做的一套人员认证系统的应该有的功能