MFC

여러개의 뷰를 만들고 뷰 전환하기 - 참조....

디버그정 2008. 9. 4. 17:09

여러개의 뷰를 만들고 뷰 전환하기

/********************************************************************************/

/* 뷰 전환 경우 1(뷰가 겹쳐있을때)

/********************************************************************************/

┏━━━━━━━┳━━━━━━━━━━━┓

┃                     ┃                                 ┃

┃                     ┃                                 ┃

┃                     ┃                                 ┃

┃       폼뷰        ┃     뷰(CBaseView)      ┃        새로만드는 뷰(CTestView)

┃(CMenuView) ┃                                 ┃

┃                     ┃                                 ┃

┃                     ┃                                 ┃

┗━━━━━━━┻━━━━━━━━━━━┛

<위와 같이 폼뷰가 있고, 기본 베이스 뷰가 오른쪽에 위치하고 새로만드는 뷰까지 총 세개의 뷰가 있다>


1. 폼뷰 생성( 라디오 버튼을 두개 만든다. CMenuView )


2. 새로운 뷰 생성( CTestView )


3. 메뉴에 뷰를 전환하기 위해 두개의 메뉴 추가


4. 메인프레임의 OnCreateClient에서

   if (!m_wndSplitter.CreateStatic(this, 1, 2))
   {
       TRACE0("Fail to create splitter window.\n");
       return FALSE;    // failed to create
   }

  

   m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CMenuView), CSize(100, 100), pContext);
   m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CBaseView), CSize(100, 100), pContext);


   m_pTestView = new CTestView;
   m_pTestView->Create( NULL, NULL, 0, CRect(0,0,0,0), &m_wndSplitter, 10, pContext );


  

//뷰의 포인터 객체 초기화 방법 1////////////////////////////////////////////////////////

   m_pMenuView = (CMenuView *)m_wndSplitter.GetPane(0, 0);
   m_pBaseView = (CMFC0608View *)m_wndSplitter.GetPane(0, 1);  

//////////////////////////////////////////////////////////////////////////////////////

  

   SetActiveView( (CView*)m_wndSplitter.GetPane(0, 0) );
 
   return TRUE;



//베이스뷰 포인터 객체 초기화 방법 2///////////////////////////////////

//베이스뷰의 OnCreate에서

CMainFrame *pFrame = (CMainFrame *)GetParentFrame();

pFrame->m_pBaseView = this;

 

//메뉴뷰의 OnCreate에서

CMainFrame *pFrame = (CMainFrame *)GetParentFrame();

pFrame->m_pMenuView = this;

/////////////////////////////////////////////////////////////////////


//※위의 두가지의 베이스뷰 포인터 객체 초기화방법중 한가지를 쓰면됨

 

5. 메뉴에서 베이스뷰 메뉴와 테스트뷰를 클릭했을경우 뷰 전환

void CMainFrame::OnBaseview()   //베이스뷰 클릭했을때
{
    if( !m_bChange ) return; //메인프레임의 생성자에서 FALSE로 초기화


    CView *pOldView, *pNewView;
 
    pOldView = m_pTestView;
    pNewView = m_pBaseView;


    pNewView->ShowWindow( SW_SHOW );
    pOldView->ShowWindow( SW_HIDE );


    pOldView->SetDlgCtrlID( pNewView->GetDlgCtrlID() );
    pNewView->SetDlgCtrlID( m_wndSplitter.IdFromRowCol(0, 1) );


    m_wndSplitter.RecalcLayout();


    CButton* pButton = (CButton *)m_pMenuView->GetDlgItem( IDC_RADIO1 );
    CButton* pButton2 = (CButton *)m_pMenuView->GetDlgItem( IDC_RADIO2 );
    pButton->SetCheck(1);
    pButton2->SetCheck(0);


    m_pMenuView->UpdateData(FALSE);  
}


void CMainFrame::OnTestview()   //테스트뷰 클릭했을때

{
    CView *pOldView, *pNewView;
 
    pOldView = m_pBaseView;
    pNewView = m_pTestView;

 

    pNewView->ShowWindow( SW_SHOW );
    pOldView->ShowWindow( SW_HIDE );

 

    pOldView->SetDlgCtrlID( pNewView->GetDlgCtrlID() );
    pNewView->SetDlgCtrlID( m_wndSplitter.IdFromRowCol(0, 1) );


    m_wndSplitter.RecalcLayout();


    CButton* pButton = (CButton *)m_pMenuView->GetDlgItem( IDC_RADIO1 );
    CButton* pButton2 = (CButton *)m_pMenuView->GetDlgItem( IDC_RADIO2 );

    pButton->SetCheck(0);
    pButton2->SetCheck(1);


    m_pMenuView->UpdateData(FALSE);  


    m_bChange = TRUE;
}


6. CTestView의 생성자와 소멸자, 메인프레임의 OnBaseview와 OnTestview를 public속성으로 변경

//메인프레임 해더에서//////////////

public:
    CMFC0608View *m_pBaseView;
    CTestView *m_pTestView;
    CMenuView *m_pMenuView;


    afx_msg void OnBaseview();
    afx_msg void OnTestview();

//////////////////////////////////

 

//테스트뷰 해더에서//////////////

public:
    CTestView();          

    virtual ~CTestView();

//////////////////////////////////

7. 메뉴뷰에서 라디오 버튼을 클릭했을때 뷰 전환

void CMenuView::OnRadio1()
{
    CMainFrame *pFrm = (CMainFrame *)AfxGetMainWnd();

    pFrm->OnBaseview();
 
}


void CMenuView::OnRadio2()
{
    CMainFrame *pFrm = (CMainFrame *)AfxGetMainWnd();

    pFrm->OnTestview();
}




/********************************************************************************/

/* 뷰 전환 경우 2(스플리터로 뷰가 나눠져 있을때)

/********************************************************************************/

┏━━━━━━━┳━━━━━━━┳━━━━━━━┓

┃                       ┃                      ┃                       ┃                

┃                       ┃                      ┃     CView2       ┃

┃                       ┃                      ┃                       ┃

┃                       ┃  CBaseView    ┣━━━━━━━┫

┃  CMenuView    ┃                      ┃                       ┃

┃                       ┃                      ┃      CView3      ┃

┃                       ┃                      ┃                       ┃

┃                       ┣━━━━━━━┻━━━━━━━┫

┃                       ┃                                                 ┃

┃                       ┃               CView1                       ┃

┃                       ┃                                                 ┃

┗━━━━━━━┻━━━━━━━━━━━━━━━┛

                              <레이아웃>

1. 메인프레임 해더에서

 CSplitterWnd m_wndSplitter;
 CSplitterWnd m_wndSplitter2;
 CSplitterWnd m_wndSplitter3;
 CSplitterWnd m_wndSplitter4;

 

 CMenuView* m_pMenuView;
 CMFC0609View* m_pBaseView;
 CView1* m_pView1;
 CView2* m_pView2;
 CView3* m_pView3;

 

 BOOL m_bView;  //생성자에서 FALSE로 초기화

 

2. 메인프레임의 OnCreateClient에서

m_wndSplitter.CreateStatic(this, 1, 2)

m_wndSplitter2.CreateStatic(&m_wndSplitter, 2, 1, WS_CHILD | WS_VISIBLE | WS_BORDER,
                                        m_wndSplitter.IdFromRowCol(0, 1))
m_wndSplitter3.CreateStatic(&m_wndSplitter2, 1, 2, WS_CHILD | WS_VISIBLE | WS_BORDER,
                                        m_wndSplitter2.IdFromRowCol(0, 0))
m_wndSplitter4.CreateStatic(&m_wndSplitter3, 2, 1, WS_CHILD | WS_VISIBLE | WS_BORDER,
                                        m_wndSplitter3.IdFromRowCol(0, 1))
CRect rt;

GetClientRect( &rt );
 
m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CMenuView), CSize(1, 1), pContext); //폼뷰
m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(CView1), CSize(1, 1), pContext);
m_wndSplitter3.CreateView(0, 0, RUNTIME_CLASS(CMFC0609View), CSize(1, 1), pContext);
m_wndSplitter4.CreateView(0, 0, RUNTIME_CLASS(CView2), CSize(1, 1), pContext);
m_wndSplitter4.CreateView(1, 0, RUNTIME_CLASS(CView3), CSize(1, 1), pContext);
 
