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

  • Live Event Date: September 23, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT The cloud is not just about a runtime platform for your projects – now, you can do your development in the cloud, too. Check out this upcoming eseminar to learn how the cloud improves your development experience and team collaboration. Join Dana Singleterry, Principal Product Manager for Oracle Dev Tools, as he discusses how to simplify every aspect of the development lifecycle, including requirements gathering, version management, code …

  • Lenovo recommends Windows 8 Pro. "I dropped my laptop getting out of the taxi." This probably sounds familiar to most IT professionals. If your employees are traveling, you know their devices are in for a rough go. Whether it's a trip to the conference room or a convention out of town, any time equipment leaves a user's desk it is at risk of being put into harm's way. Stay connected at all times, whether at the office or on the go, with agile, durable, and flexible devices like the Lenovo® …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date