Tabbed views within a splitter window

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

This article presents a class which can be used to create tabbed views within a splitter window. As a starting point, I used Daniel Harth's article about tabbed views within frame windows (SDI frame window or MDI child window).

Since splitter window dynamically creates a view object (based on RUNTIME_CLASS information), tabbed window is created in the same way. In order to perform the creation of all the views (tabs) within a tab window, this class contains a virtual function DoCreateView(...) which is called from within a Create() member function that actually creates a tab window. Default implementation of DoCreateView(...) function simply asserts since the actual creation of all the views is delegated to an overloaded function in the derived class.

Besides this technique, there are several other functions:

(1) virtual function called after the view (tab) is changed

(2) virtual function which is called to determine whether the switch to another view is allowed or not (by default it is allowed)

(3) function to change the label in runtime

(4) several informational function to get the pointer to the current view, get the current tab index, get the label etc.

Here is a pseudo code that shows how to use this class:

Declare a derived class specific to your project:


class TMyTab : public TVisualTabInSplitter 
{
protected:
 DECLARE_DYNCREATE(TMyTab)
public:
 virtual ~TMyTab();
 virtual void DoCreateView(CCreateContext *pContext);
};

Class implementation:

IMPLEMENT_DYNCREATE(TMyTab,TVisualTabInSplitter)

TMyTab::~TMyTab()
{
}

void TMyTab::DoCreateView(CCreateContext *pContext)
{
 CreateView(Page 1, RUNTIME_CLASS(CTreeView), pContext);
 CreateView(Page 2, RUNTIME_CLASS(CListView), pContext);
}

If you are creatng an SDI application, then use the following code as a sample:

BOOL DerivedFromCFrameWnd::OnCreateClient(..., CCreateContext *pContext)
{
 Splitter.CreateStatic(this,1,2);

 Splitter.CreateView(0,0,RUNTIME_CLASS(TTreeView),CSize(150,0),pContext);
 Splitter.CreateView(0,1,RUNTIME_CLASS(TMyTab),CSize(0,0),pContext);

 return TRUE;
}

Of course, you could also use a nested splitter window.

I intend to design a tabbed views class that can be used as a child to frame window and that can contain a splitter window on one of the tabs. You may collect the latest version of the class from my Web site: www.scasoftware.com.

Last updated: January 15, 1999.



