views:

365

answers:

2

I currently have some toolbar buttons with a small arrow on the side (TBSTYLE_EX_DRAWDDARROWS) that, when clicked, result in a popup context menu being displayed under the button. This is done by constructing a custom popup menu and calling TrackPopupMenu.

The client now wants to be able to select multiple options from the menu before it closes, so that multiple options can be be modified without the need to re-open the menu and wait for an intermediate redraw between each change.

For example:

  1. User clicks dropdown button
  2. Dropdown menu appears (modal, waits indefinitely for user action)
  3. User clicks some item (e.g., toggle a checkmark)
  4. Timer (e.g., 500ms) starts
  5. If timer expires, the menu is closed and all selected actions are executed.
  6. User clicks another item before the timer expires, go back to 4.

The best I can come up with is to redisplay the menu by calling TrackPopupMenu multiple times. This makes the menu "flicker" when you select an item, and will probably require me to start a thread in order to do the timeouts, which I would rather avoid.

+2  A: 

Rather than a menu, put up a dialog box with the options on it. A dialog can easily do all that is required.

A menu that doesn't close when you click it will just seem wrong. A dialog that closes by itself will seem wrong too, but it's probably the least of two evils.

Edit: If there's anything I've learned with Microsoft, it's don't try to fight the default behavior. You're asking for trouble if you do.

If you're building your menu dynamically I can see how automatic sizing can be handy, but it's not hard to do in a dialog either - make the dialog really big and before it becomes visible, enumerate the children and take a union of all their rectangles, then resize to that. Checking the boundaries to make sure they're on-screen is just a few if statements with OffsetRect. Checkboxes are trivial; icons less so, but still not bad.

One additional enhancement that would be easy to add is to dismiss the dialog immediately on a double-click.

Mark Ransom
I'm not totally sold on the idea either, the intent is reasonable. Having to re-open the menu for each change is tedious, at least in this app. I considered using something other than a menu, and it is an option, but a menu provides considerable functionality, such as automatically resizing to fit its contents, placing itself on the screen to ensure that it's visible, showing checkbox/radio button icons or custom icons, etc., that I would have to build manually.
Tim Sylvester
+1  A: 

Following @Mark Ransom's answer, you should put up a dialog box. But you can make the dialog modeless and make it close itself when you click outside of it (i.e., the dialog loses focus). That way it could behave more like a menu.

Notice that normal menus never go away by themselves, you always have to click somewhere outside the menu (or one of its options) to make it disappear.

djeidot
Thanks for bringing up an aspect I forgot. I should warn you that there are tricky edge cases when you do this, and relying on messages when you lose focus might not be enough. Sorry I can't remember specifics, but I had to go through this once and it was painful.
Mark Ransom