Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » Noob Architectural question: Dynamically adding menu items Collapse All
Subject Author Date
Guillaume Provost Aug 18, 2003 - 4:49 AM

I’m currently porting a fully dynamic (ie: nothing comes from resources) GUI system to PROF-UIs. I found precious little example code for this in your samples. Here’s what I currently do - can you guys enlighten me as to whether there is a simpler (or safer) path to the current implementation?

- Create the CExtControlMenuBar
- Dynamically add items into its underlying CMenu using InsertMenuItem
- Calling g_CmdManager->UpdateFromMenu(myMenu)
- Retrieving the CmdItem with g_CmdManager->CmdGetPtr(ID)
- Set tooltips, create a CExtCmdIcon, assign a bitmap, set flags.
- Calling CExtControlMenuBar::UpdateMenuBar( )

The problem with this approach is that it relies on talking to the underlying mfc class. So that, if I want to add a control button, I basically have to duplicate the code, and I can potentially get ID clashes occuring on command ids. Is there a way for me to do something like this:

- If it does not yet exist, register with the Command Manager
- add bitmaps, text and so on
- Add the resulting command to a toolbar or menu.

I was specifically a bit confused by the differences between CExtCmdManager::AllocCmdPtr( ) and the CmdSetup( ) path that is currently used internally inside your UpdateFromMenu( ) code. Please note that I’m also using the CCustomizeSite implementation. So changes that I make into the toolbars/menus need to be reflected (supported) when I setup the ’default’ customize state (using MenuInfoAdd( )).

Thanks!
Guillaume.

Technical Support Aug 18, 2003 - 10:20 AM

Dear Guillaume,

Of course, Prof-UIS allows you to solve all your tasks. The most appropriate way to do this is to use its customization subsystem. So, the following will be only related to the task solution based on the customizable features of the library.

Before we start, please note: Prof-UIS 2.22 is a first version that includes customization and only several basic methods of CExtCustomizeSite are covered in the help so far. But we have already finished full customization with support for keyboard and options pages, unified resizable text/combo fields in menus and toolbars, show/hide buttons menu for each bar etc. The full description of the customization subsystem is in work now. So, please consult with us to finish you work faster.

Let’s start with the architecture of the customization subsystem.

Both toolbars and menus are based on the Prof-UIS internal data type called command tree when the customization subsystem is on. The command tree is implemented in the CExtCustomizeCmdTreeNode class. It is also used for storing the command groups and document menus. This makes your task very easy. You should simply get the root command tree node pointer for any named document menu. Then you can modify this tree and update the visible menu bar. All the changes in the menu become visible. In the version 2.23 (to be released) each named document menu also holds the customizable accelerator table.

The command manager is still used to store initial information for all the commands. Each command tree node stores the current state of each command (customized icon, modified text etc.).

The CExtCustomizeSite class stores all the customization information about all toolbars and menus in a frame window. It is handy to use this class as a second base class of CMainFrame.

Now lets’ take a look at the customizable projects in details:
There are two customizable samples in the library: MDI sample DrawCli and SDI sample Bitmap Editor.

If we have already created a new project and derived the main frame window from the customize site, then we need to add initialization code for customization features. The initialization is located in CMainFrame::OnCreate() before loading the bars state (the customization subsystem may create user-defined toolbars here). CExtCustomizeSite class stores a named collection of document menus for the menu bar (one for SDI, 2 or more for MDI). The DrawCli sample registers "Default" and "Document" menus. The BitmapEditor registers the "Default" menu only. You may see how CExtCustomizeSite::MenuInfoAdd() is invoked in these two samples. Then CExtCustomizeSite::EnableCustomization() enables customization in the frame window. Next step is to register command categories (displayed in the "Commands" tab). The CExtCustomizeSite::CategoryUpdate(ID_MENU_RESOURCE) registers several categories which are based on the top-level popup sub-menus. It is possible to setup categories without menu resources using other versions of CategoryUpdate. The CExtCustomizeSite::CategoryMakeAllCmdUnique() removes repeated command entries in each registered category. The CExtCustomizeSite::CategoryUpdateAllCommands() generates standard "All commands" category with the sorted list of commands (based on previously registered categories). The CExtCustomizeSite::CategoryAppenNewMenu() appends the standard "New menu" category. The final step is invoking of CExtCustomizeSite::CustomizeStateLoad(): it loads the command trees for all the menus and toolbars, creates user toolbars if any.

The Prof-UIS customization subsystem does not require de-initialization. You may find invoke of CExtCustomizeSite::CustomizeStateSave() in the CMainFrame::DestoyWindow(). It is required to store the last state for all the toolbars and menus.

How to initialize dynamic resources?


  • In the CMainFrame::OnCreate(), after registration of command profile and before creation of menubar and toolbars, please register all the commands in the command manager;

  • Before CExtCustomizeSite::EnableCustomization(): this is the valid point for initial construction of document menus via modification of their command trees;



