A question about CRuntimeClass and Dynamic Creation
-
I want to implement a funtion.The follwing is its prototype: CRuntimeClass* FindClass(CString &strClassName) Parameter strClassName is the name of some class. I want to get the CRuntimeClass member variable of the class whose name is strClassName. For example : CString strClassName="CMyView"; CRuntimeClass * pRtc=FineClass(strClassName); ~~~~~~~~ I hope that I can get the pointer of CRuntimeClass member variable of CMyView; Thanks for your help I love sea
-
I want to implement a funtion.The follwing is its prototype: CRuntimeClass* FindClass(CString &strClassName) Parameter strClassName is the name of some class. I want to get the CRuntimeClass member variable of the class whose name is strClassName. For example : CString strClassName="CMyView"; CRuntimeClass * pRtc=FineClass(strClassName); ~~~~~~~~ I hope that I can get the pointer of CRuntimeClass member variable of CMyView; Thanks for your help I love sea
Hi, My first thought would be to add a CMapStringToPtr object into your CDocument class Then, on the constructor of each and every object you'll need, add a call to the object, e.g.
CMyView::CMyView() : CFormView(CMyView::IDD)
{
//{{AFX_DATA_INIT(CMyView)
//}}AFX_DATA_INITCMyDoc* pDoc = GetDocument();
if (pDoc) pDoc->RegisterClass(GetRuntimeClass()->m_lpszClassName, GetRuntimeClass());
}We then need to remember to add an 'unregister' to the destructor...MOST important if you have any objects that will get destroyed/recreated during the lifetime of the application - otherwise the pointer held in the map will point to junk memory
CMyView::~CMyView()
{
CMyDoc* pDoc = GetDocument();
if (pDoc) pDoc->UnregisterClass(GetRuntimeClass()->m_lpszClassName);
}Here are the functions in the Document...
BOOL CMyDoc::RegisterClass(const CString& strClassName, const CRuntimeClass* pClass)
{
CRuntimeClass* pLookup = NULL;
if (m_mapRuntimeClasses.Lookup(strClassName, (void*&)pLookup))
UnregisterClass(strClassName); // Remove existing entry ???m\_mapRuntimeClasses.SetAt(strClassName, ( void\*& )pClass); return TRUE;
}
BOOL CMyDoc::UnregisterClass(const CString& strClassName)
{
BOOL bRet = FALSE;CRuntimeClass\* pLookup = NULL; if (m\_mapRuntimeClasses.Lookup(strClassName, (void\*&)pLookup)) bRet = m\_mapRuntimeClasses.RemoveKey(strClassName); return bRet;
}
The m_mapRuntimeClasses is the CMapStringToPtr object - if you wanted to be all OO about it, then best to encapsulate the functions you want into a derived CMapStringToPtr object and have this in your CDocument. For any objects that need access to the document (other than views that already do), then preferred approach is:
CFrameWnd\* pFrame = (CFrameWnd\*)AfxGetApp()->m\_pMainWnd; if (pFrame && pFrame->GetSafeHwnd()) { CMyDoc\* pDoc = (CMyDoc\*)pFrame->GetActiveDocument(); if (pDoc) pDoc->Register(.....); }
Hope this helps, Andy
-
I want to implement a funtion.The follwing is its prototype: CRuntimeClass* FindClass(CString &strClassName) Parameter strClassName is the name of some class. I want to get the CRuntimeClass member variable of the class whose name is strClassName. For example : CString strClassName="CMyView"; CRuntimeClass * pRtc=FineClass(strClassName); ~~~~~~~~ I hope that I can get the pointer of CRuntimeClass member variable of CMyView; Thanks for your help I love sea
Your ModuleState has a public member m_classList that you can enumerate through to find what you want... // search app specific classes AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); AfxLockGlobals(CRIT_RUNTIMECLASSLIST); for (pClass = pModuleState->m_classList; pClass != NULL; pClass = pClass->m_pNextClass) { if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0) { AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST); return pClass; } } AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST); Regards "...Ability to type is not enough to become a Programmer. Unless you type in VB. But then again you have to type really fast..." Me
-
Your ModuleState has a public member m_classList that you can enumerate through to find what you want... // search app specific classes AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); AfxLockGlobals(CRIT_RUNTIMECLASSLIST); for (pClass = pModuleState->m_classList; pClass != NULL; pClass = pClass->m_pNextClass) { if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0) { AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST); return pClass; } } AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST); Regards "...Ability to type is not enough to become a Programmer. Unless you type in VB. But then again you have to type really fast..." Me
I have tried your code. But it does not work. "pModuleState->m_classList" is always eaqual to 0x0000. Can you tell me the reason? I love sea
-
Hi, My first thought would be to add a CMapStringToPtr object into your CDocument class Then, on the constructor of each and every object you'll need, add a call to the object, e.g.
CMyView::CMyView() : CFormView(CMyView::IDD)
{
//{{AFX_DATA_INIT(CMyView)
//}}AFX_DATA_INITCMyDoc* pDoc = GetDocument();
if (pDoc) pDoc->RegisterClass(GetRuntimeClass()->m_lpszClassName, GetRuntimeClass());
}We then need to remember to add an 'unregister' to the destructor...MOST important if you have any objects that will get destroyed/recreated during the lifetime of the application - otherwise the pointer held in the map will point to junk memory
CMyView::~CMyView()
{
CMyDoc* pDoc = GetDocument();
if (pDoc) pDoc->UnregisterClass(GetRuntimeClass()->m_lpszClassName);
}Here are the functions in the Document...
BOOL CMyDoc::RegisterClass(const CString& strClassName, const CRuntimeClass* pClass)
{
CRuntimeClass* pLookup = NULL;
if (m_mapRuntimeClasses.Lookup(strClassName, (void*&)pLookup))
UnregisterClass(strClassName); // Remove existing entry ???m\_mapRuntimeClasses.SetAt(strClassName, ( void\*& )pClass); return TRUE;
}
BOOL CMyDoc::UnregisterClass(const CString& strClassName)
{
BOOL bRet = FALSE;CRuntimeClass\* pLookup = NULL; if (m\_mapRuntimeClasses.Lookup(strClassName, (void\*&)pLookup)) bRet = m\_mapRuntimeClasses.RemoveKey(strClassName); return bRet;
}
The m_mapRuntimeClasses is the CMapStringToPtr object - if you wanted to be all OO about it, then best to encapsulate the functions you want into a derived CMapStringToPtr object and have this in your CDocument. For any objects that need access to the document (other than views that already do), then preferred approach is:
CFrameWnd\* pFrame = (CFrameWnd\*)AfxGetApp()->m\_pMainWnd; if (pFrame && pFrame->GetSafeHwnd()) { CMyDoc\* pDoc = (CMyDoc\*)pFrame->GetActiveDocument(); if (pDoc) pDoc->Register(.....); }
Hope this helps, Andy
Thanks a lot. I love sea
-
I have tried your code. But it does not work. "pModuleState->m_classList" is always eaqual to 0x0000. Can you tell me the reason? I love sea
The only reason it may not work is because you are using MFC in shared DLLs -- check _AFXDLL preprocessor definition and if it's defined you may use the following code: // search app specific classes AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); AfxLockGlobals(CRIT_RUNTIMECLASSLIST); for (pClass = pModuleState->m_classList; pClass != NULL; pClass = pClass->m_pNextClass) { if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0) { AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST); return pClass; } } AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST); #ifdef _AFXDLL // search classes in shared DLLs AfxLockGlobals(CRIT_DYNLINKLIST); for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL; pDLL = pDLL->m_pNextDLL) { for (pClass = pDLL->m_classList; pClass != NULL; pClass = pClass->m_pNextClass) { if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0) { AfxUnlockGlobals(CRIT_DYNLINKLIST); return pClass; } } } AfxUnlockGlobals(CRIT_DYNLINKLIST); #endif For an example of usage check code for CRuntimeClass* PASCAL CRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum) in MFC ArcCore.cpp file -- above example is taken from it -- it's used to load class during serialization... It just have to work, otherwise serialization cannot be achieved... Regards, Igor "...Ability to type is not enough to become a Programmer. Unless you type in VB. But then again you have to type really fast..." Me