MRU list in a submenu: the MFC bug and how to correct it

We should be able to use the MRU list in a submenu just by moving the menu item with the id ID_FILE_MRU_FILE1 from the "File" menu to the submenu we wanted. However, a bug in the CWinApp class causes that if the MRU first item is the first item in the submenu, the MRU list appears in the parent menu, instead of the submenu. This article describes the bug and how to correct it.

First, lets understand how the MFC framework displays the MRU menu (or submenu). The CWinApp class has a member m_pRecentFileList of type CRecentFileList*. The class CRecentFileList encapsulates the funcionality of a MRU list, and knows how to display itself. To display the MRU list, the CWinApp class calls CRecentFileList::UpdateMenu(pCmdUI). The parameter is a pointer to a CCmdUI object, that indicates to the UpdateMenu function the first item of the MRU list, which should be the item with the id ID_FILE_MRU_FILE1. If the CRecentFileList::UpdateMenu function were called always with the right pCmdUI, then there would be no problems (this function works Ok). Now, when and where is this function called? Well, only in one place, the CWinApp::OnUpdateRecentFileMenu function, the code of which is provided below:


void CWinApp::OnUpdateRecentFileMenu(CCmdUI* pCmdUI)
{
	ASSERT_VALID(this);
	if (m_pRecentFileList == NULL) // no MRU files
		pCmdUI->Enable(FALSE);
	else
		m_pRecentFileList->UpdateMenu(pCmdUI);
}

This function is the ON_UPDATE_COMMAND_UI handler for the menu item with the id ID_FILE_MRU_FILE1. Apparently, everything is right, the framework should be responsible of calling this function only when the m_nId member of the object pointed by the pCmdUI parameter is ID_FILE_MRU_FILE1 (as declared and implemented in the CWinApp's message map). The writer of this function however, forgot that the framework calls the OnUpdate function for the first menu item in a submenu also to update the submenu itself (which does not have an id). If that is the case, pCmdUI->m_pSubMenu points to the submenu, otherwise it is NULL (see technical note 21 for more information on command and message routing). Thus, the CWinApp::OnUpdateRecentFileMenu function should have been:


void CWinApp::OnUpdateRecentFileMenu(CCmdUI* pCmdUI)
{
	ASSERT_VALID(this);
	if (pCmdUI->m_pSubMenu!=NULL) // updating a submenu?
		return;

	if (m_pRecentFileList == NULL) // no MRU files
		pCmdUI->Enable(FALSE);
	else
		m_pRecentFileList->UpdateMenu(pCmdUI);
}

Now for the correction of the bug. We should obviously process the update command message ourselves, so using the ClassWizard, add an UPDATE_COMMAND_UI handler for the ID_FILE_MRU_FILE1 command to your CWinApp descendant class (I would call it OnUpdateRecentFileMenu also). In principle, we could write the handler as I said the original MFC function should have been written, but as we have it already as it is, we can save some code:


void CMyApp::OnUpdateRecentFileMenu(CCmdUI* pCmdUI)
{
	if (pCmdUI->m_pSubMenu!=NULL) // updating a submenu?
	{
		// update your submenu here, if you need to
		
		return;
	}
	
	CWinApp::OnUpdateRecentFileMenu(pCmdUI);
	return;
}

Well, that's it. I hope Microsoft will fix this bug somewhere in the near future. In the mean time, we can deal with it as described above.


Last updated: 21 November 1998



Comments

  • Still is a bug

    Posted by Andy on 01/04/2014 11:18am

    It's 2014 and this was never fixed in any service packs :)

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Confused by all the agile advice? Relax! With the Agile for Dummies eBook by your side you'll learn the fundamentals of agile and how to increase the productivity of your software teams while enabling them to produce higher-quality solutions that better fulfill customer needs much faster.

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

Most Popular Programming Stories

More for Developers

RSS Feeds