发现了一个教程,但是弄了半天都不知道为什么做错,大家帮忙一下,我发现我运行的时候有断言错误,在定义SwitchToView函数CView* pOldActiveView = (CView*)pFrame->GetActiveView();出错,还有一个是野指针的问题:OnInitDialog()函数
((CFrameWnd*)this)->SetActiveView(m_pView1);我就发现这个两个问题,不知道是我操作错了,还是什么,你们帮我看看,谢谢,原文如下:在MFC的SDI和MDI文档结构中能很方便的嵌入多视图,而有时候则要在对话框中嵌入多视图,下面是方法。
1.插入三个对话框
ID分别为IDD_VIEW1_FORM,IDD_VIEW2_FORM,IDD_VIEW3_FORM,把三个对话框的属性Style设为Child,Border设为None,映射CView1,CView2,CView3分别对应三个对话框,CView1,CView2,CView3都派生自CFormView。
2.在对话框中加入三个成员变量:
CView1 *m_pView1;
CView2 *m_pView2;
CView3 *m_pView3;
3.映射对话框WM_INITDIALOG消息,在OnInitDialog()函数中加入创建视图窗口的代码.
(注意一定要用(CView*)把三个成员变量的类型转换成CView*类型,不然调用的就是CFormView::Create,但是CFromView的Create是protected类型,不能调用)
//create view1
m_pView1 = new CView1;
ASSERT(m_pView1 != NULL);if (!((CView*)m_pView1)->Create(NULL, NULL, WS_CHILD,
   CRect(0, 0, 0, 0), this, NULL, NULL))
{
   AfxMessageBox(_T("Create view1 failed"));
   return TRUE;
}m_pView1->ShowWindow(SW_HIDE);
m_pView1->OnInitialUpdate();
//create view2
m_pView2 = new CView2;
ASSERT(m_pView2 != NULL);if (!((CView*)m_pView2)->Create(NULL, NULL, WS_CHILD,
   CRect(0, 0, 0, 0), this, NULL, NULL))
{
   AfxMessageBox(_T("Create view2 failed"));
   return TRUE; 
}m_pView2->ShowWindow(SW_HIDE);
m_pView2->OnInitialUpdate();
//create view3
m_pView3 = new CView3;
ASSERT(m_pView3 != NULL);if (!((CView*)m_pView3)->Create(NULL, NULL, WS_CHILD,
   CRect(0, 0, 0, 0), this, NULL, NULL))
{
   AfxMessageBox(_T("Create view3 failed"));
   return TRUE; 
}m_pView3->ShowWindow(SW_HIDE);
m_pView3->OnInitialUpdate();//move view in the dialog
CRect rect;
GetWindowRect(&rect);
ScreenToClient(rect);
rect.DeflateRect(200, 0, 0, 0);
m_pView1->MoveWindow(&rect);
m_pView2->MoveWindow(&rect);
m_pView3->MoveWindow(&rect);((CFrameWnd*)this)->SetActiveView(m_pView1);
m_pView1->ShowWindow(SW_SHOW);
m_pView1->SetDlgCtrlID(AFX_IDW_PANE_FIRST); ...... 在对话框中按顺序加入三个radio box,在第一个radio box中勾上group选项(三个radio box 靠左边放,注意不要被嵌入的视图覆盖住。。在映射按钮消息函数中加入SwitchToView函数。(SwitchToView用来切换视图)
void Cxxxxx::OnRadio1()
{
SwitchToView(IDD_VIEW1_FORM);
}void Cxxxxx::OnRadio2()
{
SwitchToView(IDD_VIEW2_FORM);
}void Cxxxxx::OnRadio3()
{
SwitchToView(IDD_VIEW3_FORM);
}SwitchToView的函数定义为:
void Cxxxxx::SwitchToView(UINT uViewID)
{
//the following statement is important!!!
CFrameWnd *pFrame = (CFrameWnd*)this;//only for debug
ASSERT_VALID(pFrame);
CView *pNewActiveView = NULL;
CView* pOldActiveView = (CView*)pFrame->GetActiveView();switch(uViewID)
{
case IDD_VIEW1_FORM: 
   pNewActiveView = m_pView1;
   break;
case IDD_VIEW2_FORM: 
   pNewActiveView = m_pView2;
   break;
case IDD_VIEW3_FORM: 
   pNewActiveView = m_pView3;
   break;
default:
   AfxMessageBox(_T("invalid view id"));
   return;
}ASSERT(pOldActiveView!=NULL && pNewActiveView!=NULL);if (pNewActiveView == pOldActiveView)
   return;pNewActiveView->ShowWindow(SW_SHOW);
pOldActiveView->ShowWindow(SW_HIDE);
pFrame->SetActiveView(pNewActiveView);if (pOldActiveView -> IsKindOf(RUNTIME_CLASS(CView1)))
   pOldActiveView -> SetDlgCtrlID(IDD_VIEW1_FORM);
else if(pOldActiveView -> IsKindOf(RUNTIME_CLASS(CView2)))
   pOldActiveView -> SetDlgCtrlID(IDD_VIEW2_FORM);
else if (pOldActiveView -> IsKindOf(RUNTIME_CLASS(CView3)))
   pOldActiveView -> SetDlgCtrlID(IDD_VIEW3_FORM);
//set the identity of current active view
pNewActiveView -> SetDlgCtrlID(AFX_IDW_PANE_FIRST);
}

解决方案 »

  1.   

    对话框中可以很方便的嵌入frame,frame挂多个view也不难。
      

  2.   

    CFrameWnd 和CDialog都是从Cwnd派生出来的
    不能CFrameWnd *pFrame = (CFrameWnd*)this(this指针代表对话框)
    因为他们属于不同的类,Cwnd* p=(Cwnd*) this;这样是可以的,因为CDialog是从
    Cwnd中派生的!学编程的时候,不要人家怎么写,你也跟着怎么写,要理解人家的意图!根据自己的需要去做!其实你完全没必要做转换操作,直接保存一个CView * m_pNewActiveView
    做全局变量,不就可以了吗?
      

  3.   

    CFrameWnd *pFrame = (CFrameWnd*)this  原文作者这样子做的意图是利用CFrameWnd类的GetActiveView()函数来获取当前活动窗口,用SetActiveView()激活新视图,应该是这样子吧……
      

  4.   


    俺的程序从网上抄的,这样在dialog中挂了一个frameint
    CCommonScriptDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CDialog::OnCreate(lpCreateStruct) == -1)
    {
    return -1;
    }

    // Because the CFRameWnd needs a window class, we will create
    // a new one. I just copied the sample from MSDN Help.
    // When using it in your project, you may keep CS_VREDRAW and
    // CS_HREDRAW and then throw the other three parameters.
    CString strMyClass = AfxRegisterWndClass( CS_VREDRAW |
    CS_HREDRAW,
    ::LoadCursor( NULL, IDC_ARROW ),
    ( HBRUSH )::GetStockObject( WHITE_BRUSH ),
    ::LoadIcon( NULL, IDI_APPLICATION ) ); // Create the frame window with "this" as the parent
    m_pFrame = new CCommonScriptFrame();
    m_pFrame->SetID( IDR_TOOLBAR_COMMON_SCRIPT_CN, IDR_TOOLBAR_COMMON_SCRIPT_EN ); m_pFrame->Create( strMyClass, _T( "Common Script Tool View" ) , WS_CHILD,
    CRect( 0, 0, 1, 1 ), this );
    //m_pFrame->ShowWindow( SW_SHOW );
    m_pFrame->MoveWindow( 0, 0, 300, 300 ); return 0;
    }
      

  5.   

    int CConnectScheduleFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
    if (CDialogFrame::OnCreate(lpCreateStruct) == -1)
    return -1;

    // TODO: Add your specialized creation code here
    CCreateContext ccc;
    ccc.m_pNewViewClass   = RUNTIME_CLASS( CConnect_Spy_View );
    ccc.m_pCurrentDoc     = NULL;
    ccc.m_pNewDocTemplate = NULL;
    ccc.m_pLastView       = NULL;
    ccc.m_pCurrentFrame   = this; // Because the CFRameWnd needs a window class, we will create
    // a new one. I just copied the sample from MSDN Help.
    // When using it in your project, you may keep CS_VREDRAW and
    // CS_HREDRAW and then throw the other three parameters.
    //CString strMyClass = AfxRegisterWndClass( CS_VREDRAW |
    // CS_HREDRAW,
    // ::LoadCursor( NULL, IDC_ARROW ),
    // ( HBRUSH )::GetStockObject( WHITE_BRUSH ),
    // ::LoadIcon( NULL, IDI_APPLICATION ) ); m_pView = ( CConnect_Spy_View * )( this->CreateView( &ccc ) );
    ::SendMessage( m_pView->GetSafeHwnd(), WM_INITIALUPDATE, 0, 0 ); this->SetActiveView( ( CView * )m_pView );
    return 0;
    }这样又在frame中加载了一个view,这里是formview,这个view中你想加嵌套再加载一个frame也行,分隔成多个view也行,加载toolbar,状态条等都行。
      

  6.   

    LZ说问题出在SwitchToView这个函数里,我是新手,不太懂原理,做的时候没用这个函数,把OnRadio()函数
    void Cxxxxx::OnRadio1()
    {
    SwitchToView(IDD_VIEW1_FORM);
    }void Cxxxxx::OnRadio2()
    {
    SwitchToView(IDD_VIEW2_FORM);
    }void Cxxxxx::OnRadio3()
    {
    SwitchToView(IDD_VIEW3_FORM);
    }改成
    void CXXX::OnRadio1() 
    {
    m_pView1->ShowWindow(SW_SHOW);
    m_pView1->OnInitialUpdate();
    }void CXXX::OnRadio2() 
    {
    m_pView2->ShowWindow(SW_SHOW);
    m_pView2->OnInitialUpdate();
    }void CXXX::OnRadio3() 
    {
    m_pView3->ShowWindow(SW_SHOW);
    m_pView3->OnInitialUpdate();
    }程序就可以运行了。
      

  7.   

    什么地方有这方面的书可以看,关于FORMVIEW对话框的这个,我也很乱
      

  8.   

    m_pView1 = new CView1;这一句老出错:
    error C2248: 'CView1::CView1' : cannot access protected member declared in class 'CView1'
            view1.h(20) : see declaration of 'CView1::CView1'
      

  9.   

    对话框嵌入视图类并不难,关键代码只有几句(测试成功的,我经常用):
    m_pView = new CMyView;
    if (!m_pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0,0,0,0), this, AFX_IDW_PANE_FIRST, NULL))
    {
    EndDialog(IDABORT);
    }
    CMyDoc* pDoc = new CMyDoc;//不需要DOC类,注释掉
    pDoc->AddView(m_pView);//不需要DOC类,注释掉
    m_pView->SendMessage(WM_INITIALUPDATE, 0, 0);
     
    不要用SetActiveView(),因为是CFrameWnd的函数,用CDialog盗用这个函数,是会报错的。
    切换时只需显示隐藏相应的对象就行了。
      

  10.   

    另外要用new,必须把构造和析构函数放到public里
      

  11.   

    http://www.vckbase.com/english/code/splitter/cxysplitter.shtml.htm