50分!请问,怎么让Frame含有多个View可以切换?而且这些View没有最大最小关闭按钮,用户不能控制它显示。 50分!请问,怎么让Frame含有多个View可以切换,而且这些View没有最大最小关闭按钮,用户不能控制它显示。请提供稍微具体一点的实现方法!!谢谢!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 http://www.vckbase.com/document/viewdoc/?id=691 我想从CFrameWnd直接实现,我只需要切换 我是让你参考其创建View的方法,在CMainFrame中可以直接显示View,当然你应该建立SDI的工程。注意:可能切换View的时候会出问题! Windows程序一般分为以下几种风格:多文档、单文档、基于对话框的。Word一类多文档程序和计算器一类基于对话框的程序不在本文介绍之列。单文档又分为单视的和多视的。一般情况下,单文档仅需要单视就够了,如画笔等。但也有一些情况下,单文档需要多视支持,比如同时观察文档的不同部分,同时从不同的角度观察同一文档等。 在MFC的框架下,文档对象(CDocument)维持了一个保存其所有视的列表,并提供了增加与删除视的函数,以及当文档内容改变时通知其所有视的方法。通过多文档框架的窗口复制机制和单文档框架的分割窗口机制是实现单文档多视的主要方法。但这些标准方法在有的情况下并不够用,为此笔者摸索出另外两种实用的方法,在实践中使用效果良好。 二、三种标准的单文档与多视情况 1.视对象基于同一视类,每个视位于MDI的一个独立子文档框架中。 用户可以通过“窗口\新窗口”菜单,为同一文档的视再创建一个窗口,通过新创建的窗口,可以编辑和观察文档的另一部分,同一文档各个视图之间自动实现同步,用户修改一个视的内容,在另外的视中也自动更新。 MFC框架通过复制原来的子框架窗口和其中的视来实现上面的功能,并且是完全自动的。 2.视对象基于同一视类,所有视位于同一文档框架中。 分割窗口将单文档窗口的视区分割成几个独立的视,框架从同一视类创建多个视对象。Word的子窗口即属于这种类型。 3.视对象基于不同的视类,所有的视位于同一文档框架中。 多个视共享同一文档框架,但从不同的视类创建,每个视可以为文档提供不同的观察和编辑方法。比如一个视用图形观察文档,而另一个视用文本编辑文档中对象的属性。这种情况也适应于用不同的视来观察文档的不同部分。这种类型的实现方法是通过重载OnCreateClient函数实现。下面的例子实现了图中的分割窗口。 BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT,CCreateContext* pContext) { RECT rect; // 先分割为 1X2的形式 m_wndSplitter1.CreateStatic(this, 1, 2, WS_CHILD | WS_VISIBLE ); m_wndSplitter1.SetColumnInfo(0,300,0); // 设置第一列的宽度 // 将第一列进一步分割为 2X1的形式 m_wndSplitter2.CreateStatic( &m_wndSplitter1,2, 1, WS_CHILD | WS_VISIBLE, m_wndSplitter1.IdFromRowCol(0, 0)); // 创建各个视 m_wndSplitter1.CreateView(0, 1,RUNTIME_CLASS(CviewView1), CSize(0, 0), pContext); m_wndSplitter2.CreateView(0, 0,RUNTIME_CLASS(CviewView2), CSize(0, 0), pContext); m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(CviewView3), CSize(0, 0), pContext); ...... } 在实践中,笔者发现这三种方式有时都不适用。比如以下的两种情况:需要在不同的时间分别观察同一文档的不同部分,而文档分割成不同部分的数量较多,这样就不宜用分割窗口来实现,而需要在同一框架中切换不同的视;另一种情况可以说是上面提到的第三种情况和此处第一种情况的组合,即在单文档框架中包含有多个由分割窗口分割的区域,而某(或某些)分割区域中包含有多个不同的视,仅有其中的一个视显示出来。与第三种情况类似,其它分割区域中具有不同的视,但它们同时显示出来。因为在实现方法上有所不同,所以这里分为两种情况来讨论,这也是这篇文章要介绍的重点。 三、单文档单框架窗口中的多视 下面的例子演示了第一种情况下,具有两个视的简单实现方法。必需考虑如下的问题:非活动的视是否继续连接到文档。当视连接到文档时,它从文档接收OnUpdate通知消息,使其保持与文档内容同步。但这样做将增加计算机的开销,同时也会增加程序开发的任务。另一方法是当非活动的视重新变成活动时,再进行与文档的同步工作。例子中采用后一种方法。 BOOL CMainFrame::OnViewChange(UINT nCmdID) { CView* pViewAdd; CView* pViewRemove; CDocument* pDoc = GetActiveDocument(); UINT nCmdID; nCmdID = LOWORD(GetCurrentMessage()-〉wParam); if((nCmdID == ID_VIEW_VIEW1) && (m_currentView == 1)) return; if((nCmdID == ID_VIEW_VIEW2) && (m_currentView == 2)) return; if (nCmdID == ID_VIEW_VIEW2) { if (m_pView2 == NULL) { m_pView1 = GetActiveView(); m_pView2 = new CMyView2; m_pView2-〉Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, rectDefault, this, AFX_IDW_PANE_FIRST + 1, NULL); } pViewAdd = m_pView2; pViewRemove = m_pView1; m_currentView= 2; } else { pViewAdd = m_pView1; pViewRemove = m_pView2; m_currentView= 1; } // 将活动视的child id设置为AFX_IDW_PANE_FIRST // 将其它视设置为AFX_IDW_PANE_FIRST以外的值, // 这样当调用 CFrameWnd::RecalcLayout重新布局窗口时, // 才会得到正确的视 int nSwitchChildID = pViewAdd-〉GetDlgCtrlID(); pViewAdd-〉SetDlgCtrlID(AFX_IDW_PANE_FIRST); pViewRemove-〉SetDlgCtrlID(nSwitchChildID); // 显示活动视而隐藏非活动视 pViewAdd-〉ShowWindow(SW_SHOW); pViewRemove-〉ShowWindow(SW_HIDE); // 将新的活动视连接到文档,并断开原来的视与文档的连接 pDoc-〉AddView(pViewAdd); pDoc-〉RemoveView(pViewRemove); SetActiveView(pViewAdd); RecalcLayout(); } 四、单文档分割窗口中,某分割区的多视的实现 第二种情况下,窗口的分割与标准方法的第3种类似,这里不再重复。下面的函数用于切换某分割(第3种标准界面中,左上区域)区域中的视。 这里的实现方法是:先删除原来的视,然后在原分割区域创建一个新的视。 void CMainFrame::OnViewView1() { ChangeView(RUNTIME_CLASS(CviewView1)); ViewingView = ID_VIEW_VIEW1; } void CMainFrame::OnViewView2() { ChangeView(RUNTIME_CLASS(CviewView2)); ViewingView = ID_VIEW_VIEW2; } void CMainFrame::OnUpdateViewView1(CCmdUI* pCmdUI) { pCmdUI-〉SetCheck(ViewingView == ID_VIEW_VIEW1); } void CMainFrame::OnUpdateViewView2(CCmdUI* pCmdUI) { pCmdUI-〉SetCheck(ViewingView == ID_VIEW_VIEW2); } void CMainFrame::ChangeView(CRuntimeClass * pRTClass) { // 先删除原来的视 m_wndSplitter2.DeleteView(0,0); // 创建新的视 CCreateContext Context; Context.m_pNewViewClass = pRTClass; // 视类 Context.m_pCurrentDoc = GetActiveDocument(); // 与文档连接 m_wndSplitter2.CreateView(0,0, pRTClass,CSize(0,0),&Context); CView * pView = (CView *)m_wndSplitter2.GetPane(0,0); // 获取分割区域 pView-〉ShowWindow(SW_SHOW); pView-〉OnInitialUpdate(); SetActiveView(pView); m_wndSplitter2.SetRowInfo(0, 300, 20); // 设置宽度 ::SetWindowLong(pView-〉m_hWnd, GWL_ID, AFX_IDW_PANE_FIRST); m_wndSplitter2.RecalcLayout(); } 单文档多视的应用场合很多,可能还有各种不同的需要和实现方法,愿笔者的介绍能对您有所帮助。 看了个SYN Flood的源代码,为什么抓包抓不到呢? 橡皮筋类的应用问题!!!!!!!!!!!!!! 如何将CString的中文字符串,转成UTF-8字符集的char*字符串???? SDI中切换闪烁的问题 怎样才能 把鼠标锁定 在本窗体之内?? 求显示导入类的方法 MFC中使用CImage类显示的图像不正常 MFC动态曲线 紧急求救!在网络环境中,用VC开发的客户端程序使用ADO连接SQL SERVER总是不可靠,如何解决? 关于在状态栏第0格中,滚动字幕显示 AfxBeginThread问题, 要让编辑框响应回车输入,必须子类化?
用户可以通过“窗口\新窗口”菜单,为同一文档的视再创建一个窗口,通过新创建的窗口,可以编辑和观察文档的另一部分,同一文档各个视图之间自动实现同步,用户修改一个视的内容,在另外的视中也自动更新。 MFC框架通过复制原来的子框架窗口和其中的视来实现上面的功能,并且是完全自动的。
2.视对象基于同一视类,所有视位于同一文档框架中。
分割窗口将单文档窗口的视区分割成几个独立的视,框架从同一视类创建多个视对象。Word的子窗口即属于这种类型。
3.视对象基于不同的视类,所有的视位于同一文档框架中。
多个视共享同一文档框架,但从不同的视类创建,每个视可以为文档提供不同的观察和编辑方法。比如一个视用图形观察文档,而另一个视用文本编辑文档中对象的属性。这种情况也适应于用不同的视来观察文档的不同部分。这种类型的实现方法是通过重载OnCreateClient函数实现。下面的例子实现了图中的分割窗口。 BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT,CCreateContext* pContext) { RECT rect; // 先分割为 1X2的形式 m_wndSplitter1.CreateStatic(this, 1, 2, WS_CHILD | WS_VISIBLE ); m_wndSplitter1.SetColumnInfo(0,300,0); // 设置第一列的宽度 // 将第一列进一步分割为 2X1的形式 m_wndSplitter2.CreateStatic( &m_wndSplitter1,2, 1, WS_CHILD | WS_VISIBLE, m_wndSplitter1.IdFromRowCol(0, 0)); // 创建各个视 m_wndSplitter1.CreateView(0, 1,RUNTIME_CLASS(CviewView1), CSize(0, 0), pContext); m_wndSplitter2.CreateView(0, 0,RUNTIME_CLASS(CviewView2), CSize(0, 0), pContext); m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(CviewView3), CSize(0, 0), pContext); ...... } 在实践中,笔者发现这三种方式有时都不适用。比如以下的两种情况:需要在不同的时间分别观察同一文档的不同部分,而文档分割成不同部分的数量较多,这样就不宜用分割窗口来实现,而需要在同一框架中切换不同的视;另一种情况可以说是上面提到的第三种情况和此处第一种情况的组合,即在单文档框架中包含有多个由分割窗口分割的区域,而某(或某些)分割区域中包含有多个不同的视,仅有其中的一个视显示出来。与第三种情况类似,其它分割区域中具有不同的视,但它们同时显示出来。因为在实现方法上有所不同,所以这里分为两种情况来讨论,这也是这篇文章要介绍的重点。 三、单文档单框架窗口中的多视 下面的例子演示了第一种情况下,具有两个视的简单实现方法。必需考虑如下的问题:非活动的视是否继续连接到文档。当视连接到文档时,它从文档接收OnUpdate通知消息,使其保持与文档内容同步。但这样做将增加计算机的开销,同时也会增加程序开发的任务。另一方法是当非活动的视重新变成活动时,再进行与文档的同步工作。例子中采用后一种方法。 BOOL CMainFrame::OnViewChange(UINT nCmdID) { CView* pViewAdd; CView* pViewRemove; CDocument* pDoc = GetActiveDocument(); UINT nCmdID; nCmdID = LOWORD(GetCurrentMessage()-〉wParam); if((nCmdID == ID_VIEW_VIEW1) && (m_currentView == 1)) return; if((nCmdID == ID_VIEW_VIEW2) && (m_currentView == 2)) return; if (nCmdID == ID_VIEW_VIEW2) { if (m_pView2 == NULL) { m_pView1 = GetActiveView(); m_pView2 = new CMyView2; m_pView2-〉Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, rectDefault, this, AFX_IDW_PANE_FIRST + 1, NULL); } pViewAdd = m_pView2; pViewRemove = m_pView1; m_currentView= 2; } else { pViewAdd = m_pView1; pViewRemove = m_pView2; m_currentView= 1; } // 将活动视的child id设置为AFX_IDW_PANE_FIRST // 将其它视设置为AFX_IDW_PANE_FIRST以外的值, // 这样当调用 CFrameWnd::RecalcLayout重新布局窗口时, // 才会得到正确的视 int nSwitchChildID = pViewAdd-〉GetDlgCtrlID(); pViewAdd-〉SetDlgCtrlID(AFX_IDW_PANE_FIRST); pViewRemove-〉SetDlgCtrlID(nSwitchChildID); // 显示活动视而隐藏非活动视 pViewAdd-〉ShowWindow(SW_SHOW); pViewRemove-〉ShowWindow(SW_HIDE); // 将新的活动视连接到文档,并断开原来的视与文档的连接 pDoc-〉AddView(pViewAdd); pDoc-〉RemoveView(pViewRemove); SetActiveView(pViewAdd); RecalcLayout(); }
四、单文档分割窗口中,某分割区的多视的实现 第二种情况下,窗口的分割与标准方法的第3种类似,这里不再重复。下面的函数用于切换某分割(第3种标准界面中,左上区域)区域中的视。 这里的实现方法是:先删除原来的视,然后在原分割区域创建一个新的视。 void CMainFrame::OnViewView1() { ChangeView(RUNTIME_CLASS(CviewView1)); ViewingView = ID_VIEW_VIEW1; } void CMainFrame::OnViewView2() { ChangeView(RUNTIME_CLASS(CviewView2)); ViewingView = ID_VIEW_VIEW2; } void CMainFrame::OnUpdateViewView1(CCmdUI* pCmdUI) { pCmdUI-〉SetCheck(ViewingView == ID_VIEW_VIEW1); } void CMainFrame::OnUpdateViewView2(CCmdUI* pCmdUI) { pCmdUI-〉SetCheck(ViewingView == ID_VIEW_VIEW2); } void CMainFrame::ChangeView(CRuntimeClass * pRTClass) { // 先删除原来的视 m_wndSplitter2.DeleteView(0,0); // 创建新的视 CCreateContext Context; Context.m_pNewViewClass = pRTClass; // 视类 Context.m_pCurrentDoc = GetActiveDocument(); // 与文档连接 m_wndSplitter2.CreateView(0,0, pRTClass,CSize(0,0),&Context); CView * pView = (CView *)m_wndSplitter2.GetPane(0,0); // 获取分割区域 pView-〉ShowWindow(SW_SHOW); pView-〉OnInitialUpdate(); SetActiveView(pView); m_wndSplitter2.SetRowInfo(0, 300, 20); // 设置宽度 ::SetWindowLong(pView-〉m_hWnd, GWL_ID, AFX_IDW_PANE_FIRST); m_wndSplitter2.RecalcLayout(); } 单文档多视的应用场合很多,可能还有各种不同的需要和实现方法,愿笔者的介绍能对您有所帮助。