| BOOL EnumChildWindows( HWND hWndParent, // 父窗口的句柄 WNDENUMPROC lpEnumFunc, // 用户自定义回调函数 LPARAM lParam // 传给回调函数的自定义参数 ); 回调函数的定义如下: BOOL CALLBACK EnumChildProc( HWND hwnd, // 字窗口的句柄 LPARAM lParam // 自定义参数 ); |
| { ...... CWnd* pWnd; CWnd* pWndToDelete; // 使用EnumChildWindows查找从CView继承的子窗口 ::EnumChildWindows(m_hWnd, MyWndEnumProc, (LPARAM)&(pWnd)); if(pWnd == NULL) {// 没有发现子窗口 return FALSE;} // 发现子窗口,找到级别最高的子窗口,即父窗口为CMainFrame的窗口 while( lstrcmp(pWnd->GetRuntimeClass()->m_lpszClassName, ″CMainFrame″) ) { pWndToDelete = pWnd; pWnd = pWnd->GetParent(); } // 确保视图被删除时文档不被删除 pDoc->m_bAutoDelete = FALSE;} // 删除视图 |
用户定义的回调函数:
| BOOL CALLBACK MyWndEnumProc(HWND hWnd, LPARAM ppWndLPARAM) { CWnd* pWndChild = CWnd::FromHandlePermanent(hWnd); CWnd** ppWndTemp = (CWnd**)ppWndLPARAM; if( pWndChild && pWndChild->IsKindOf(RUNTIME_CLASS(CView)) ) { // 发现任何从CView继承的子窗口,将子窗口指针传递出去 *ppWndTemp = pWndChild; // 停止继续搜索 return FALSE; } else { *ppWndTemp = NULL; // 继续搜索 return TRUE; }} |
2.创建新的视图
| CDocument* pCurrentDoc = ((CFrameWnd*) m_pMainWnd)->GetActiveDocument(); // 初始化创建上下文相关指针 CCreateContext newContext; newContext.m_pNewViewClass = RUNTIME_CLASS(CView1); newContext.m_pCurrentDoc = pCurrentDoc; newContext.m_pNewDocTemplate = NULL; newContext.m_pLastView = NULL; newContext.m_pCurrentFrame = NULL; CView* pNewView = STATIC_DOWNCAST(CView, CreateView(&newContext)); if( pNewView == NULL ) { return FALSE; } // 使用CreateView创建的视图不能自动调用OnInitialUpdate函数,需要人工调用OnInitialUpdate函数或者发送WM_INITIALUPDATE消息 pNewView->OnInitialUpdate(); // 使用CreateView创建的视图不会自动显示并且激活,需要人工操作 pNewView->ShowWindow(SW_SHOW); SetActiveView(pNewView); RecalcLayout(); |
注:RUNTIME_CLASS宏含义
每一个从CObject类继承的类,在定义DECLARE_DYNAMIC、DECLARE_DYNCREATE、DECLARE_SERIAL三个中任意一个宏时都会产生一个CRuntimeClass结构的静态对象,RUNTIME_CLASS返回的就是这个对象的指针,这个对象包含了其基类和本身在运行时刻的信息。以上是笔者在编写多个视应用在单文档的程序时整理出来的两种方法,因为VC++的强大和灵活,笔者相信还有更加巧妙的方法实现这个功能,希望这篇文章能够起到抛砖引玉的作用,也希望广大VC++编程爱好者对本文能够给予批评和指正。
关注此文的读者还看过: