mfc >> dynamic menus

by Bill Brehm » Sat, 13 Aug 2005 12:41:55 GMT

I want to be able to create a hierarchy of menus under the view menu. I
don't know at design time how many items will be under each submenu.

I have been able to access and add to the view menu itself. By I have not
been able to add anything under that added menu. I know it shuold be a popup
menu. but when I make it a popup, I get an assert when I try to open the
view menu. Here's what I have so far (some experimentation still remains):

m_pWndMenu = GetMenu();
//int count = m_pWndMenu->GetMenuItemCount();
//CString string;
//m_pWndMenu->GetMenuString(2, string, MF_BYPOSITION);
CMenu *pViewMenu = m_pWndMenu->GetSubMenu(2); // gets view menu.
pViewMenu->InsertMenu(0, MF_BYPOSITION | MF_SEPARATOR);
CMenu objectMenu;
objectMenu.CreateMenu();
pViewMenu->InsertMenu(0, MF_BYPOSITION | MF_STRING | MF_POPUP,
(int)objectMenu.m_hMenu, "Objects");
CMenu *pObjectMenu = pViewMenu->GetSubMenu(0); // gets object menu
pObjectMenu->InsertMenu(0, MF_BYPOSITION | MF_STRING, 101, "Object 1");
pObjectMenu->InsertMenu(0, MF_BYPOSITION | MF_STRING, 102, "Object 2");

What am I doing wrong and how do I fix it?

Also, will have to call a function and/or work with OnUpdateCmdUI(). How do
I dynamically create IDs for these when I won't know in advance how many
levels deep and how many items at each level. (I have seen duplicate IDs in
resource.h. But I don't know where duplicates are allowed without causing a
conflict.) I have looked at the dynamenu example, but they are only adding
into a menu that already exists and they are not creating a popupmenu.
Furthermore, they have predefined all their IDs because they know in advance
that they will support four colors.

Thanks for any assistance...




mfc >> dynamic menus

by Ajay Kalra » Sat, 13 Aug 2005 13:21:03 GMT


Hello Bill Brehm" don't want any spam,


You may not have a View menu when you are doing this. Is it MDI or SDI? For
MDI, for example, handle of the window that you want is a public member of
doctemplate(I think its m_hwndShared or some such thing). This is the menu
handle that you want to deal with.

--
Ajay Kalra [MVP - VC++]
XXXX@XXXXX.COM





mfc >> dynamic menus

by David Ching » Sat, 13 Aug 2005 13:31:27 GMT





Most likely your objectMenu is going out of scope and being destroyed. Make
objectMenu a member of a class (perhaps the CWnd that owns the menu) that
will stick around for the lifetime of the menu.



Each command ID generated by the menu items must be unique. Beyond that,
there is no restriction. Perhaps you could use a counter, initialized to a
value greater than any of the existing menu item command id's, and increment
it each time you add one of your own. (I think Windows restrict command
id's to some range, so you can't use just any number.) Then you'd have to
remember which ID was for what function, so you could properly handle the
commands when they are selected from your menu.

-- David
http://www.dcsoft.com




dynamic menus

by Bill Brehm » Sat, 13 Aug 2005 16:17:15 GMT

es, you are right about the variable going out of scope. I'm new at Windows
programming, so I keep getting tripped up by little things like this.
Thanks, I'm able to move further now.

So every menu item ID within the entire project must be unique, but it
doesn't matter if the ID is reused by a button or string or any other
control? I see the standard menu ID have a special range stating near
0xE000, so I will stay away from that. I have to be careful that I don't use
an ID that the class wizard may later assign to another menu that is not
dynamically generated. Is it safe to use WM_USER and add one for each new
dymanic menu item?

More importantly, how do I 'connect' these to OnDynamicMenuItem() and
OnUpdateDynamicMenu()? Since I am creating the menus at runtimme, I can't
depend on compile time functions. That means I would prefer to have the
entire range of these dynamic menus be 'connected' to single functions that
are passed the ID, so they can look up the correct menu object to access. I
could put the dynamic menu item along with its two functions into a class.
But I still don't know how to programmatically add the 'connection' from the
ID to the functions.

