The first thing a ribbon does when it shows up is to disable the traditional menu bar. This innocent looking behaviour has very important effect on command updates, that is enabling or disabling program commands depending on the context. You know, when nothing is selected you want to disable Edit > Copy command and re-enable it once something is selected. The aforementioned WTL ribbon class does this nicely extending the basic CUpdateUI mechanism so that CRibbonUpdateUI::UIEnable uses the ribbon's UI_PKEY_Enabled property to mirror command states just like as if one was using a normal menu bar. Case closed — or is it?
Yesterday I accidentally pressed a keyboard shortcut for a command that was supposed to be disabled, and noticed that the command executed nevertheless blowing off a few assertion messages as it was not expected to occur. When I swapped the ribbon for a good old menu, the same accelerator key was blocked, correctly. WTF? I wasted a few hours checking the pretranslate queue where keys are translated into commands, but couldn't see what difference a menu or ribbon should make!? Then I read the documentation of TranslateAccelerator carefully and a few breakpoints later I saw the light.
You see, TranslateAccelerator API does not just convert a key to a WM_COMMAND using the current accelerator table. It consults the menu bar (if any) and sends WM_INITMENUPOPUP and other messages. If it discovers that a menu command is disabled, it just eats the key and no command is despatched. If there's a ribbon (ie. no menu), this "disable accelerators for free" behaviour is lost. How subtle is that? Ok now we know what's the cause, here's how to fix it:
And that will fix the "leak" of disabled commands through their keyboard accelerators.
This flaw could possibly affect MFC programs (CCmdUI object) but there a different CMFCRibbonBar is used and good luck deciphering how MFC daedalus-esque command routing is affected.