Comments

  • www.scasoftware.com is down?

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

    Originally posted by: visualC

    www.scasoftware.com is down?
    where can i find the demo and the source code, now?

    Reply
  • where's the source now?

    Posted by Legacy on 10/01/2002 12:00am

    Originally posted by: suzanne

    seems the site's down... can't get at the source.

    Reply
  • Trying to use VisualFX with CHtmlView derived class

    Posted by Legacy on 08/23/2002 12:00am

    Originally posted by: btp

    Hi!
    
    

    I have used the VisualFXSdi_demo (compiled with CASE_3 defined) to test the use of the library with CHtmlView derived views. I have created a split window with a CFormView in the first pane and a tabWnd with 3 tabs in the second pane as shown in the code below.

    // Splitter (1 row, 2 columns). Second column is a tab with 2 panes
    TVisualObject *pSplitter = new TVisualObject(1,"Test", 1, 2, pContext);
    TVisualObject *pView1 = new TVisualObject(2,0,0,pContext, RUNTIME_CLASS(CTCFormView), CSize(300,0));
    TVisualObject *pTab = new TVisualObject(3,0,1,pContext, RUNTIME_CLASS(TTabWnd), CSize(0,0),TVisualObject::TOS_TABTOP);
    TVisualObject *pTabView1 = new TVisualObject(4,"Browser1",pContext,RUNTIME_CLASS(CDummyHtml));
    TVisualObject *pTabView2 = new TVisualObject(5,"Browser2", pContext,RUNTIME_CLASS(CDummyHtml2));
    TVisualObject *pTabView3 = new TVisualObject(6,"Browser3", pContext,RUNTIME_CLASS(CDummyHtml3));

    m_Framework.Add(pSplitter);
    m_Framework.Add(pSplitter, pView1);
    m_Framework.Add(pSplitter, pTab);
    m_Framework.Add(pTab, pTabView1);
    m_Framework.Add(pTab, pTabView2);
    m_Framework.Add(pTab, pTabView3);


    All this works like a charm as long as I do not click any of the tabs. If I have changed tab, then I get an Access Violation when I exit the app. If I have not changed tabs I do not get any access violation.

    Has any one used this framework with CHtmlView derived views successfully? If so were there problems of this sort? I have attempted to step through the destruction sequence in both the the good and the bad scenarios and I have found nothing so far to indicate why I have the access
    errors. The CHtmlView OnDestroy method is being called (properly, I think). The access violation actually shows up when the SplitterWnd is finally being deleted. Any help would be appreciated.

    By the way the VisualFX framework is pretty cool none-the-less.


    BTP

    Reply
  • Default laypout just display one Spit window only

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

    Originally posted by: wky086

    Hi:
    Sorry to disturb you. I found that your example is very useful for my program. But I face some problem. I want a lkie this :
    ----------
    | | |
    | | |
    -----------
    | |
    | |
    -----------
    but the output is like this
    -----------
    -----------
    | |
    | |
    | |
    | |
    -----------

    the upper two panel cannot display . I only can see them by manually pull the split bar.
    The folling is my code in the .CreateClient
    {
    TVisualObject *pSplitter = new TVisualObject(1,"Test", 2, 1, pContext);
    TVisualObject *pView1 = new TVisualObject(2,0,0,1,2,pContext);

    TVisualObject *pView2 = new TVisualObject(3,1,0,pContext,RUNTIME_CLASS(TTabWnd),CSize(0,0),TVisualObject::TOS_TABTOP);

    TVisualObject *pNestedView1 = new TVisualObject(4,0,0,pContext,RUNTIME_CLASS(CEventView),CSize(0,100));
    TVisualObject *pNestedView2 = new TVisualObject(5,0,1,pContext,RUNTIME_CLASS(CEventView),CSize(100,100));

    TVisualObject *pPane1 = new TVisualObject(6,"View", pContext, RUNTIME_CLASS(CEventView));
    TVisualObject *pPane2 = new TVisualObject(7,"Edit", pContext, RUNTIME_CLASS(CEventView));

    pView1->SetHotKey('1');
    pNestedView1->SetHotKey('2');
    pNestedView2->SetHotKey('3');
    pPane1->SetHotKey('4');
    pPane2->SetHotKey('5');

    pPane1->SetIcon(IDI_TESTICON_A);
    pPane2->SetIcon(IDI_TESTICON_A);

    m_Framework.Add(pSplitter);

    m_Framework.Add(pSplitter, pView1);
    m_Framework.Add(pSplitter, pView2);
    m_Framework.Add(pView1, pNestedView1);
    m_Framework.Add(pView1, pNestedView2);

    m_Framework.Add(pView2, pPane1);
    m_Framework.Add(pView2, pPane2);


    m_Framework.Create(this);

    TVisualFrameworkIterator it(m_Framework);
    while (!it.End()) {
    TVisualObject *pObject = it.Get();
    it++;
    }
    }
    CEventView is just a class derived from CView. Not construct yet. Just create for testing.

    Do you have any idea why it come like this. In your example, I change the CSize(); It will change the disply area. But in this case not. Could you give me me idea. I really like to use your example code. It is very powerful.
    Millions of thanks in advance.

    Reply
  • Can't use memory dc in tabbed views

    Posted by Legacy on 11/22/2001 12:00am

    Originally posted by: tide

    CDC dc;
    dc.CreateCompatibleDC (pDC);
    CBitmap bit;
    bit.CreateCompatibleBitmap (pDC,200,400);
    dc.SelectObject (&bit);
    dc.FillSolidRect (0,0,200,400,RGB(10,10,100));
    pDC->BitBlt (0,0,200,400,&dc,0,0,SRCCOPY);

    I got a black rect.

    Reply
  • How can I put a CTreeCtrl in one of the splitter window?

    Posted by Legacy on 09/23/2001 12:00am

    Originally posted by: Qiuxiang

    HI,
    
    

    I have seen many examples doing these two kinds of things:
    1. Create a splitter window, then calling
    Splitter.CreateView(0,0,RUNTIME_CLASS(CTreeView),....)
    to create a CTreeView in Panel(0,0)

    OR

    2. Create the CTreeCtrl in ...AppView.cpp:
    CTreeCtrl m_TreeFile;
    CRect r;
    if (!m_TreeFile.Create(WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS | TVS_SHOWSELALWAYS, r, this, 100))
    ...

    The question is:
    If I have a class derived from CTreeCtrl(Not CTreeView), I want to create a splitter window, then I want to put the CTreeCtrl into one of the spliiter window, How and Where should I put the code?

    Thank you very much for help!

    Reply
  • How to activate a view through another on an event?

    Posted by Legacy on 05/07/2001 12:00am

    Originally posted by: Pushpa

    Sir, 
    
    I have understood how to split windows. I want to know how to activate a Form(base class CFormView) from other view or dialog in the same way we do for a dialog using CDialog::DoModal();
    Kindly reply soon

    Reply
  • Cannot view a custom control within a tab

    Posted by Legacy on 09/01/2000 12:00am

    Originally posted by: bjm

    I placed Chris Maunders grid control into a tab and
    It does not show up. Does anyone have a suggestion how
    I can fix this?

    Reply
  • Runtime treeview is ok, bu listview has some problem.

    Posted by Legacy on 08/21/2000 12:00am

    Originally posted by: xjl200

      typedef CcsView_T<CcsDynTreeCtrl> CcsDynTreeCtrlView;
    
    CRuntimeClass* pRTClass = CcsDynTreeCtrlView::GetStaticRTClass();
    typedef CcsView_T<CcsDynListCtrl> CcsDynListCtrlView;
    CRuntimeClass* pRTClass1 = CcsDynListCtrlView::GetStaticRTClass();
    TVisualObject *pTab1 = new TVisualObject(1,"",pContext,RUNTIME_CLASS(TTabWnd),TVisualObject::TOS_TABTOP);
    TVisualObject *pTabView1 = new TVisualObject(2,"Configuration",1,2,pContext);
    TVisualObject *pTabView2 = new TVisualObject(3,"Script", pContext, RUNTIME_CLASS(CScriptForm));
    TVisualObject *pSplitView1 = new TVisualObject(4,0,1,pContext,pRTClass1,CSize(100,0));
    TVisualObject *pNested = new TVisualObject(13,0,0,2,1,pContext);
    TVisualObject *pNestedPane = new TVisualObject(14,0,0,pContext,pRTClass,CSize(0,150));
    TVisualObject *pSplitView2 = new TVisualObject(5,1,0,pContext,RUNTIME_CLASS(TTabWnd),CSize(0,0),TVisualObject::TOS_TABBOTTOM);
    TVisualObject *pPane1 = new TVisualObject(6,"DC",pContext,pRTClass1,TVisualObject::TOS_SELECTED);
    TVisualObject *pPane2 = new TVisualObject(7,"TC",pContext,pRTClass1);
    TVisualObject *pPane3 = new TVisualObject(9,"File",pContext,pRTClass1);


    m_Framework.Add(pTab1);
    m_Framework.Add(pTab1,pTabView1);
    m_Framework.Add(pTab1,pTabView2);
    m_Framework.Add(pTabView1,pNested);
    m_Framework.Add(pNested, pNestedPane);
    m_Framework.Add(pNested,pSplitView2);
    m_Framework.Add(pSplitView2,pPane1);
    m_Framework.Add(pSplitView2,pPane2);
    m_Framework.Add(pSplitView2,pPane3);
    m_Framework.Add(pTabView1,pSplitView1);

    m_Framework.Create(this);
    TVisualFrameworkIterator it(m_Framework);
    while (!it.End()) {
    TVisualObject *pObject = it.Get();
    it++;
    }
    pTabView1->SetActiveTab();
    CSplitterWnd *m_pWnd=new CSplitterWnd;
    m_pWnd=(CSplitterWnd *)pTabView1->GetWnd();
    m_pWnd->SetColumnInfo(0,200, 0);
    m_pWnd->RecalcLayout();
    CcsDynTreeCtrlView* pTreeView = (CcsDynTreeCtrlView*)pNestedPane->GetWnd();
    ASSERT_VALID(pTreeView);

    CcsDynTreeCtrl*pTreeCtrl = pTreeView->GetChildCtrl(); ASSERT_VALID(pTreeCtrl);
    if(!pTreeCtrl->Create(AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),pTreeView,AFX_IDW_PANE_FIRST))
    return FALSE;

    pTreeCtrl->InitDomView(pApex); // TreeView is right

    CcsDynListCtrlView* pDynListCtrlView = (CcsDynListCtrlView*) CcsDynListCtrlView::CreateObject();
    ASSERT_VALID(pDynListCtrlView);
    DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP;


    if(!pDynListCtrlView->Create(NULL,_T("ScriptView"),dwStyle,CRect(0,0,0,0),
    m_Framework.Get(6)->GetWnd(),CCS_FAKE_WNDID(0,0)))
    {
    return FALSE;
    } // I don't know how to setup the parent window,
    // Maybe it is m_Framework.Get(6))->GetWnd(), or pPane1->GetWnd(). but both are failed.

    CcsDynListCtrl* pDynListCtrl = pDynListCtrlView->GetChildCtrl(); ASSERT_VALID(pDynListCtrl);
    if(!pDynListCtrl->Create(AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),pDynListCtrlView,AFX_IDW_PANE_FIRST))
    return FALSE;
    pDynListCtrl->InitDomView(pApex); // ListView is failed.

    Why TreeView is right and ListView is failed. do you know how to setup the parent window?

    Reply
  • Good software but ....

    Posted by Legacy on 08/20/2000 12:00am

    Originally posted by: xjl200

    The software is good. but still has some problem.
    1. If the first tab incluse two spliter windows. the first window( or column) is a neated view with two spliter windows. the software can't work.
    2. I can add RunTime treeview into table view. but I can add RunTime List view into tab view. i don't know the parent Window of ListCtl.
    i solve topic 1 and left topic 2 to you.
    any suggestion will be thanked.
    regards,
    xjl

    Reply
  • Loading, Please Wait ...

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