Introduction
This article shows a technique to disable top-level popup menus embedded in the Command Bar of PocketPC 2002 applications built with MFC. This is the result of my continuing discussions with John Simmons / outlaw programmer about the "ease of use" of the PocketPC 2002 User Interface API under MFC. On our last take at these issues, we found that disabling top-level popup menus is not a trivial task. Here is one solution.
Top-level popup menus
They are not popup menus. They are fakes. They are toolbar buttons! I reached this conclusion by looking at how CCeCommandBar::LoadToolBar
is implemented. The menu resource you supply is broken into its popups, and a text toolbar button is created for each one of them. So it is useless to try and use CMenu
methods to enable or disable these, you have to manipulate the underlying buttons.
Popup menu buttons are created with standard IDs starting with 0xF000 for the first one, and are incremented by 1 for the next ones. So, in order to know what button you want to access, you have to know its ordinal position. If you are using the "shared new" button, 0xF000 will be the first one to the right of it.
The solution
My first approach was to use the TB_ENABLEBUTTON
message. It seemed to work until John Simmons noticed that some of the button's texts were being truncated when grayed. In fact, when the toolbar disables a text button, it paints it in gray with a white shadow, making the text one pixel wider. Needless to say that the rectangle that holds this text is not changed and the text is clipped...
The next approach was based on the GetButtonInfo
and SetButtonInfo
methods of the CToolBarCtrl
that supports all toolbars. With these, I set a number of properties of the TBBUTTONINFO
structure, namely fsState
and cx
. The first one is used to set the button state (enabled or disabled), where the second is used to increase the button size when it is disabled, and to decrease it back when it is enabled.
I encapsulated the solution in the CCeCommandBarEx
class that has only one method (besides standard constructor and destructor): EnablePopupMenu
. The implementation is as follows:
BOOL CCeCommandBarEx::EnablePopupMenu(int iIndex, BOOL bEnable)
{
CToolBarCtrl& rToolBar = GetToolBarCtrl();
TBBUTTONINFO tbi;
int nID = 0xf000 + iIndex;
CSize sizeImage(16,15),
sizeButton(23, 21);
BOOL bRval;
tbi.cbSize = sizeof(tbi);
tbi.dwMask = TBIF_STATE | TBIF_SIZE | TBIF_COMMAND;
tbi.idCommand = nID;
bRval = rToolBar.GetButtonInfo(nID, &tbi);
if(bRval)
{
if(tbi.fsState & TBSTATE_ENABLED)
tbi.cx += bEnable ? 0 : 1;
else
tbi.cx -= bEnable ? 1 : 0;
if(bEnable)
tbi.fsState |= TBSTATE_ENABLED;
else
tbi.fsState &= ~TBSTATE_ENABLED;
rToolBar.SetButtonInfo(nID, &tbi);
SetSizes(sizeButton, sizeImage);
}
return bRval;
}
Note that I have to call SetSizes
to avoid an incomprehensible bug I found: when increasing the popup menu button size, all other buttons would change their sizes as well.
The demo project
You will find that the demo project is an adaptation of the same project I used in my other article Multiple Toolbars in the PocketPC 2002 , but with some changes namely:
- Tool tips on all toolbars
- Toolbars are now exclusively shown