[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3037
  • Last Modified:

Need to disable PopUp Menu items

I need to disable the menu items that are not applicable at various places in the application.
The command messages are not being routed through the OnUpdate handlers.
I have looked at a few issues that talk about this. For example using "this" on the following does not work:
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
Attaching it to the mainframe does something but still not going through the handlers
void CEHRTreeCtrl::OnUpdatePopupPopulatenormalcase(CCmdUI* pCmdUI) 
{
	if (m_bWorkFlowTree || !IsPatientData())
		pCmdUI->Enable(false);
	else
		pCmdUI->Enable(true);
}
 
void CEHRTreeCtrl::OnContextMenu(CWnd*, CPoint point)
{
 
	// CG: This block was added by the Pop-up Menu component
	{
		if (point.x == -1 && point.y == -1){
			//keystroke invocation
			CRect rect;
			GetClientRect(rect);
			ClientToScreen(rect);
 
			point = rect.TopLeft();
			point.Offset(5, 5);
		}
 
		CMenu menu;
		VERIFY(menu.LoadMenu(CG_IDR_POPUP_EHRDECISION_TREE));
 
		CMenu* pPopup = menu.GetSubMenu(0);
		ASSERT(pPopup != NULL);
		CWnd* pWndPopupOwner = this;
 
		// this sets it for all menu items
		m_bHasChildren = IsNodeChildrenOnDemand();
		if(!m_bHasChildren)
		{
			pPopup->ModifyMenu( ID_EDIT_COPY, MF_BYCOMMAND, ID_EDIT_COPY, _T("&Copy Selected Item") );
			pPopup->ModifyMenu( ID_EDIT_CUT, MF_BYCOMMAND, ID_EDIT_CUT, _T("&Cut Selected Item") );
			CString strMenuItem = _T("&Delete Selected Item");
			if (GetSelectedCount() > 0)
			{
				 strMenuItem += _T("s");
			}
			pPopup->ModifyMenu( ID_EDIT_DELETE, MF_BYCOMMAND, ID_EDIT_DELETE, strMenuItem );
			pPopup->ModifyMenu( ID_EDIT_FIND, MF_BYCOMMAND, ID_EDIT_FIND, _T("&Find Item or Sub Tree") );
			pPopup->ModifyMenu( ID_EDIT_PASTE, MF_BYCOMMAND, ID_EDIT_PASTE, _T("&Paste Selected Item") );
		}
		
		pPopup->ModifyMenu( ID_POPUP_INSERTSUBTREE, MF_BYCOMMAND, ID_POPUP_INSERTSUBTREE, _T("&Insert Items After Selected Item") );
		
		if (!IsNodeManagementTree())
		{
			pPopup->DeleteMenu(ID_POPUP_ATTACHNODESTOSELECTEDFORM, MF_BYCOMMAND);
		}
		else if (IsFormManagementTree() || IsReportManagementTree())
		{
			pPopup->ModifyMenu( ID_POPUP_ADDSUBTREE, MF_BYCOMMAND, ID_POPUP_ADDSUBTREE, _T("&Add Multiple New Nodes") );
		}
		CWnd* pWnd = GetParent()->GetParent()->GetParent();
		pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
			this);
	}
}

Open in new window

0
GlennBrand
Asked:
GlennBrand
  • 4
  • 4
2 Solutions
 
DanRollinsCommented:
Have you seen this article:
   When Update Handlers Are Called
   http://msdn.microsoft.com/en-us/library/essk9ab2.aspx
I can't tell from your code, but... there has to be an ON_UPDATE_COMMAND_UI entry and (this is the most common oversight) there must also be an  ON_COMMAND entry somewhere with the same command ID
Also, command UI is usually in the MainFrame, so that's what you will typically used as the owning window in the TrackPopupMenu call
0
 
alb66Commented:
Instead of

                CWnd* pWnd = GetParent()->GetParent()->GetParent();
                pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
                        this);

try to use

                CWnd* pWnd = GetParentFrame();
                pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
                        pWnd);

See GetParentFrame details at
http://msdn.microsoft.com/en-us/library/6f45sskz.aspx
0
 
GlennBrandAuthor Commented:
I tried that and a frame window is returned but when I use it all the menu items are greyed out meaning that it can't find the message handlers that are working now in the tree. The frame window is to the property dialog box that contains the tree.

