classView不显示已存在的类向导

本文介绍了一个常见的VC++6.0程序开发中的bug:在ClassView中无法查看到某些类的信息。文章提供了详细的解决方案,包括删除.ncb文件并重新编译项目的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做一个VC++程序,在做的过程中出现一个问题:视图类明明存在可是在ClassView中竟然没有类的相关信息,这是怎么回事呢,网上查资料,原来是vc++ 6.0的一个非常经典的bug.

解决:打开工程所在项目----->找到一个以.ncb结尾的文件,将其删除----->再次打开工程----->看到完整的类信息了----->解决。

注:

NCB是 “No Compile Browser”的缩写,其中存放了供ClassView、WizardBar和Component Gallery使用的信息,由VC开发环境自动生成。无编译浏览文件。当自动完成功能出问题时可以删除此文件。编译工程后会自动生成。

 

<think>我们之前讨论的是在MFC中通过消息传递机制实现视图切换。在消息处理函数中,我们创建了新的视图对象。现在,问题聚焦在:这个新创建的视图是否是一个新的视图? 回答: 在之前的实现中,我们通过消息传递机制切换视图时,会动态创建新的视图对象。这个新视图对象可以是已有的视图,也可以是新定义的视图。关键在于我们在切换时指定的运行时(CRuntimeClass*)。 解释: 1. 视图的定义:在MFC中,视图通常是从CView或其派生(如CFormView、CListView等)派生的。这些支持动态创建(使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏)。 2. 视图切换过程: - 当需要切换视图时,我们调用SwitchView函数,并传入目标视图的CRuntimeClass指针(例如RUNTIME_CLASS(CNewRightView))。 - 在消息处理函数OnViewSwitch中,我们使用传入的CRuntimeClass来动态创建该的对象(使用CreateObject方法)。 - 然后,我们创建视图窗口,并将其显示在分割窗口的右 pane 中。 3. 新视图: - 如果传入的CRuntimeClass指向一个之前未使用过的视图(例如新创建的CNewRightView),那么这就是一个新创建的视图实例。 - 如果传入的是已经存在的视图(如初始的CInitialRightView),那么我们会创建该的另一个实例(除非我们使用视图缓存,复用已有实例)。 4. 视图的生命周期: - 在切换视图时,我们会销毁当前的右视图(如果存在),然后创建新的视图对象。因此,每次切换都会创建一个新的视图对象(除非使用缓存)。 - 新创建的视图对象与文档关联(通过CCreateContext设置文档指针),因此可以访问文档数据。 示例代码片段(来自之前的实现): ```cpp // 在OnViewSwitch函数中: // 创建新视图 CView* pNewView = (CView*)pParam->pViewClass->CreateObject(); if (!pNewView) return 0; // 创建视图窗口 if (!pNewView->Create(NULL, NULL, WS_CHILD | WS_VISIBLE, rect, &m_wndSplitter, 0, &context)) { delete pNewView; return 0; } ``` 5. 视图的设计: - 每个视图负责特定的显示和交互功能。 - 例如,初始右视图(CInitialRightView)可能包含一个按钮,点击后切换到新视图(CNewRightView)。 - 新视图(CNewRightView)则可能包含同的控件和功能。 因此,在切换视图时,我们创建的是指定视图的一个新实例(对象),而是定义一个新的视图。视图本身是在代码中预先定义好的。 但是,如果我们需要一个新的视图型(例如显示图表的视图),那么我们就需要先创建一个新的视图(如CChartView),然后就可以在切换时使用这个新。 创建新视图的步骤: 1. 使用类向导添加新的MFC,继承自CView(或其它视图基)。 2. 在声明中使用DECLARE_DYNCREATE宏。 3. 在实现中使用IMPLEMENT_DYNCREATE宏。 4. 重写必要的虚函数(如OnInitialUpdate, OnDraw等)。 5. 设计视图的界面(如果是CFormView,则设计对话框资源)。 这样,我们就可以在切换视图时使用这个新视图。 总结: 在消息传递机制中切换的视图可以是: - 已经存在的视图(如初始视图)的新实例 - 也可以是新定义的视图(如CChartView)的实例 所以,问题中的“新创建的视图”实际上是指新创建的视图对象,它属于一个已有的视图(可能是新编写的,也可能是旧的)。视图的定义是在编码阶段完成的,而视图对象是在运行时动态创建的。 相关问题: 根据问题,用户可能关心如何定义新的视图,以及如何在切换时使用它们。 §§相关问题§§: 1. 如何在MFC中创建一个新的视图? 2. 如何使一个视图支持动态创建? 3. 在视图切换时,如何传递参数给新视图? 4. 如何管理多个视图共享的文档数据?</think># 视图的创建与使用详解 在MFC应用中,"新创建的视图"指的是在运行时动态创建的视图对象,而是在编译时静态定义的。让我们深入探讨这个概念及其实现方式。 ## 视图的创建机制 ### 1. 视图的定义 视图是在编译时定义的,继承自`CView`或其派生: ```cpp // 初始右视图 (编译时定义) class CInitialRightView : public CFormView { DECLARE_DYNCREATE(CInitialRightView) public: CInitialRightView(); virtual ~CInitialRightView(); // 按钮处理函数 afx_msg void OnBtnShowNewView(); DECLARE_MESSAGE_MAP() }; // 新视图 (编译时定义) class CNewRightView : public CFormView { DECLARE_DYNCREATE(CNewRightView) public: CNewRightView(); virtual ~CNewRightView(); // 返回按钮处理 afx_msg void OnBtnReturn(); DECLARE_MESSAGE_MAP() }; ``` ### 2. 视图对象的创建 在运行时动态创建视图对象: ```cpp // 在框架中创建视图对象 LRESULT CMainFrame::OnViewSwitch(WPARAM wParam, LPARAM lParam) { ViewSwitchParam* pParam = reinterpret_cast<ViewSwitchParam*>(lParam); // 使用运行时信息创建视图对象 CView* pNewView = (CView*)pParam->pViewClass->CreateObject(); // 创建视图窗口 pNewView->Create( NULL, // 名 NULL, // 窗口名 WS_CHILD | WS_VISIBLE, // 样式 rect, // 位置和大小 &m_wndSplitter, // 父窗口 0, // 子窗口ID &context // 创建上下文 ); // 初始化视图 pNewView->OnInitialUpdate(); } ``` ## 视图对象的动态创建过程 ### 1. 运行时系统 (CRuntimeClass) MFC使用运行时系统实现动态创建: ```cpp // 视图声明 class CNewRightView : public CFormView { DECLARE_DYNCREATE(CNewRightView) // 声明动态创建支持 // ... }; // 视图实现 IMPLEMENT_DYNCREATE(CNewRightView, CFormView) // 实现动态创建 // 动态创建机制实现 CObject* CRuntimeClass::CreateObject() { if (m_pfnCreateObject == NULL) { TRACE1("Error: Trying to create object which is not DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n", m_lpszClassName); return NULL; } return (*m_pfnCreateObject)(); // 调用创建函数 } ``` ### 2. 视图创建流程 1. **获取运行时信息**: ```cpp CRuntimeClass* pClass = RUNTIME_CLASS(CNewRightView); ``` 2. **创建对象实例**: ```cpp CObject* pObj = pClass->CreateObject(); ``` 3. **创建窗口**: ```cpp pView->Create(...); // 创建实际窗口 ``` 4. **初始化视图**: ```cpp pView->OnInitialUpdate(); // 初始化视图 ``` ## 视图生命周期管理 ### 1. 视图创建 ```cpp // 创建视图的完整过程 CView* CreateViewInstance(CRuntimeClass* pViewClass, CWnd* pParent, CCreateContext* pContext) { // 创建视图对象 CView* pView = (CView*)pViewClass->CreateObject(); if (!pView) return nullptr; // 创建视图窗口 if (!pView->Create(NULL, NULL, WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), pParent, AFX_IDW_PANE_FIRST, pContext)) { delete pView; return nullptr; } // 初始化视图 pView->OnInitialUpdate(); return pView; } ``` ### 2. 视图销毁 ```cpp // 安全销毁视图 void DestroyViewInstance(CView* pView) { if (pView) { // 保存状态(可选) SaveViewState(pView); // 销毁窗口 pView->DestroyWindow(); // 删除对象 delete pView; } } ``` ## 视图状态管理 ### 1. 视图状态保存/恢复 ```cpp // 视图状态管理 class CViewStateManager { public: void SaveState(CView* pView, const CString& state) { CString className = typeid(*pView).name(); m_stateMap[className] = state; } CString RestoreState(CView* pView) { CString className = typeid(*pView).name(); auto it = m_stateMap.find(className); return (it != m_stateMap.end()) ? it->second : CString(); } private: std::map<CString, CString> m_stateMap; }; // 在视图切换时使用 void SwitchView(CRuntimeClass* pNewClass) { // 保存当前视图状态 CString currentState = GetCurrentViewState(); m_stateManager.SaveState(m_pCurrentView, currentState); // 创建新视图 CView* pNewView = CreateViewInstance(pNewClass, ...); // 恢复新视图状态 CString savedState = m_stateManager.RestoreState(pNewView); if (!savedState.IsEmpty()) { RestoreViewState(pNewView, savedState); } } ``` ### 2. 具体视图状态处理 ```cpp // 在具体视图中实现状态保存/恢复 class CDataGridView : public CView { public: CString GetState() const { CString state; // 保存列宽、排序等状态 state.Format(_T("%d,%d,%d"), m_sortColumn, m_sortAscending, m_pageSize); return state; } void RestoreState(LPCTSTR lpszState) { if (lpszState && *lpszState) { int sortCol, sortAsc, pageSize; if (_stscanf_s(lpszState, _T("%d,%d,%d"), &sortCol, &sortAsc, &pageSize) == 3) { m_sortColumn = sortCol; m_sortAscending = (sortAsc != 0); m_pageSize = pageSize; } } } }; ``` ## 高级视图管理技术 ### 1. 视图缓存 ```cpp class CViewManager { public: CView* GetView(CRuntimeClass* pViewClass) { // 查找缓存 auto it = m_viewCache.find(pViewClass); if (it != m_viewCache.end()) { return it->second; } // 创建新视图 CView* pView = CreateViewInstance(pViewClass, ...); if (pView) { m_viewCache[pViewClass] = pView; pView->ShowWindow(SW_HIDE); // 初始隐藏 } return pView; } void ShowView(CRuntimeClass* pViewClass) { CView* pView = GetView(pViewClass); if (pView) { // 隐藏所有视图 for (auto& pair : m_viewCache) { pair.second->ShowWindow(SW_HIDE); } // 显示目标视图 pView->ShowWindow(SW_SHOW); pView->SetFocus(); } } private: std::map<CRuntimeClass*, CView*> m_viewCache; }; ``` ### 2. 视图工厂模式 ```cpp // 视图工厂接口 class IViewFactory { public: virtual CView* CreateView(CWnd* pParent, CCreateContext* pContext) = 0; }; // 具体视图工厂 template <class T> class TViewFactory : public IViewFactory { public: CView* CreateView(CWnd* pParent, CCreateContext* pContext) override { CView* pView = new T; CRect rect; pParent->GetClientRect(rect); if (pView->Create(NULL, NULL, WS_CHILD, rect, pParent, AFX_IDW_PANE_FIRST, pContext)) { pView->OnInitialUpdate(); return pView; } delete pView; return nullptr; } }; // 视图工厂注册 class CViewFactoryRegistry { public: template <class T> void RegisterView(LPCTSTR lpszName) { m_factories[lpszName] = std::make_unique<TViewFactory<T>>(); } CView* CreateView(LPCTSTR lpszName, CWnd* pParent, CCreateContext* pContext) { auto it = m_factories.find(lpszName); if (it != m_factories.end()) { return it->second->CreateView(pParent, pContext); } return nullptr; } private: std::map<CString, std::unique_ptr<IViewFactory>> m_factories; }; ``` ## 视图与文档的交互 ### 1. 文档更新通知 ```cpp // 文档 class CMyDocument : public CDocument { public: void UpdateData() { // 更新数据... UpdateAllViews(NULL); // 通知所有关联视图 } }; // 视图 void CMyView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { switch (lHint) { case UPDATE_DATA: // 处理数据更新 RefreshDisplay(); break; case UPDATE_LAYOUT: // 处理布局更新 AdjustLayout(); break; } } ``` ### 2. 视图特定更新 ```cpp // 只更新特定视图 void CMyDocument::UpdateSpecificView(CView* pTargetView) { POSITION pos = GetFirstViewPosition(); while (CView* pView = GetNextView(pos)) { if (pView == pTargetView) { pView->OnUpdate(NULL, UPDATE_SPECIFIC, NULL); break; } } } ``` ## 总结:视图的创建与使用 1. **视图 vs 视图对象**: - **视图**:在编译时定义的(如 `CInitialRightView`) - **视图对象**:在运行时动态创建的实例 2. **创建过程**: - 使用 `DECLARE_DYNCREATE` 和 `IMPLEMENT_DYNCREATE` 宏支持动态创建 - 通过 `CRuntimeClass::CreateObject()` 创建对象实例 - 调用 `Create()` 方法创建实际窗口 - 调用 `OnInitialUpdate()` 初始化视图 3. **生命周期管理**: - 创建:动态分配内存并创建窗口 - 销毁:调用 `DestroyWindow()` 并删除对象 - 缓存:可选地缓存视图对象以提高性能 4. **状态管理**: - 在切换视图时保存/恢复视图状态 - 使用序列化或自定义格式保存状态 5. **高级技术**: - 视图缓存减少创建开销 - 工厂模式统一创建接口 - 文档-视图通信机制 在MFC应用中,视图切换时创建的是**视图对象的新实例**,这些实例属于预先定义的视图。每次切换可能会创建新的对象实例(除非使用缓存),但这些实例都属于同一个编译时定义的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值