A Fix for CToolBar with IE4 | CodeGuru

A Fix for CToolBar with IE4

The new version of COMCTL32.DLL that is shipped with the release version of IE4 (4.71.1712.3) has a problem when combined with the MFC CToolBar.  When an MFC application is run under IE4, and a toolbar with separators (groups) is docked vertically, or floated with >1 row) then the bottom button/row is clipped. The reason for […]

Written By
CodeGuru Staff
CodeGuru Staff
Feb 7, 1999
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

The new version of COMCTL32.DLL that is shipped with the release version of IE4
(4.71.1712.3) has a problem when combined with the MFC CToolBar.  When an MFC
application is run under IE4, and a toolbar with separators (groups) is docked vertically,
or floated with >1 row) then the bottom button/row is clipped.

The reason for this is that CToolBar was written with the assumption the horizontal
separators are 8 pixels wide and vertical separator are (8*2/3) = 5 pixels high. 
This was the case until IE4 came along.  Now the vertical separators are 8 pixels
high instead of 5 pixels.  So CToolBar does not allocate enough room for the tooblar
buttons.

If MFC had made the function which calculates the size of the buttons and separtors
virtual, then all that would be required is to override that single function. 
However, in their infinite wisdom, the MFC designers di not do this for us.  So now
one needs to copy many functions with many many lines of code so one can patch up this
‘mistake’.

The code below assumes that you have the code I published earlier the detects the
version of COMCTL32 that is currently loaded.  It then makes the fixes required based
on which version is running.  If it is the IE4 version, then it uses 8 pixels for the
height, otherwise it uses 5 pixels as before (8*2/3)

Step 1:

To make the fix, copy the following functions verbatim from the "BARTOOL.CPP"
in your MFC source tree, and change all occurences of "CToolBar" to
"CMyToolBar"

void CMyToolBar::_GetButton(int nIndex, TBBUTTON* pButton) const
{
     ...
}
void CMyToolBar::_SetButton(int nIndex, TBBUTTON* pButton)
{
     ...
}

#ifdef _MAC
     #define CX_OVERLAP  1
#else
     #define CX_OVERLAP  0
#endif

void CMyToolBar::SizeToolBar(TBBUTTON* pData, int nCount, int nLength, BOOL bVert)
{
     ...
}
}

struct _AFX_CONTROLPOS
{
     int nIndex, nID;
     CRect rectOldPos;
};

CSize CMyToolBar::CalcLayout(DWORD dwMode, int nLength)
{
     ...
}

CSize CMyToolBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
     ...
}
CSize CMyToolBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
     ...
}

Step 2:

Copy and MODIFY the CalcSize routine from "BARTOOL.CPP" as shown .. my
changes and additions are commented with // RO

CSize CMyToolBar::CalcSize(TBBUTTON* pData, int nCount)
{
    // Check for COMCTL32 version number // RO
    bool isfullheightsep = false; // RO
    if (QWinApp::ComCtl32Version() >= COMCTL32_471) { // RO
        isfullheightsep = true// RO
    }    // RO
    ASSERT(pData != NULL && nCount > 0);

    CPoint cur(0,0);
    CSize sizeResult(0,0);

    for (int i = 0; i < nCount; i++)
    {
        if (pData[i].fsState & TBSTATE_HIDDEN)
            continue;
        int iBitmapx = pData[i].iBitmap;    // RO
        int iBitmapy = iBitmapx;            // RO
        if (! isfullheightsep)
            iBitmapy = iBitmapy * 2 / 3;    // RO

        if (pData[i].fsStyle & TBSTYLE_SEP)
        {
            // A separator represents either a height or width
            if (pData[i].fsState & TBSTATE_WRAP)
                sizeResult.cy = max(cur.y + m_sizeButton.cy + iBitmapy,sizeResult.cy);    // RO
                // RO sizeResult.cy = max(cur.y + m_sizeButton.cy + pData[i].iBitmap * 2 / 3, sizeResult.cy);
            else
                sizeResult.cx = max(cur.x + iBitmapx, sizeResult.cx); // RO
                // RO sizeResult.cx = max(cur.x + pData[i].iBitmap,sizeResult.cx);
        }
        else
        {
            sizeResult.cx="max(cur.x" + m_sizeButton.cx, sizeResult.cx);
            sizeResult.cy="max(cur.y" + m_sizeButton.cy, sizeResult.cy);
        }

        if (pData[i].fsStyle & TBSTYLE_SEP)
            cur.x +="pData[i].iBitmap;"
        else
            cur.x +="m_sizeButton.cx" CX_OVERLAP;

        if (pData[i].fsState & TBSTATE_WRAP)
        {
            cur.x = 0;
            cur.y += m_sizeButton.cy;
            if (pData[i].fsStyle & TBSTYLE_SEP)
                cur.y +=iBitmapy; // RO
            cur.y +="pData[i].iBitmap" * 2 / 3;
        }
   }

   return sizeResult;
} 

In summary I have added 5 lines at the top to detect the version, added 3 lines before
"if (pData[i].fsState & TBSTYLE_SEP)", replaced two lines in the following
"if" and replaced one line near the end.

Advertisement

Step 3:

You need to define a CToolBar derived CMyToolBar (or CFlatToolBar-derived, or make the
changes to CFlatTOolBar anyway which is what I did). In that class, you will need to copy
the declarations for the functions we have copied – don’t forget to make CalcDynamicSize
and CalcFixedSize VIRTUAL functions !!

That should do it.  Now your toolbars will work under all versions of COMCTL32.DLL
– well, at least until MS releases a new version 🙂

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.