My question is why can it find all the message handlers for the messages them selles but not on the OnUpdate messages. It doesn't make sense.

Is there a way to redirect whatever messages to the tree itself?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
DanRollinsCommented:
What you describe is symptomatic of having an ON_UPDATE_COMMAND_UI entry and no ON_COMMAND entry (see the article I cited, above).  
I suggest using Spy++ and watch for the WN_INITMENUPOPUP message.  A CFrameWnd-derived object should get that message and do the command U/I enabling.
0
 
GlennBrandAuthor Commented:
Yes I had one for each one. To no avail. Even tried redirecting the message to the tree itself but no luck.
I finally found another solution.
I had to do what I did in the OnContextMenu in the code snippet attached.
Thanks for trying. I know this is a problem for many people.
		if (IsFormManagementTree() || IsReportManagementTree() || m_bWorkFlowTree)
		{
			pPopup->EnableMenuItem(ID_POPUP_POPULATENORMALCASE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_MOVESUBTREE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_EDIT_CUT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
		}
		if (m_bWorkFlowTree || IsDecisionTree())
		{
			pPopup->EnableMenuItem(ID_POPUP_ADDSUBTREE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_INSERTSUBTREEBEFORE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_INSERTSUBTREE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_SHOWEDITOR, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_SHOWSCRIPTEDITOR, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
		}
		if (!m_bWorkFlowTree && IsDecisionTree())
		{
			pPopup->EnableMenuItem(ID_POPUP_MODIFYITEMPROPERTIES, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_EDITITEMTEXT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_EDIT_CUT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_EDIT_COPY, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_EDIT_DELETE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_MOVESUBTREE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_EDIT_PASTE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_PASTEBEFORESUBTREE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
			pPopup->EnableMenuItem(ID_POPUP_PASTEAFTERSUBTREE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
		}

Open in new window

0
 
DanRollinsCommented:
For what it's worth:
I just looked at the source code for an old SDI project of mine.  It pops up a context menu when clicking on an item in a CTreeView-derived pane.  The enabling is done in the ON_UPDATE_COMMAND_UI handlers, and items are correctly enabled or disabled according to the specific context at the time of the pop up.
All I can say is that it does work as advertised in the MFC documentation.  I use:
   AfxGetApp()->m_pMainWnd
as the CWnd pointer in the fourth parameter in the TrackPopupMenu call (it is the pointer to my CFrameWnd-derived object.  In that module, CMainFrame, I have message map entries for both ON_COMMAND and ON_UPDATE_COMMAND_UI for each item in the popup menu.
My code in the CTreeView-derived object looks almost identical to yours (before you added the manual enabling).  All I can suggest is that you examine the actual values of constants such as ID_POPUP_MOVESUBTREE and see if they are unique (examine your resource.h file).  Also, each of my menu item command IDs is higher than 1000 (I vaguely recall that there was an issue with context help or something).  If you are not using CView- and CFrameWnd-derived objects, that might also affect the behavior.
In my case, the MainFrame gets a WM_INITMENUPOPUP message and breakpoints in the updateUI handlers immediately get hit.
0
 
GlennBrandAuthor Commented:
I tried using the main frame also. The menu changed completely with many greyed out options and some enabled functions. It was as if the main frame had other items it found with similar ID values. IN this case the tree is in a DLL so it is possible that some of the IDs are the same as in the main app.
But more importantly is it customary to use the main window then?
What is happening and how should I setup my handlers. None of the handlers seem to have been called in the tree class itself which currently works the way I coded it.
0
 
DanRollinsCommented:
It is the code in
   CFrameWnd::OnInitMenuPopup(...)
that cycles through the menu and calls the OnUpdateXxxx for each item.
CWnd::OnInitMenuPopup() is not a virtual function, so you can't override it in your view- or control- derived class object.
You can add a handler for WM_INITMENUPOPUP in some other window (such as your tree control).  It could be menu-specific (rather than generalized as is the one in CFrameWnd).  But it's lots more work, in that you need to decode the message parameters, walk the menu tree, etc.
So yes... it is customary (if not required) to put command handlers, and UI update handlers  in the main frame.   If doing so casues other menu items to be disabled unexpectedly, then you need to add command handlers and ui update handlers for them.
0
 
GlennBrandAuthor Commented:
My solution is the only other way from what I can tell besides what DanRollins writes.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now