How to append a dynamic menu item after call CMenu::LoadMenu? - windows

In my project, there is a menu that need to be appended an item dynamically.
In original code, items in the menu are stationary. So the menu is defined in the resource file:
IDM_SERVER_OPTIONS MENU DISCARDABLE
BEGIN
POPUP ""
BEGIN
MENUITEM "&Connect", IDC_LAUNCHITEM_CONNECT
MENUITEM "&Delete", IDC_REMOVE_SERVER
END
END
and is loaded in the code:
CMenu menu;
menu.LoadMenu(IDM_SERVER_OPTIONS);
Now, there is a new requirement that need to append a dynamic menu item after load the resource menu. I referred this aricle:
Dynamic menu using mfc
Followed it, I wrote these code:
CMenu menu;
menu.LoadMenu(IDM_SERVER_OPTIONS);
CMenu *autoConnectMenu = new CMenu;
autoConnectMenu->CreatePopupMenu();
autoConnectMenu->AppendMenu(MF_STRING | MF_ENABLED,
IDC_MENU_AUTO_CONNECT_SERVER,
utils::LoadString(IDS_MENU_AUTO_CONNECT_SERVER));
menu.AppendMenu(MF_POPUP,
(UINT)autoConnectMenu->m_hMenu,
L"auto connect server");
Unfortunately, it doesn't work. The new menu item "auto connect server" can't be displayed.
Then, I tried the HMENU function:
CMenu menu;
menu.LoadMenu(IDM_SERVER_OPTIONS);
AppendMenu((HMENU)menu.GetSubMenu(0),
MF_STRING | MF_ENABLED,
IDC_AUTO_CONNECT_SERVER,
utils::LoadString(IDS_MENU_AUTO_CONNECT_SERVER));
It works fine!
I want to know what problem in my former code? Appreciate!

I think that I have found the issue. I should have called
menu.GetSubMenu(0)->AppendMenu(...);
instead of
menu.AppendMenu(...);

Related

Delphi form menus

So I have two menu's. When I click a button on menu 1, it creates menu 2, then menu 1 hides itself. After that I want to go back to menu 1 and hide menu 2.
How do I keep a reference to menu 1 in menu 2? Then if I want to go back to menu 2 I don't want to create a new instance, I want to use the already created one. How do I do that?
I know this may be easy but I find Delphi extremley confusing and can't seem to find a way out of it.
Thanks!
If you mean Main menu when you say "form menu" then you can have only one actual TMainMenu component on a form.
Dynamically creating a new TMainMenu is doable, but involves message handling to postpone the deletion of the exisiting TMainMenu to then be able to create a new one. The reason is that you can not delete a menu in the OnClick handler of one of the menu's items.
Let me suggest an easier way to achieve something similar by hiding / showing branches of a single TMainMenu as follows:
Drop a TMainMenu on the form and write menu items as usual. In my example I created two branches, one named MenuA and the other MenuB. Under these I added menu items, of which the first one (you are free to choose which one you use) activates the other menu branch and hides it's own branch. And visa versa for the other one.
Here's the menu part of the form in text view:
object MainMenu1: TMainMenu
Left = 112
Top = 48
object MenuA: TMenuItem
Caption = 'MenuA'
object Item11: TMenuItem
Caption = 'MenuB'
OnClick = Item11Click
end
object Item12: TMenuItem
Caption = 'Item12'
end
end
object MenuB: TMenuItem
Caption = 'MenuB'
object Item21: TMenuItem
Caption = 'MenuA'
OnClick = Item21Click
end
object Item22: TMenuItem
Caption = 'Item22'
end
object Item23: TMenuItem
Caption = 'Item23'
end
end
end
And here is the code for the menu clicks. Note that I make the second menu branch hidden in the forms OnCreate even. Instead, you can of course set the Visible property to False at design time, in the Object Inspector.
procedure TForm9.FormCreate(Sender: TObject);
begin
MenuB.Visible := False;
end;
procedure TForm9.Item11Click(Sender: TObject);
begin
MenuB.Visible := True;
MenuA.Visible := False;
end;
procedure TForm9.Item21Click(Sender: TObject);
begin
MenuB.Visible := False;
MenuA.Visible := True;
end;

E4 RCP How to set selection of ToolBarItem that contains Radio Buttons

