Switching views in splitter panes (SDI)

I add here the code that could be used to switch views in splitter panes. I usually make database applications, and I don't want that the document to be created/destroyed by the framework, so I create the document myself, and in document's constructor I set the m_bAutoDelete flag to FALSE. The CMainFrame class contains CSplitterWnd m_wndSplitter member.

The CMyApp class contains as public member a pointer to my document.

In this case I create a view (which happens to be a TreeView) in the first pane that I don't switch. In second pane you can switch as many views as you want. Just add view classes and create command handlers similar with OnView1, and UpdateUI like OnUpdateView1. The first view that will be in the second pane will be the view from the document template.

In InitInstance function of CMyApp you should have something like this:


CDocTemplate *pAmortDocTemplate = new CSingleDocTemplate(
					 IDR_MAINFRAME,
					 RUNTIME_CLASS(CMyDoc),
					 RUNTIME_CLASS(CMainFrame), // main SDI frame window
					 RUNTIME_CLASS(CView1)); //change the class with the view you want to be displayed as default
//you can extend this so the program saves the active view (not the view J , only information about which one was active), and you can
//restore the last one when the program will start again
AddDocTemplate(pAmortDocTemplate);


void CMainFrame::OnView1() 
{
	// TODO: Add your command handler code here
	CRect cr;
	GetClientRect(&cr);
	CSize paneSize1(3*cr.Width()/4, cr.Height());
	CCreateContext Context;
	Context.m_pNewViewClass=RUNTIME_CLASS(CView1);
	Context.m_pCurrentDoc=((CMyApp*)AfxGetApp())->m_pDoc;
	Context.m_pCurrentFrame=this;
	Context.m_pNewDocTemplate=Context.m_pCurrentDoc->GetDocTemplate();
	Context.m_pLastView=(CView*)m_wndSplitter.GetPane(0,0);
	m_wndSplitter.DeleteView(0, 1);
	m_wndSplitter.CreateView(0, 1,RUNTIME_CLASS(CView1),paneSize1, &Context);
	CView1 *pView=(CView1*)m_wndSplitter.GetPane(0,1);
	pView-GetParentFrame()->RecalcLayout();
	m_wndSplitter.RecalcLayout();
	pView->OnInitialUpdate(); 
	m_wndSplitter.SetActivePane(0,1);
}

//this one is only to gray out the menu item (and/or toolbar button) that corresponds to the active view
void CMainFrame::OnUpdateView1(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(!m_wndSplitter.GetPane(0,1)->IsKindOf( RUNTIME_CLASS(CView1))); 
}


BOOL CMainFrame::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, 
				DWORD dwStyle, const RECT& rect, 
				CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	// TODO: Add your specialized code here and/or call the base class
	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}


BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
	CRect cr;
	BOOL rc;
	if (!m_wndSplitter.CreateStatic(this,1,2)){
		TRACE0("Failed to create split bar ");
		return FALSE; // failed to create
	}
	GetClientRect(&cr);
	CSize paneSize(cr.Width()/4, cr.Height());
	CSize paneSize1(3*cr.Width()/4, cr.Height());
	((CMyApp*)AfxGetApp())->m_pDoc=(CMyDoc*)(pContext->m_pCurrentDoc);
	pContext->m_pCurrentFrame=this;
	rc=m_wndSplitter.CreateView(0, 1,pContext->m_pNewViewClass,paneSize1, pContext);
	if(!rc)return FALSE;
	pContext->m_pNewViewClass=RUNTIME_CLASS(CMyTree);
	pContext->m_pCurrentDoc=((CMyApp*)AfxGetApp())->m_pDoc;
	pContext->m_pCurrentFrame=this;
	rc=m_wndSplitter.CreateView(0,0,pContext->m_pNewViewClass,paneSize,pContext);
	m_wndSplitter.RecalcLayout();
	m_wndSplitter.SetActivePane(0,1);
	return rc;
}

Download demo project - 43.1 KB



