Introduction
In my recent
project - a simple multiplayer network game
- I needed a very large
toolbar
(21 buttons), surely taking some width on
the screen :) it would be possible to create
it neatly arranged in a floated
toolbar:
Should be
simple, I thought. But it kept me
experimenting and digging the rest of the
day and encountering a bug in the
toolbar control
(at least under my Win98 SE, IE 5.5) ...
Regarding the
MSDN docs you should look at the
CToolBarCtrl::SetRows
function, that says - "ucancode.net the
toolbar
control to resize itself to the requested
number of rows". Lets hope the toolbar
is polite enough to do so.
Of course, it
isn't. When you do something like :-
CRect rcNew;
m_wndJewelBar.GetToolBarCtrl().SetRows(5, TRUE, &rcNew);
The buttons are
rearranged like in the picture above, but
the toolbar
window itself stays the same lengthy same,
whether docked or not:
Fortunately the
rcNew
rectangle returned is correct. Now I could
use it to reset the width of the toolbar:
m_wndJewelBar.CalcDynamicLayout(rcNew.Width(), LM_HORZ | LM_COMMIT);
But: nothing
seems to have happened - until I touched the
toolbar
with the mouse: magically it popped into the
correct size: you have to move the
toolbar
window before it redraws itself the the
correct shape. And for moving the
toolbar
there is the function
CFrameWnd::FloatControlBar(&m_wndJewelBar, rcNew,
CBRS_ALIGN_TOP | CBRS_SIZE_DYNAMIC);
Code
listing
Pretty weird,
isn't it? Now, I put things together and
made a little function for this:
Collapse
int CMainFrame::FloatToolbarSetRows(
CToolBar *pToolbar, int nRows, BOOL bLarger,
CPoint *pClientPos)
{
CPoint newPos(0,0); if (pClientPos)
newPos = *pClientPos;
ClientToScreen(&newPos);
if (!pToolbar->IsFloating())
FloatControlBar(pToolbar, CPoint(0,0));
CRect rcNew;
pToolbar->GetToolBarCtrl().SetRows(nRows,
bLarger, &rcNew);
pToolbar->CalcDynamicLayout(rcNew.Width(),
LM_HORZ | LM_COMMIT);
FloatControlBar(pToolbar, newPos,
CBRS_ALIGN_TOP | CBRS_SIZE_DYNAMIC);
return pToolbar->GetToolBarCtrl().GetRows();
}
Conclusion
There are two
known bugs in this code, but I would like to
blame Windows for this:
- My
function is to return the actual number
of rows in the tool bar. This is wrong.
In my 21 button toolbar, I tell the
function to create 5
rows,
which it does, but
GetRows()
returns 9 - ouch! If you really care
about the new size, you may calculate it
by using the new toolbar window
rectangle height and divide it by the
toolbar button size.
- When you
resize my toolbar to having 11
rows,
the last group of four buttons is wider
than the toolbar width of 3. The last
button of the group will not be
displayed (see image above). Since I can
duplicate this behavior by manually
floating and resizing the toolbar, I
decided not to care about this, and
think the Redmondians are fooling me.
At last (and
least) have fun with this code. May there be
a fine day you find the finished game on my
homepage :)