In Eclipse E4 (Luna), using the application model to create parts, handlers, commands, handled menu items etc, (these are not created programatically). I have a toolbar. This contains a sub-Menu item called "Filter" that contains another sub-menu of two filters. The two filters are two Handled Menu Items which are set up as "Radio" Buttons.
When I select the appropriate in the UI of my running app from the selection, the Radio button switches just fine to the selected Item. However I would like this selection to update (deselecting one Radio button and selecting the appropriate radio button of the handled menu item) when my ViewPart changes through other UI selection. Currently my ViewPart updates, but the Radio buttons are on the same previous selection through the UI.
Is there a way in which I get access both Handled Menu Item's IDs and set the selection (one to false, the other to true) when the viewer is updated.
Image of design is attached below:
Hierarchy of the application model is as follows:
Thanks in advance,
Marv
You can use the model service to find menu items. Use something like:
#Inject
EModelService modelService;
#Inject
MApplication app;
List<MMenuItem> items = modelService.findElements(app, "menu item id", MMenuItem.class, Collections.emptyList(), EModelService.IN_MAIN_MENU);
Once you have the MMenuItem you can call the setSelected(boolean) method to change the selection.
To find a menu item which is in a Part menu use:
modelService.findElements(app, "menu item id", MMenuItem.class, Collections.emptyList(), EModelService.IN_PART);
(IN_PART argument instead of IN_MAIN_MENU).
You could also specify the MPart rather than the Application as the first argument to findElements which may speed up the search.
For menus as a child of a Tool Bar Item it appears that the model services cannot find these directly. However you can find the Tool Bar Item and look at the menu yourself:
List<MToolItem> items = modelService.findElements(app, "tool bar item id", MToolItem.class, Collections.emptyList(), EModelService.IN_PART);
MToolItem item = items.get(0);
MMenu menu = item.getMenu();
List<MMenuElement> children = menu.getChildren();
... search menu elements
I solved this by starting with MPart PartID and drilling down to the HandledMenuItems on which I wanted to set the Radio Button selections, then setting the selection property for each individual HandledMenuItem.
This can probably be refactored to be more concise, but I've left the code with each step to have the solution easier to read.
BTW, in every instance / combination of the EModelService methods, the list returned a size of 0. So I'm not certain if that will work for what I'm trying to achieve. The following does work, although I'm not certain it is the most efficient means.
I hope this helps others.
// Get view part
MPart viewPart = _partService.findPart("part_id");
// get list of all menu items from the Part
List<MMenu> viewPartMenu = viewPart.getMenus();
// Get list of ViewMenus from viewPartMenu there is only one View Menu so it will be index 0
MMenu viewMenu = viewPartMenu .get(0);
// Get list of MMenuElements from the viewMenu - the children in the view menu
List<MMenuElement> viewMenuElements = viewMenu.getChildren();
// This gets me to the 2 HandledMenuItems
// Upper Most HandledMenuItem Radio Button is at viewMenuElements index 0. This is cast to MHandledMenuItem
MHandledMenuItem upperHandledMenuItem = (MHandledMenuItem) viewMenuElements.get(0);
// Set Selection
upperHandledMenuItem.setSelected(false);
// Lower Most HandledMenuItem Radio Button is at viewMenuElements index 1. This is cast to MHandledMenuItem
MHandledMenuItem lowerHandledMenuItem = (MHandledMenuItem) viewMenuElements.get(1);
// Set selection
lowerHandledMenuItem.setSelected(true);

What does & mean in a MENUITEM in a .rc file?

I am a beginner in windows programming. I have seen a .rc file which looks like this
IDR_MAINFRAME MENU PRELOAD DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New", ID_FILE_NEW
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM SEPARATOR
MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP
MENUITEM SEPARATOR
MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_APP_EXIT
END
END
Can someone explain me what does & mean in MENUITEM "&New"
and what does it mean in MENUITEM "E&xit" ?
& defines accelerator for the entry - so menu entry corresponding to "&File" can be selected by pressing "F" when menu is active or "Alt+F" for top level choices.
Same applies to dialog resources.

Duplication of menu items in Window Menu of CMFCMenuBar

I ported my MFC application to Feature pack.When i try to insert a new sub menu/popup menu to CMFCMenuBar, the menu items in "Window" menu gets duplicated. Kindly help me. I used the below code to insert submenu.
CMenu* pMenu;
HMENU hMenu = m_wndMenuBar.GetHMenu();
ASSERT(::IsMenu(hMenu));
pMenu = CMenu::FromHandle(hMenu);
pMenu = pMenu->GetSubMenu(2);
pMenu->InsertMenu(2, MF_BYPOSITION ,
(UINT)ID_SORTING_SORTBYACCESS, _T("My Menu"));
m_wndMenuBar.CreateFromMenu(hMenu, false, true);

how to add message map to dynamic menu item in MFC

I writing a MFC which has a listview control. When the user right clicks any item , I am generating a dynamic menu item with that text that is selected in listview. Everything is displaying properly, but I do not know how to add a message map to that dynamic menu item.
Any help?
void CMyListDlg::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
int nIndex = m_List.GetSelectionMark();
CString pString = m_List.GetItemText(nIndex,1);
CMenu menu, * pSubMenu;
int pos=0;
menu.LoadMenu(IDR_MENU1);
pSubMenu = menu.GetSubMenu (0);
pSubMenu->DeleteMenu(0,MF_BYPOSITION);
pSubMenu->InsertMenu(pos,MF_BYPOSITION,NULL,pString);
CPoint oPoint;
GetCursorPos (& oPoint);
pSubMenu-> TrackPopupMenu (TPM_LEFTALIGN, oPoint.x, oPoint.y, this);
*pResult = 0;
}
At the moment you are inserting the menu item with ID = 0 (NULL). That way you can't figure out which command was pressed. You have to assign an ID to the item, the simplest one is to
#define WM_MYMESSAGE WM_USER + 1
then you insert it like this:
pSubMenu->InsertMenu(pos,MF_BYPOSITION,WM_MYMESSAGE,pString);
If you override OnCommand for your window, you get your ID as wParam.
To actually figure out what happened, store some additional information in another class member, like m_nLastItemClicked or ... you get the idea?!
Check the MFCIE sample, it generates a favorite menu from the user's favorite folder and navigates to the favorite url when a favorite menu item is clicked.
Just add ON_COMMAND (and ON_UPDATE_COMMAND_UI if necessary) handlers for the menu items' IDs on your class.

Resources