Click here to Skip to main content
15,886,362 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a main window derived from CFrameWnd that contains vertical and horizontal CSplitterWnd.

I would like to maintain their pane proportions during resizing.

Both vertical and horizontal splitter have 2 panes, so main window looks like a Cartesian coordinate system.

What I have tried:

I have tried the following in the OnSize(UINT nType, int cx, int cy) handler:

C++
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
    CFrameWnd::OnSize(nType, cx, cy);

    int iCX = 0, iCY = 0, iCX2 = 0, iCY2 = 0,
        iCYMin = 0, iCXMin = 0;     // dummy variables, required by the API, not used

    m_wndSplitter.GetRowInfo(0, iCY, iCYMin);
    m_wndSplitter.GetRowInfo(1, iCY2, iCYMin);

    m_wndSplitter2.GetColumnInfo(0, iCX, iCXMin);
    m_wndSplitter2.GetColumnInfo(1, iCX2, iCXMin);

    double row_scaling_coefficient = static_cast<double>(iCY) / static_cast<double>(iCY2 + iCY);
    double column_scaling_coefficient = static_cast<double>(iCX) / static_cast<double>(iCX + iCX2);

    iCX = static_cast<int>(column_scaling_coefficient * static_cast<double>(cy) + 0.5);
    iCY = static_cast<int>(row_scaling_coefficient * static_cast<double>(cx)+ 0.5);

    //================ dirty workaround, since RecalcLayout() does not work if size remains unchanged 
    // we +1 so CSplitterWnd registers size change
    m_wndSplitter.SetRowInfo(0, iCY + 1, 0);
    m_wndSplitter2.SetColumnInfo(0, iCX + 1, 0);

    m_wndSplitter.RecalcLayout();
    m_wndSplitter2.RecalcLayout();

    // then reset to actual size
    m_wndSplitter.SetRowInfo(0, iCY, 0);
    m_wndSplitter2.SetColumnInfo(0, iCX, 0);

    m_wndSplitter.RecalcLayout();
    m_wndSplitter2.RecalcLayout();
    //======================================
}
Posted
Updated 25-Jan-21 7:02am

1 solution

I would not resort to your "dirty workaround." You have the previous row and column sizes so I would calculate new sizes and compare them with the old ones and only recalculate the layout if either of them change. If neither change then you don't have to do anything with the splitters.

-ETA:

I messed around with this a bit and got something to work. The key things are don't call the base class' OnSize method initially. Also, you have to take the width of the splitter into account. Here's what I ended up with for a single vertical splitter. This can be easily extended to more splitters.
C++
void CMainFrame::OnSize( UINT type, int cx, int cy )
{
    static int splitwidth = 0;
    static bool first = true;
    int temp;

    if( m_InitSplitter && first )
    {
        // on the first entry determine the width of the splitter

        first = false;

        RECT cr;
        GetClientRect( & cr );
        int width = cr.right - cr.left;

        int svx1, svx2;
        m_SplitterV.GetColumnInfo( 0, svx1, temp );
        m_SplitterV.GetColumnInfo( 1, svx2, temp );
        int colw = svx1 + svx2;
        splitwidth = width - colw;

//      TRACE( "x1=%3d, x2=%3d, colw=%4d, swidth=%d\n",
//              svx1, svx2, colw, splitwidth );
    }

    if( m_InitSplitter && ( type != SIZE_MINIMIZED ) )
    {
        int svx1, svx2;

        m_SplitterV.GetColumnInfo( 0, svx1, temp );
        m_SplitterV.GetColumnInfo( 1, svx2, temp );
        int colw = svx1 + svx2 + splitwidth;

        double colScale = (double) svx1 / (double)( colw );
        int cx1 = (int)( cx * colScale + 0.5 );

//      TRACE( "x1=%3d, x2=%3d, colw=%4d, cx=%4d, cx1=%d\n",
//              svx1, svx2, colw, cx, cx1  );

        m_SplitterV.SetColumnInfo( 0, cx1, 0 );
        m_SplitterV.RecalcLayout();
    }

    __super::OnSize( type, cx, cy );
}
The m_InitSplitter member is initially false and set true after all the splitters and their views have been created. This test program made a vertical splitter and a horizontal splitter. This logic changed only the vertical splitter when the window was resized horizontally.
 
Share this answer
 
v3
Comments
MyOldAccount 25-Jan-21 13:09pm    
Thank you for answering.
I have to because main windows gets minimized on startup and does not paint splitter panes properly when restored.
Rick York 26-Jan-21 3:04am    
please see the revised solution.
MyOldAccount 26-Jan-21 4:04am    
Thank you, this is enough for now. 5ed

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900