How to get the command tree pointer for the named document menu?
There are two command trees for each document menu. One is the initial command tree which is using for resetting menu state. Other is the current menu command tree. Initially these trees are equal.
CExtCustomizeCmdTreeNode * pNodeInitial = CExtCustomizeSite::MenuInfoGetByName( _T("Document") )->GetNode(true);
CExtCustomizeCmdTreeNode * pNodeCurrent = CExtCustomizeSite::MenuInfoGetByName( _T("Document") )->GetNode(false);

If you have modified pNodeInitial, you need to copy it into the pNodeCurrent:

*pNodeCurrent = *pNodeInitial;

The CExtCustomizeCmdTreeNode class provides a set of methods for accessing command properties and tree navigation. Each command tree node should have a command identifier which is registered in the command manager.

Please let us know if you have any questions.

Guillaume Provost Aug 19, 2003 - 6:14 PM

This does’nt help me. I need to know how to construct and change the UI in *code*, not how to set it up for the user to change it at run-time. All your samples, wether they support the CExtCustomizeSite or not, take all their GUI definitions from resources, not actual code.

I can do this two ways. Either:

-----------------------------------------------------

#1 - Change the underlying MFC control items directly, and then refresh both the Command manager and the CustomizSite from it

CExtMenuControlBar menuBar;

menuBar.Create(NULL, this, ID_MYMENUBAR)

// Note the absence of any "LoadFromXXX"!

// Now add the items
menu.GetMenu()->InsertMenuItem( ... )
menu.GetMenu()->InsertMenuItem( ... )
menu.GetMenu()->InsertMenuItem( ... )

// Update the command manager
g_CmdManager->UpdateFromMenu(...,menu->GetSafeHmenu()));

// Setup extended PROF-UIs specific info:
    
CExtCmdItem *pCmdItem = g_CmdManager->CmdGetPtr( ... )
pCmdItem->sToolBarText = ...; pCmdItem->sStatusText = ...; // etc...

pCmdItem = g_CmdManager->CmdGetPtr( ... )
pCmdItem->sToolBarText = ...; pCmdItem->sStatusText = ...; // etc...

pCmdItem = g_CmdManager->CmdGetPtr( ... )
pCmdItem->sToolBarText = ...; pCmdItem->sStatusText = ...; // etc...

// Assign an icon
CExtCmdIcon *cmdIcon = g_CmdManager->CmdGetIconPtr(...);
cmdIcon->AssignFromHBITMAP( ... )

// Update the GUI component
myBar.UpdateMenuBar();

// Update the customize site
CExtCustomizeSite::CategoryUpdate(myBar.GetMenu()->GetSafeHMENU());

-----------------------------------------------------
or

#2 - Add the items into Prof-UIS directly, then insert them into the controls

<Add, register the items directly with the CExtCustomizeSite and
the CExtCommandManager I need help on how to do this.>

CExtMenuControlBar menuBar;
menuBar.Create(NULL, this, ID_MYMENUBAR)

<Update ’menuBar’, I’m guessing I’d do this using the CExtCustomizeSite (?), to insert
my new commands in it>

------------------------------------------------------
My question is:
- should I be doing #1 or #2?
- if I should be doing #2, how do I add items directly into both the command manager and the CustomizeSite?
- How do I use the CExtCustomizeSite to directly append Commands into menus and toolbars?

Thanks!
Guillaume

Technical Support Aug 20, 2003 - 4:14 AM

Dear Guillaume,

You have correct understanding of the dynamic menu building task. You should use the first way if you don’t need the customization features. You should use the second way in other case. The second way is similar to first one, but requires additional initialization of customize site data. To avoid the long and complicated messages here we decided to code an example for you. This should take less than a day. Example will use on-the-fly constructed menu-bar and support the customization. You should receive a letter with attached ZIP file today.

Best regards,
Technical Support Team.

Guillaume Provost Aug 21, 2003 - 10:57 PM

Hey! This is just a reminder on this. I don’t seem to have received a mail with a zip file yet. By the by, writing a sample is real nice of you guys, but we can compare notes as well (ie: I don’t want to suck up all of your time). If you guys can give me the general gist of operations to perform in what order, I don’t mind digging into your code to figure out the details. I just need a starting point on the architecture. Ie: Do I add to the Command manager first? Using AllocPtr( ) or CmdSetup( )? Or do I add directly to the CustomizeTreeNodes? Give me a place to start, and I can wing it from there.

Thanks!
G.

Technical Support Aug 22, 2003 - 4:15 AM

Dear Guillaume,

Please believe us, an e-mail has been sent to your address at guillaume@pseudointeractive.com. And we’ve received a delivery notification from your mail server! But we haven’t yet received a read notification from your e-mail client software. Anyway, we’ve sent one more e-mail on the safe side.

The TestDynRes sample attached is very simple. You need to take a look at the CMainFrame::OnCreate() method. All the required steps and comments can be found there. We think this is the most appropriate support for your current task. The e-mail also describes a sequence of operations for initialization of dynamic resources.