Thanks...


"David Ching" < XXXX@XXXXX.COM > wrote in message
news:PAfLe.1308$A% XXXX@XXXXX.COM ...




dynamic menus

by Bill Brehm » Sat, 13 Aug 2005 16:18:54 GMT

It is SDI, but I might want to change it to MDI, as you might have seen in
another post.

David Ching solved my problem with the ASSERT. My CMenu variable was going
out of scope and being destroyed.







dynamic menus

by Scott McPhillips [MVP] » Sat, 13 Aug 2005 19:50:12 GMT




Manually add ON_COMMAND_RANGE to the message map in the class that
should receive the menu commands. It has to be a window class or
CDocument. Similarly, you can add ON_UPDATE_COMMAND_UI_RANGE. The
message handler function will be passed the ID of the selected menu item.

--
Scott McPhillips [VC++ MVP]



dynamic menus

by Bill Brehm » Sat, 13 Aug 2005 20:34:56 GMT

Brilliant, thanks. Can the start and end IDs be variables, so that as I add
new dynamic menus and update the end variable, the range will be updated?









dynamic menus

by David Ching » Sat, 13 Aug 2005 22:40:58 GMT










No, the message maps only take constants. You can #define the begin and
end, then ensure the end is greater than your incrementing variable used to
assign command id's to the menu items.

-- David




dynamic menus

by David Ching » Sat, 13 Aug 2005 22:43:20 GMT





Glad that solved it.



Actually, all WM_COMMAND id's need to be unique. Buttons also generate
WM_COMMAND ids, so these can't overlap the menu items. I believe the id is
specified in the WPARAM of the WM_COMMAND message. The WM_COMMAND doc may
list the valid ranges of user commands.

Cheers,
David
http://www.dcsoft.com




dynamic menus

by Scott McPhillips [MVP] » Sat, 13 Aug 2005 23:48:07 GMT




No, the message map is a static structure defined at compile time. But
the effect you want can be achieved by reserving ranges of IDs in
resource.h. There are enough unused number ranges that you could have
many ranges of 100+ IDs that you could assign as you like when
dynamically creating menu items.

--
Scott McPhillips [VC++ MVP]



dynamic menus

by Tom Serface » Sun, 14 Aug 2005 02:26:09 GMT

You can also use OnInitPopupMenu() if you want to enable or disable some of
the entries. I typically use entries in a range and use ON_COMMAND_RANGE(),
but I've had trouble with the UI counterpart unless it's a frame window
menu. If you are doing this in a popup menu (context sensitive) you might
find this handy. Also, you can define your range of commands in the string
table to reserve the ID's. I.E., there may be other ID's 101, 102, etc. so
make sure you don't get them duplicated somehow.

http://www.codeproject.com/menu/menu_non_framewnd.asp

Tom







dynamic menus

by Bill Brehm » Mon, 15 Aug 2005 23:59:01 GMT

hanks for all the tips so far. They've been a big help. I'd like to ask a
question about the bigger hierarchy picture.

I'm trying to put together an SDI foundation that can be used for several
future projects. The projects will be in the machine control area, but
that's not really important. The thing is, these machines will vary hugely
from one another, but they will all have basic machine control objects, like
state machines, motors, sensors, solenoids, etc. For each of these types of
objects, I'd like to have a dialog available for the user to interace with
them. The GUI can't know in advance the number of objects or even the number
of types of objects. Yet under the View menu, I would like to make the full
hierarchy of object dialogs available. The menu items here will just be to
show or to hide the dialogs and they will be able to display a check mark to
indicate if the dialog is shown or hidden.

