“Sticky” MFC popup menu


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.

Best Solution

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.

Related Question