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

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

Most Popular Programming Stories

More for Developers

RSS Feeds