Okay, I figure I need a CObjectDialog from which all the dedicated object
dialogs will be derived. I will also need something like a CDynamicMenu. I
know I will need message map entries for ON_COMMAND_RANGE and
ON_UPDATE_COMMAND_UI_RANGE. Should they be in the View or the Doc or the
Mainframe? I think the functions for OnCommandRange and
OnUpdateCommandUIRange should be in the CDynamicMenu class, as it will
register all the types and instances of machine control objects and be able
to look up the correct dialog to show and hide and keep track of the check.
But can the message map in a view or doc or mainframe be mapped to a
function in another class? Assuming I might have to have more than one
instance of dynamic menu hierarchy, where should I locate them - globally,
as a static inside the CObjectDialog class, etc?

I appreciate any comments and questions.


"Bill Brehm" <don't want any spam> wrote in message
news:% XXXX@XXXXX.COM ...




dynamic menus

by Scott McPhillips [MVP] » Tue, 16 Aug 2005 07:14:15 GMT




The menu belongs to the CMainFrame. (See GetMenu.) The toolbar, if any,
also belongs to the CMainFrame. So I would suggest that your dynamic
menu management and message handlers also belong in CMainFrame.

Your CMainFrame could have a member CDynamicMenu, so you could have more
than one instance if necessary. The only way to handle the messages in
a non-CWnd class of your own is to put the message handlers into a CWnd
class (such as CMainFrame) and make one-line calls from the message
handlers to functions in your non-CWnd class.

--
Scott McPhillips [VC++ MVP]



dynamic menus

by Bill Brehm » Tue, 16 Aug 2005 16:29:02 GMT

Thanks. I am looking at an SDI app built by the wizard and I see the view
has the menu's message map handlers like:

ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

so I guess it's okay to add mine there. I suspect the answer will be no, but
I'll ask anyway. Is it possible to dynamically add and subtract message
mappings during runtime?

Bill









dynamic menus

by Scott McPhillips [MVP] » Tue, 16 Aug 2005 20:34:10 GMT




As you suspect, it is not possible to dynamicaly add and subtract
message mappings at runtime. But there is no need to. Plan and reserve
the maximum ID ranges you will use for various kinds of dynamic menu
commands. You can #define these constants in resource.h. Use
ON_COMMAND_RANGE in the message map to map each range you will be using.
Then every menu command within a certain range will call a function
you define, and it will be passed the clicked ID.

--
Scott McPhillips [VC++ MVP]



Similar Threads

1. Dynamic Menu Positioning - CSharp / C#

2. Dynamic menus

Just couldn't find any article in MSDN about dynamic menus. I know i can
create menus dynamically in run time using the information from a database
combined with System.Refletion, but didn't find any real example.
does anyone know where i could find it?
thanks a lot.


3. How to dispose dynamic menu items??? - CSharp/C#

4. Dynamic Menu

Hi All
 I need Dynamic Menu in asp.net project
Using Javascript and child window's should be control in  aspx page wise
Please send me related links

Regards
Venu


5. Dynamic Menus in C# and Popup event handler - CSharp/C#

6. Dynamic Menu Structure

I am having an issue with Context Menus, and can't readily find a resource on 
the net to help.  

I have a menu structure that is static with one menuitem (mnuCurrentTasks) 
that we would like to have a submenu off this item.  This submenu will be 
dynamically generated every X minutes.  It will list all the current tasks 
assigned to a user, with an onlick event (would also be nice to have a mouse 
over option, to display more text).  

If anyone can help:  it would be greatly apprecaited.

Thanks
Andy

7. Dynamic Menu Creation - CSharp/C#

8. Dynamic Menu

Typically you would do this in response to OnInitMenuPopUp and  manipulate
meus. However, you can also do it by going to the appropriate menu handle
that is store in the doctemplate.


"sreekanth" < XXXX@XXXXX.COM > wrote in message
news:006b01c368c1$25bff5e0$ XXXX@XXXXX.COM ...
> Hello,
>   Can any body tell me the procedure to add new menuitems
> to the menu dynamicaly ? Moreover I want to show the
> string for display, which ever I was selected from the
> menu.
>
> thank U
> sreekanth