MFC如何为同doc的多个view制作选项卡

2024-12-25 07:12:21
推荐回答(1个)
回答1:

不用纠结在“选项卡”上,反正楼主的意思就是能有一种供用户选择不同VIEW的办法。菜单也可以,工具栏也可以,快捷键等都可以,无非是个交互方式而已。

楼主应该做过动态控件吧,就是好比在一个对话框中,原本只有一个按钮,点击一下对话框的菜单后,又会显示一个新的按钮,然后再点击这个菜单,原来的两个按钮就只剩一个了。

如果对以上的程序模式楼主很熟悉了,那一个文档对应多个VIEW的程序模式就容易实现多了。

应该把CFrameWnd想象成对话框,CView想象成按钮,它们的基本模式是差不多的。然后还要再融入一些SDI特有的属性,就可以了。

首先必须明确,点击了菜单(也可以是楼主说的选项卡)后,由哪个类负责相应这条命令。一般都是由CFrameWnd来维护的,然后必须明确CView必须和哪个CDocument建立对应关系,或许会认为对于SDI而言应该只有一个CDocument,其实SDI是指只有一个文档模板,即CSingleDocTemplate,一个SDI可以有很多个文档,即一种类型的文档可以具有很多实例,形象点就是一个int类型可以有很多变量,如int i1, i2, i3。CDocument doc1, doc2等。同一类型的所有文档都由一个文档模板来管理。因此在创建新VIEW的时候,楼主要考虑清楚要关联的是doc1, doc2还是doc3。

CView就像对话框中的按钮一样,应该为他分配一个ID,对于SDI而言,当前活动的CView的ID一般是固定的等于AFX_IDW_PANE_FIRST,活动CView的ID不能随意赋值。

创建2个以上的CView要考虑的是:
当点击菜单后,被选择的那个CView是否已经有个窗口了,如果没有先创建CView的一个实例,然后用该实例调用窗口创建函数CreateWindow等。代码类似于:
CView1* CMainFrame::m_pView1;//CFrameWnd的一个指针成员变量
CView2* CMainFrame::m_pView2;
void CMainFrame::OnShowView1() {
if (NULL == m_pView1) {
m_pView1 = new CView1;
ASSERT(NULL != m_pView1);
m_pView1->Create(NULL, NULL, WS_BORDER, CRect(1, 1, 15, 15)/*窗口大小无所谓,因为后面必须修改它的大小*/, this, 123/*ID也无所谓,因为后面也要修改它*/, /*这个参数和文档有关,后面说明*/);
m_pView1->OnInitialUpdate();
}
...
}

好了CView第一次被调用所需做的工作就如上所示,和动态创建按钮是一样的。如果CView刚刚被创建或早已创建(类似于该菜单项已经被点击过好多次,不可能每次都要创建一个按钮,只是在第一次创建,当点击了CView2这个菜单项时,只是把CView1这个窗口给藏起来了,再点击CView1菜单项时,把CView2藏起来,显示CView1),对刚被创建的CView或被早已创建的CView进行显示的代码如下:
/*CFrameWnd类的成员函数*/SetActiveView(m_pView1);
m_pView1->ShowWindow(SW_SHOW);
m_pView1->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
最后一句是刚才在Create时提到的窗口大小无所谓,这里简单调用CFrameWnd成员函数就能将CView的大小进行合适调整:
RecalcLayout();

对于本来被显示的那个CView如view2应该对他进行隐藏,并且不能再占用AFX_IDW_PANE_FIRST 这个ID了。代码如下:
CView2* pView = GetActiveView();
pView->ShowWindow(SW_HIDE);
pView->SetDlgCtrlID(124);

还要做的一件事就是CView应该关联哪个文档,一般SDI只有一个文档实例,可以调用CFrameWnd成员函数GetActiveDocument()得到文档指针,然后和CView进行关联,这个关联一般都是在初次创建CView窗口时即上面提到的Create函数被调用的时候就可以进行关联的,代码如下:
CCreateContext context;
context.m_pCurrentDoc = GetActiveDocument();
m_pView1->Create(...,&context/*最后一个参数*/);

大致就是这样的要点了,其他还需要注意的是m_pView1是被new出来的,别忘了自己控制delete。 还要注意的是刚才所示代码是根据新手理解程序的逻辑安排代码先后顺序的,实际排列代码可能需要进行交叉的,如上面现有SetActiveView,再有GetActiveView,实际排列肯定是这样的:
pOldView = GetActiveView();
SetActiveView(pNewView);
pOldView->ShowWindow(SW_HIDE);
pNewView->ShowWindow(SW_SHOW);
...
以上的代码不是公式,实际会根据需要有很多组合方式,楼主需要根据自己的程序逻辑查看MSDN中关于各个类成员函数的介绍,要点如上!
----------------------------------------------
晕!

大过年的才有时间打这么多字!简单说下吧,首先你要看下CPropertySheet和CPropertyPage两个类的说明。然后在资源视图构造N个对话框,这N个对话框对应N个选项卡,然后为N个对话框添加N个类,基类不要选CDialog,选择CPropertyPage,接着为CPropertySheet的子类构造N个数据成员,这些成员的类型就是刚才对应N个对话框派生的CPropertyPage的子类,如PAGE1 m_page1, PAGE2 m_page2,在CPropertySheet的构造函数为这些PAGE依次调用AddPage。最后为VIEW的菜单构造响应函数:
MyPropertySheet sheet;
sheet.DoModal();就可以弹出选项卡了。
至于如何将选项卡的选择内容进行保存这个和对话框是一样的。另外的就是对话框的风格必须为:
1)NO BORDER
2)CHILD
3)NO VISIBLE

楼主的问题是个大问题,无法给出具体细节的,就好比一个根本没学过VC的人,问怎么写个VC程序,一般很难回答这样的问题的。:)

-----------------------------------------------------------
CFormView + 对话框资源 + tab control