Search code examples
c++mfcmfc-feature-pack

How to calculate the size of a CMFCRibbonStatusBarPane


I have MFC ribbon based application that includes three status bars as follows;

CString LongString;
LongString.Format("%0*lf", 60, 0.0);
m_pStatusWnd = new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE1, _T(""), TRUE,NULL, LongString);
m_pStatusCommand = new CMFCRibbonStatusBarPane(ID_INDICATOR_PROMPT, _T("Command"), TRUE, NULL, "000000000000000000000000000000");
m_pStatusSnap = new CMFCRibbonStatusBarPane(ID_INDICATOR_SNAP, _T("Snaps"), TRUE, NULL, "00000000000000000000");
ui.GetStatusBar().AddElement(m_pStatusWnd, "Status");
ui.GetStatusBar().AddExtendedElement(m_pStatusCommand, "Command");
ui.GetStatusBar().AddExtendedElement(m_pStatusSnap, "Snaps");
ui.GetStatusBar().RecalcLayout();

The two extended status panes on the bottom right side of the screen have fixed sizes, but I'd like the left side status pane to take the remaining space to the edge of the frame. The only method I can find for setting the pane width is the SetAlmostLargeText method, which isn't really that useful as the value will vary based on the size of the frame. From testing, if I give a value too large, the status pane simply does not display any content. Similarly, if I resize the frame and make it smaller, the content on the left pane is lost entirely once it goes below the AlmostLargeTextSize

Is there a method of calculating the size of the left CMFCRibbonStatusBarPane based on available frame space? Nearest I can find is CMFCRibbonBaseElement::GetSize which I could possibly figure out the maximum available text size from when used in conjunction with average font size metrics, but it seems rather crude.


Solution

  • I got this working as follows;

    void CMainFrame::OnSize(UINT nType, int cx, int cy)
    {
        CMyMainFrame::OnSize(nType, cx, cy);
        if (!m_MyFrameInitialised)
          return;  // Only proceed if frame creation has been completed
        CString SnapStr = m_pStatusSnap->GetAlmostLargeText();
        CString CommandStr = m_pStatusCommand->GetAlmostLargeText();
        int SnapChars = SnapStr.GetLength(),CommandChars = CommandStr.GetLength(),  StatusChars = 0;
        CDC *pDC = GetWindowDC();
        CSize SnapSize = m_pStatusSnap->GetSize(pDC);
        pDC->LPtoDP(&SnapSize);
        double CharWidth = SnapSize.cx;  
        CharWidth /= SnapChars;
        double TotalChars = cx / CharWidth;
        StatusChars = TotalChars - (SnapChars + CommandChars);
        CString LongStatusString;
        LongStatusString.Format("%0*.0lf", StatusChars, 0.0);
        m_pStatusWnd->SetAlmostLargeText(LongStatusString);
        ui.GetStatusBar().RecalcLayout();
    }
    

    Basically, when the frame window gets sized at any time after initially being created, calculate the size of the width of the frame in terms of status pane characters, subtract the number of characters of the known panes, and set the left pane based on the result.

    Seems a bit cumbersome for a UI that is supposed to offer a high level of abstraction, but it was the best I could come up with.