SetActiveView( (CView*)m_wndSplitter.GetPane(0, 0) ); //처음 포커스를 줄 뷰를 선택한다.

 

//뷰 클래스 포인터 객체 초기화
m_pMenuView = (CMenuView *)m_wndSplitter.GetPane( 0, 0 );
m_pBaseView = (CMFC0609View *)m_wndSplitter2.GetPane( 1, 0 );
m_pView1 = (CView1 *)m_wndSplitter3.GetPane( 0, 0 );
m_pView2 = (CView2 *)m_wndSplitter4.GetPane( 0, 0 );
m_pView3 = (CView3 *)m_wndSplitter4.GetPane( 1, 0 );

 

m_bView = TRUE;
 
return TRUE;


3. 메뉴설정( 원래사이즈, 베이스뷰, view1, view2, view3, 폼뷰 )

void CMainFrame::OnResize()  //원래 사이즈로
{
    CRect rt;

    GetClientRect( &rt );

    m_wndSplitter.SetColumnInfo(0, rt.Width() / 3, 10);
    m_wndSplitter2.SetRowInfo(0, rt.Height() / 3 * 2, 10);
    m_wndSplitter3.SetColumnInfo(0, rt.Width() / 3, 10);
    m_wndSplitter4.SetRowInfo(0, rt.Height() / 3, 10);


    m_wndSplitter.RecalcLayout();
    m_wndSplitter2.RecalcLayout();
    m_wndSplitter3.RecalcLayout();
    m_wndSplitter4.RecalcLayout();
}


void CMainFrame::OnView1() 
{
    CRect rt;

    GetClientRect( &rt );
 
    m_wndSplitter.SetColumnInfo(0, 0, 1);
    m_wndSplitter2.SetRowInfo(0, 0, 1);
 
    m_wndSplitter.RecalcLayout();
    m_wndSplitter2.RecalcLayout();  
}


void CMainFrame::OnView2()
{
    CRect rt;

    GetClientRect( &rt );
 
    m_wndSplitter.SetColumnInfo(0, 0, 1);
    m_wndSplitter2.SetRowInfo(0, rt.Height(), 1);
    m_wndSplitter3.SetColumnInfo(0, 0, 1);
    m_wndSplitter4.SetRowInfo(0, rt.Height(), 1);
 
    m_wndSplitter.RecalcLayout();
    m_wndSplitter2.RecalcLayout();
    m_wndSplitter3.RecalcLayout();
    m_wndSplitter4.RecalcLayout();
}


void CMainFrame::OnView3()
{
    CRect rt;

    GetClientRect( &rt );
 
    m_wndSplitter.SetColumnInfo(0, 0, 1);
    m_wndSplitter2.SetRowInfo(0, rt.Height(), 1);
    m_wndSplitter3.SetColumnInfo(0, 0, 1);
    m_wndSplitter4.SetRowInfo(0, 0, 1);
 
    m_wndSplitter.RecalcLayout();
    m_wndSplitter2.RecalcLayout();
    m_wndSplitter3.RecalcLayout();
    m_wndSplitter4.RecalcLayout();  
}


void CMainFrame::OnFormview() 
{
    CRect rt;

    GetClientRect( &rt );
 
    m_wndSplitter.SetColumnInfo(0, rt.Width(), 1);
 
    m_wndSplitter.RecalcLayout();
}


void CMainFrame::OnBaseview()
{
    CRect rt;

    GetClientRect( &rt );
 
    m_wndSplitter.SetColumnInfo(0, 0, 1);
    m_wndSplitter2.SetRowInfo(0, rt.Height(), 1);
    m_wndSplitter3.SetColumnInfo(0, rt.Width(), 1);
 
    m_wndSplitter.RecalcLayout();
    m_wndSplitter2.RecalcLayout();
    m_wndSplitter3.RecalcLayout();
}


4. 메인프레임의 OnSize오버라이드

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
    if( !m_bView ) return;

    OnResize();
}