Comments

  • Splitter Window

    Posted by Legacy on 05/10/2003 12:00am

    Originally posted by: sgz

    great

    Reply
  • Setting focus to a multi-paned view

    Posted by Legacy on 02/04/2003 12:00am

    Originally posted by: Paul Osborne

    Ok, I know how to switch the focus from one view to another, but I can't do that when the view has three different panes. I use the get parent function with the set pane and stuff, but when I do that it just sets it to the middle frame, that has three different panes in it. Is there a way to set it to a specific pane even if it is inside a nested splitter?

    ____________________
    ____________________
    | |
    | |
    | |
    | |
    ____________________
    ____________________

    i hope that looks right, my top and bottom frames are banners. The middle three frames are all part of ONE of the big frames panes and it is split into 3 panes. I want the middle pane to be focused whenever the user clicks either of the banners or either of the sides. How can I do this?

    Reply
  • Ya well can you make it change one view by clicking in the other view...well can ya :)

    Posted by Legacy on 11/06/2002 12:00am

    Originally posted by: gregg

    Forgive me for bothering you Mr Roman but I am working on something that is driving me nuts….short trip I know. But
    how would you change your view when you selected something in the other view. This could be a drawn entity and the other view would be a form view of the entities attributes. How would you notify the frame class that it needed to change the form view. Thanks.

    Reply
  • How to stop TAB?

    Posted by Legacy on 12/05/2000 12:00am

    Originally posted by: qsx

    When I use splitter ,I Set the left pane al  a CFormView,so I can place button in it ,but  I  don't want user to use TAB to Select button ,I remove the WS_TABSTOP from the CREATESTRUCT ,but that has no effect ! How can I realize that?
    
    thanks a lot for you answer!

    Reply
  • Memory Leak !!!

    Posted by Legacy on 10/13/2000 12:00am

    Originally posted by: wang jun

    in delete/create mode , just set the m_bautodelete = FALSE
    is not enough . because program will not automatically delete the Instance of CMyDoc when Program Closing , it will cause memory Leak !!!

    how to delete the instance of CMyDoc when Program Closing ??

    Reply
  • Problem with Message Routing

    Posted by Legacy on 11/09/1999 12:00am

    Originally posted by: Denis Flotat

    I have defined an DOC/VIEW application (SDI) built with 2 panes. On the left pane, a treeview (classic). On the left pane a CListView and a CFormView depending on current treeview selection (embedded into a CFrameWnd).

    The problem is that i have defined a ContextMenu on the ListView but menu is always grayed when i try to invoke from ListView. I think there is a problem with routing message because of the 2 frames ? who can help ?

    Reply
  • Not working for Formview

    Posted by Legacy on 07/02/1999 12:00am

    Originally posted by: swamy k.m.s

    This application i tried with a view classes derived from cview and formview,s. If i try to change the form view with another form view it is aborting
    please help.

    Reply
  • Problems with CRecordViews

    Posted by Legacy on 03/11/1999 12:00am

    Originally posted by: Hoffmann Thorsten

    I try to switch between CRecordViews, but i got an error when starting
    the program. May someone can help me???

    Reply
  • Replacing & Switching in Splitter

    Posted by Legacy on 03/05/1999 12:00am

    Originally posted by: Lee, Gee Man

    // source - ftp://eps01.iae.re.kr/pub/program/splitter.zip
    
    // I refered KB Q149257 & Q141334

    BOOL CSplitterWndEx::ReplaceView(int row, int col, CRuntimeClass *pViewClass)
    {
    if( (GetPane(row, col)->IsKindOf(pViewClass)) == TRUE )
    return FALSE;

    // Get pointer to CDocument object so that it can be used in the creation
    // process of the new view
    CView *pView = (CView *)GetPane(row, col);
    CDocument *pDoc = pView->GetDocument();
    int ctrl_id = pView->GetDlgCtrlID();
    int width, height, min_width, min_height;

    GetRowInfo(row, width, min_width);
    GetColumnInfo(col, height, min_height);

    // Delete existing view
    pView->DestroyWindow();

    // Create new view
    CCreateContext context;
    context.m_pCurrentDoc = pDoc;
    CreateView(row, col, pViewClass, CSize(width, height), &context);
    pView = (CView *)GetPane(row, col);
    pView->SetDlgCtrlID(ctrl_id);

    SetRowInfo(row, width, min_width);
    SetColumnInfo(col, height, min_height);
    RecalcLayout();

    return TRUE;
    }

    BOOL CSplitterWndEx::SwitchView(int row, int col, CView *pNewView)
    {
    int old_id, new_id;
    CView *pOldView = (CView *)GetPane(row, col);
    if( pNewView == pOldView )
    return FALSE;

    old_id = pOldView->GetDlgCtrlID();
    new_id = pNewView->GetDlgCtrlID();

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

    pOldView->SetDlgCtrlID(new_id);
    pNewView->SetDlgCtrlID(old_id);

    RecalcLayout();

    return TRUE;
    }

    // if you use SwitchView function, pNewView already created.
    // i was create in CFrameWnd::OnCreateClient()

    BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
    {
    CSize size(100, 100);

    m_wndSplitter.CreateStatic(this, 1, 4);

    m_wndSplitter.CreateView(0, 0,
    RUNTIME_CLASS(CMyView1), size, pContext);
    m_wndSplitter.CreateView(0, 1,
    RUNTIME_CLASS(CMyView2), size, pContext);
    m_wndSplitter.CreateView(0, 2,
    RUNTIME_CLASS(CMyView3), size, pContext);

    m_wndSplitter.CreateView(0, 3,
    RUNTIME_CLASS(CCtrlView1), size, pContext);

    int last_pane_id = m_wndSplitter.GetPane(0, 3)->GetDlgCtrlID();

    CView *pView = new CCtrlView2;
    pView->Create(NULL, NULL, 0L, CFrameWnd::rectDefault,
    &m_wndSplitter, last_pane_id+1, pContext); // last pane id
    pView->OnInitialUpdate();

    return TRUE;
    }

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date