如何使用CSplitterWnd动态隐藏一个分割窗口

解决方案 »

  1.   


    不太明白你的意思,看看这篇文章吧,或许有启发  大多数情况下与文档相连的视只有一个。我们在VC编程环境中可以发现,在一个界面上开启多个窗口是非常方便的。我们可以让一个窗口控制视的显示,另一个窗口具体显示。应用框架有若干种方式表示多视,这些方式包括切分窗口和MDI子窗口。切分窗口看上去像是一种特殊的框架窗口,在各个窗片中包含了若干个视。应用程序在创建的时候就可以对窗口进行划分,也可以通过选择菜单命令或拖动切分窗口滚动条中的切分框对窗口进行划分。窗口被切分之后,用户可以通过鼠标移动来调整窗片的相对尺寸。切分窗口即适用于SDI应用程序又适用于MDI应用程序。  切分窗口是通过类CSplitterWnd来实现的。对Windows来说,CSplitterWnd是一个真正的窗口,它完全占据了框架窗口的用户区域,而视窗则占据了切分窗口的窗片区域。切分窗口不参与命令传递机制。   切分窗口有动态切分和静态切分两种方式。动态切分窗口允许用户在任何时候都对窗口进行切分,即可以通过选择菜单项来对窗口进行切分,也可以通过滚动条中的切分框对窗口进行切分。动态切分窗口中的窗片通常使用的是同一个视类。当切分窗口被创建时,左上窗片通常被初始化成一个特殊的视。在动态切分窗口中,滚动条在视中是被共用的。例如,在只进行了一次水平切分的窗口中,底滚动条同时控制着上下两个视。对于静态切分窗口,当窗口被第一次创建时,窗片就已经被切分好了,用户可以移动窗棱,但此时已不可能对窗口进行合并或再次切分。静态切分窗口允许使用多个视类,并且可在创建时对这些视类进行配置。在静态切分窗口中,每个窗片都有自己的滚动条。为了使一静态分割窗口拥有滚动条,可以把WS_HSCROLL和WS_VSCROLL风格加到dwStyle上。  下面就一个例子对静态切分进行详细说明。  第一步:建立一个基于单视窗的工程test。所有都取默认值。  第二步:在类CmainFrame中重载虚函数OnCreateClient,生成虚函数virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);    在类CmainFrame中定义变量CSplitterWnd m_wndSplitter;  第三步:生成一个CformView类。分析如下:CformView类是一个非常有用的类,具有许多无模式对话框的特点。象Cdialog派生类一样,CformView的派生类也与相应的对话框资源相联系。对话框资源中定义了格式视的框架特性,并且列举出了它所包含的所有的控件。CformView类也支持DDX和DDV。用定义一个对话框来生成一个CformView类,此对话框要作如下设置:style=Child
    Border=None
    Visible=不选中   定义一个对话框,其属性按上述要求设置。定义其对应的类Cview1,基类为CformView。在其中设置一个按钮IDD_BUTTON1,IDC_BUTTON2,IDC_BUTTON3。同样的方式添加Cview2。  第四步:在OnCreateClient中添加如下代码:BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
    {
     BOOL ret=m_wndSplitter.CreateStatic(this,3,1);
     ret|=m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CTestView),CSize(100,100),pContext);
     ret|=m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CView1),CSize(100,200),pCon text);
     ret|=m_wndSplitter.CreateView(2,0,RUNTIME_CLASS(CView2),CSize(100,100),pContext);
     return ret;
    }   此时,即可以产生多个视的窗口。  第五步:添加功能函数。实现在Cview1中点击Button1实现在视中画图,编写函数如下:void CView1::OnButton1() 
    {
     file://得到一SplitterView的指针
     CTestView*   pView=(CTestView*)(((CMainFrame*)AfxGetMainWnd())->m_wndSplitter.GetPane(1,0));
     file://定义View的DC
     CClientDC dc(pView);
     dc.MoveTo(10,10);
     dc.LineTo(10,100);
     dc.TextOut(10,10,"guanximing");
    }   第六步;实现某一窗片的尺寸变化。定义函数如下:void CView1::OnButton2() 
    {
    (((CMainFrame*)AfxGetMainWnd())->m_wndSplitter.SetRowInfo(0,4,0));
    (((CMainFrame*)AfxGetMainWnd())->m_wndSplitter.RecalcLayout());
    }   第七步:实现通过键盘对切分窗口进行尺寸改变,这种方法对窗片的尺寸改变很方便。编写代码如下:void CView1::OnButton3() 
    {
    (((CMainFrame*)AfxGetMainWnd())->m_wndSplitter.DoKeyboardSplit());
    }   好了,现在功能都实现了,试一下吧。 
      

  2.   

    获得视的指针后,可以用showwindows()和RecalcLayout()实现动态隐藏
      

  3.   

    CSplitterWnd::CreateStatic没有办法建立你要的动态!
    我做了一个Frame上面有一个分隔窗,可以动态生成一个CHtmlView
    1从CSplitterWnd派生一个类在加上自己的函数,Create,Frame就用这个来创建这个窗口
    BOOL CMySplitterWnd::Create(CFrameWnd* pParentWnd)
    {
    CCreateContext context;
    context.m_pCurrentFrame = pParentWnd;
    context.m_pCurrentDoc = NULL;
    context.m_pNewViewClass = RUNTIME_CLASS(CListView);
    context.m_pNewDocTemplate = NULL; if (CSplitterWnd::Create(pParentWnd, 2, 1, CSize(100,20), &context, WS_CHILD | WS_VISIBLE | SPLS_DYNAMIC_SPLIT))
    {
    m_pDynamicViewClass = RUNTIME_CLASS(CHtmlView);
    return TRUE;
    } return FALSE;
    }
    重载函数 virtual BOOL SplitRow(int cyBefore);(你可能还要重载SplitCol)
    virtual void DeleteRow (int rowDelete);
    BOOL CMySplitterWnd::SplitRow(int cyBefore)
    {
    if (CSplitterWnd::SplitRow(cyBefore))
    {
    CView* pView1 = (CView*)GetPane(0,0);
    CView* pView2 = (CView*)GetPane(1,0);
    if (pView1 && pView2 &&
    pView1->IsKindOf(RUNTIME_CLASS(CListView)) &&
    pView2->IsKindOf(RUNTIME_CLASS(CHtmlView)))
    {
    pView1->SetDlgCtrlID(IdFromRowCol(1,0));
    pView2->SetDlgCtrlID(IdFromRowCol(0,0));
    RecalcLayout();
    }
    return TRUE;
    }
    return FALSE;
    }void CMySplitterWnd::DeleteRow(int rowDelete)
    {
    CSplitterWnd::DeleteRow(0); return; ASSERT_VALID(this);
    ASSERT(GetStyle() & SPLS_DYNAMIC_SPLIT); ASSERT(m_nRows > 1);
    ASSERT(rowDelete < m_nRows); int rowActive, colActive;
    if (GetActivePane(&rowActive, &colActive) != NULL && rowActive == rowDelete)
    {
    if (++rowActive >= m_nRows)
    rowActive = 0;
    SetActivePane(rowActive, colActive);
    } CWnd* pScrollDel = m_bHasVScroll ?
    GetDlgItem(AFX_IDW_VSCROLL_FIRST+rowDelete) : NULL;
    for (int col = 0; col < m_nCols; col++)
    {
    DeleteView(rowDelete, col);
    for (int row = rowDelete+1; row < m_nRows; row++)
    {
    CWnd* pPane = GetPane(row, col);
    ASSERT(pPane != NULL);
    pPane->SetDlgCtrlID(IdFromRowCol(row-1, col));
    if (m_bHasVScroll && col == m_nCols-1)
    {
    CWnd* pScroll = GetDlgItem(AFX_IDW_VSCROLL_FIRST+row);
    if (pScroll != NULL)
    pScroll->SetDlgCtrlID(AFX_IDW_VSCROLL_FIRST+row-1);
    }
    }
    }
    m_nRows--;
    if (pScrollDel != NULL)
    pScrollDel->DestroyWindow(); RecalcLayout();     // re-assign the space
    }
    因为CSplitterWnd::IdFromRowCol有ASSERT所以你自己写一个
    int CMySplitterWnd::IdFromRowCol(int row, int col) const
    {
    ASSERT_VALID(this);
    ASSERT(row >= 0);
    ASSERT(col >= 0); return AFX_IDW_PANE_FIRST + row * 16 + col;
    }
      

  4.   

    可以通过SetColomnInfo/SetRowInfo将窗格大小设为0来实现隐藏