65.9K
CodeProject is changing. Read more.
Home

MFC 7.0 Assertion Bug in CToolBar::CreateEx(...), CControlBar::SetBarStyle(...) and others

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (3 votes)

Feb 26, 2002

1 min read

viewsIcon

71010

This is a buggy ASSERT statement that limits the number of docking flags to one.

Introduction

I was recently going through the process of trying some code with MFC 7.0 when I stumbled on the following statement in CControlBar::SetBarStyle(...):

ASSERT((dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_TOP ||
       (dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_BOTTOM ||
       (dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_LEFT ||
       (dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_RIGHT);
Now let’s go to the MFC documentation and find out what those flags mean:
  • CBRS_ALIGN_TOP Allows the control bar to be docked to the top of the client area of a frame window.
  • CBRS_ALIGN_BOTTOM Allows the control bar to be docked to the bottom of the client area of a frame window.
  • CBRS_ALIGN_LEFT Allows the control bar to be docked to the left side of the client area of a frame window.
  • CBRS_ALIGN_RIGHT Allows the control bar to be docked to the right side of the client area of a frame window.
  • CBRS_ALIGN_ANY Allows the control bar to be docked to any side of the client area of a frame window.
On a first glance it looks like the purpose of the ASSERT statement is to make sure that at least one of the docking flag is set. But this is wrong! This statement is actually an exclusive OR - it will assert unless only one of the docking styles is set! It is clear to see why:

Let's say that we want our toolbar to be able to dock on the top and left sides of the frame window. So we need to call CControlBar::SetBarStyle(...) with the following flags:

m_ToolBar.SetBarStyle(CBRS_ALIGN_TOP | CBRS_ALIGN_LEFT);
So substituting the actual hex values from afxres.h we get:
ASSERT((0x3000 & 0xF000) == 0x2000 ||
       (0x3000 & 0xF000) == 0x8000 ||
       (0x3000 & 0xF000) == 0x1000 ||
       (0x3000 & 0xF000) == 0x4000);
This becomes:
ASSERT(0x3000 == 0x2000 ||
       0x3000 == 0x8000 ||
       0x3000 == 0x1000 ||
       0x3000 == 0x4000);
From here it is clear that this is equivalent to:
ASSERT(FALSE);
If the genuine idea if this statement is to make sure that at least one of the docking flags is set it should be replaced with:
ASSERT((dwStyle & CBRS_ALIGN_ANY) != 0);
This ASSERT statement can be found in the following functions:
  • CReBar::Create(...)
  • CControlBar::SetBarStyle(...)
  • CDockBar::Create(...)
  • CStatusBar::CreateEx(...)
  • CToolBar::CreateEx(...)