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 » Properly Serializing GUI States with dynamically allocated Command IDs. Collapse All
Subject Author Date
Guillaume Provost Sep 12, 2003 - 12:09 PM

Are you guys currently using the Command Identifier as a save tag for saving GUI Layout and Customization? If I’m dynamically allocating command identifiers within my application:

    cmdItem = g_CmdManager->CmdAllocPtr(GetProfileName(), 0);

The actual command id for a given item becomes order dependant:

CExtCmdItem * CExtCmdProfile::CmdAllocPtr(
    UINT nCmdID // = 0 // 0 means any free in avail range
    )
{
    if( nCmdID != 0 && CmdIsRegistered(nCmdID) )
        return NULL;
    if( nCmdID == 0 )
    { // find free ID for new command
        nCmdID = 65534;
        if( !m_cmds.IsEmpty() )
        {
            while( true )
            {
                CExtCmdItem * pCmdItem = NULL;
                BOOL bExist =
                    m_cmds.Lookup( nCmdID, pCmdItem );
                if( bExist )
                {
                    ASSERT( pCmdItem != NULL );
                    nCmdID --;
                    if( nCmdID == 0 )
                    {
                        ASSERT( FALSE );
                        return NULL;
                    }
                    continue;
                }
                ASSERT( CExtCmdManager::IsCommand(nCmdID) );
                break;
            } // while( true )
        } // if( !m_cmds.IsEmpty() )
    } // find free ID for new command

    This is a significant problem: each time the allocation ordering changes (quite common an occurence in our case), the command Ids for given GUI items change.
    
    Should I use some kind of Name-based heuristic to generate a unique CommandID using a hash? Is there a way for me to change the keying mechanism you use to identify and store GUI layouts and customization information for a given GUI item? (ie: use names instead of CommandIds?)

    Guillaume.

Technical Support Sep 18, 2003 - 8:40 AM

Dear Guillaume,

We are sorry for the delay with replying to you.

Yes, we use command identifiers as unique tags. They all should be registered in the command manager. Furthermore, all the command tree nodes should also have identifiers which are registered in it. The best way for your task is to use pre-defined command ranges. For example, you can use command IDs in range 40000 - 60000 and store ID of the last allocated command. You should register these commands as well as their descriptions before restoring the command manager state and the customization subsystem state (and/or before constructing custom command trees). You should store the information about custom commands when you save the state of Prof-UIS subsystems. The CmdAllocPtr(nID=0) method allows you to allocate the command identifier with a specified nID value. We can help you code a simple class which will manage dynamic commands (allocation, serialization and command manager updating) and assign internal names to them.

Guillaume Provost Sep 19, 2003 - 11:49 AM

I think that my original post may have been misconstrued. My issue was mainly that my command IDs for a given item may change each time I run the application, since I dynamically allocate command IDs to the GUI items.
You guys already sent me everything I needed to do this (it actually runs and stuff, I’m just having some registry save/load issues between sessions).
This seems to be going against the whole system, so instead of fighting it, I’ll assign a few key elements a static, persistent command ID that PROF-UIs can always refer to when storing/reloading the GUI state of these items. Here are additional questions regarding this:

- Is there a way to completely disable saving/restoring of GUI layouts for certain windows? I cannot guarantee the command ID assigned to certain windows will stay the same, and they are generally not windows for which the layout is very important.

- We internally pipe all our GUI commands through a script system. What’s the easiest way for me to modify the customization dialog page to have an ’Add Command’ option where the user can add a totally new command using a simple text script that gets executed? (I can handle the execution aspects of things).

This way I’d have:
- Statically allocated GUI items (ie: Range 1000 - 5000)
- Dynamically allocated GUI items - Since command IDs in this range can be reused for multiple, different GUI items, I need to disable Save/Restore GUI layout, and customization (ie: Range 65535-60000) - Think of these as temporary/intermediary data views.
- Customized new GUI Commands created by the user (at run-time). These need to be serialized into the registry, and they are dynamically assigned a command ID at creation time. (ie: Range 50000 - 60000)

What I need from you guys:

- How do I add the ’new command’ option in the customization page
- How do I disable all save/load operations for a given CExtCustomizeCmdTreeNode object

Technical Support Sep 20, 2003 - 11:17 AM

Dear Guillaume,

You have a good task and we are especially interested in helping you because your project seems to fully use all customization features possible. This message describes the solution in general.
We need some more additional information so that we would provide you with ready-to-use code snippets.

Is there a way to completely disable saving/restoring of GUI layouts for certain windows?

You should create any bars after restoring UI layouts and destroy them before saving both UI and customization states.

We internally pipe all our GUI commands through a script system. What’s the easiest way for me to modify the customization dialog page to have an "Add Command" option where the user can add a totally new command using a simple text script that gets executed?
and
How do I add the "new command" option in the customization page?

The CExtCustomizeSite::OnCreateCustomizeForm() virtual method creates a customization property sheet and initializes all the pages. It puts CExtCustomizePageCommands object onto the property sheet. You should override the code for form creation and implement your commands page. It can be derived from the CExtCustomizePageCommands class. You can use a dialog resource similar to the Prof-UIS commands page (you need to add buttons like "Add Command To Selected Category"). As for creation of a new command, you have to allocate a new command identifier and modify the command tree node associated with the category content. A set of CExtCustomizeSite::CategoryGet...() methods allow you to access category data. These methods maybe useful for initializing categories.

How do I disable all save/load operations for a given CExtCustomizeCmdTreeNode object?

There is no way and there is no reason to disable customization features for a particular command node because it can hold both standard and your dynamic commands inside. We think the task may be construed in a different way. Suppose you have a frame-based application which displays different kind of data inside (e.g. different documents like). Some parts of the UI (bars and/or commands) are specific for the currently displayed data. Why cannot we store the dynamically constructed UI commands (e.g. script commands) with the data (or documents)? It is possible with Prof-UIS and this technique is implemented in MS Office.

We think all the questions will be solved much faster and easier if we make a template project, which fully meet your requirements. It is not a problem for us.

Guillaume Provost Sep 26, 2003 - 6:35 PM

"You should create any bars after restoring UI layouts and destroy them before saving both UI and customization states."

This makes it a bit too easy to cause regressions to occur. We are working with a reasonably large development team, and I can easily foresee windows getting created but not cleaned up before the UI layout is saved to the registry. PROF-UIs effectively crashes upon its UI State Load if it cannot find a Control Window with a specific Command ID. Given how large my system currently is, it would be much easier for me to be able to filter windows I want or do not want to save based on their command identifiers. If a command identifier is, say, above 0xf000, then I can simply conclude it was dynamically allocated and should not be saved (ie : I used AllocCmdPtr with a cmdId of 0). I don’t only have dynamically created/destroyed windows, I also have dynamic menu items that get temporarily appended to the ’view’ submenu, for example. The problem with these dynamic items is twofold:

- They may not exist at load time, PROF-UIs does not handle these situations very gracefully. (ie: it crashes)
- Since they are generally dynamically allocated through user action (ie: user opens a document), certain GUI items may effectively swap their command ids depending on the order in which a user has performed certain actions.

- Perhaps I can simply browse through the list of items that PROF-UIs saves just before calling the save functions and simply destroy all objects with an ID > 0xf000?

"We think all the questions will be solved much faster and easier if we make a template project, which fully meet your requirements. It is not a problem for us."

That’s very thoughtful of you, but I am porting about 80 000 lines of GUI code. Just outlining what they do will take longer than figuring it all out on my own. :) Asking you the more specific questions that cause me problems is a little easier for me - I’m sorry if I’m a time sink.

Technical Support Sep 29, 2003 - 1:10 AM

Dear Guillaume,

Your app should carefully track all the dynamic commands. Besides, we are sure your task will be much easier if you save a list of dynamic commands outside Prof-UIS Command Manager and Customize Site. In this case you need to restore dynamic commands before loading Prof-UIS states. Of course, this list should be saved when saving the UI state. This is a key to solve your task. If you need to make some toolbars specific for some UI state, create them programmatically as user-defined toolbars (they should be part of Customize Site). With this approach, you don’t need anything but your dynamic command list. Everything else Prof-UIS will manage automatically. You need to implement only one complicated piece of code that should add /remove a command both in the Command Manager and all the command tree nodes of the Customize Site (menubar/toolbars nodes and command categories).