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 » Prevent user to customize Menu - ContextMenu Collapse All
Subject Author Date
Stephan Finkler Dec 20, 2004 - 9:34 AM

I have inherited CMainFrame from CExtCustomizeSite to customize my app.

How can I prevent that the user can modify some menus?
(the menu can have ComboBox etc.)

How can I prevent the context menu for a menu when it is in configuration mode?

Thanks for your help

Technical Support Dec 21, 2004 - 8:10 AM

Dear Stephan,

Thank you for the interesting question. The easiest way to prevent the drag-and-drop operation for any command in a menu/toolbar is to override the following method of the CExtCustomizeSite class:

virtual bool OnCanDragCustomizeCommand(
    CExtCmdItem * pCmdItem
    ); 

If your method returns false for some commands, then you will not be able to drag-and-drop these commands wherever they are. But if you need to prevent the drag-and-drop for some command items somewhere in a menu/ toolbar, then you need to override this method of the CExtCustomizeSite class:
virtual bool DoDragCmdNode(
    ICustomizeDropSource * pCustomizeDragSource,
    CExtCustomizeCmdTreeNode * pNodeI,
    CExtCustomizeCmdTreeNode * pNodeC,
    RECT & rcItem
    ); 
Your method should return false if the pNodeC command tree node is not enabled for drag-and-drop. Otherwise, call the parent method. The pCustomizeDragSource parameter may be converted into CExtCustomizeCommandListBox, CExtPopupMenuWnd or CExtToolControlBar with the dynamic_cast operator. This is the easiest way to detect from where the user makes an attempt to drag the command tree node. The universal way of detecting the location of the pNodeC command tree node is to walk through its parent nodes by invoking pNodeC->GetParentNode() and comparing each parent command tree node with the root nodes of all the toolbars and document menus.

The following method of the CExtCustomizeSite class fills the lists with pointers to all the basic and user-defined CExtToolControlBar objects:
virtual void BuildToolbarLists(
    CPtrList * pListBarsBasic,
    CPtrList * pListBarsUser = NULL
    ); 
The below method of the CExtCustomizeSite class returns the root node of the toolbar object (you need set bInitialNode parameter to false):
CExtCustomizeCmdTreeNode * GetToolbarCmdNode(
    CExtToolControlBar * pBar,
    bool bInitialNode = false
    ); 
The returned pointer to the command tree node can be compared with parent nodes of any node.

The following code returns the root node of the document menu that is currently used by the menu bar:
CExtCustomizeSite::CCmdMenuInfo * pCmdMenuInfo =
     pCustomizeSite->MenuInfoFindForMenuBar()
 ASSERT( pCmdMenuInfo != NULL );
CExtCustomizeCmdTreeNode * pMenuRootNode =
    pCmdMenuInfo->GetNode( false );
        ASSERT_VALID( pMenuRootNode ); 
The pMenuRootNode command tree node pointer can be compared with parent nodes of any node.

These operations are a bit complicated but allow your application(s) to have full control over any command tree node. Besides, there is one more way to solve your task. It is based on overriding the following method of the CExtCustomizeSite class:
virtual CExtCustomizeCmdTreeNode * OnCmdNodeCreate(
    UINT nCmdIdBasic = 0L,
    UINT nCmdIdEffective = 0L,
    CExtCustomizeCmdTreeNode * pParentNode = NULL,
    DWORD dwFlags = 0L,
    __EXT_MFC_SAFE_LPCTSTR strTextInToolbar = NULL,
    __EXT_MFC_SAFE_LPCTSTR strTextInMenu = NULL,
    __EXT_MFC_SAFE_LPCTSTR strTextUser = NULL,
    LPARAM lParam = 0L,
    CExtCmdIcon * pIconCustomized = NULL
   #if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD),
    INT nTextFieldWidth = 100,
    INT nDropDownWidth = -2, // (-1) - auto calc, (-2) - same as button area
        INT nDropDownHeightMax = 250
    #endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
       ); 
This method used by the Prof-UIS to create a new instance of the CExtCustomizeCmdTreeNode class that implements any command tree node in customizable applications. Your method may create instances of your own classes derived from CExtCustomizeCmdTreeNode. So, your application may use your custom command tree nodes which may have their own properties. The Prof-UIS Automation Pack uses this way to implement COM wrappers around the command tree nodes. But you may simply mark some nodes as disabled for the drag-and-dropping and then analyze this flag in the pNodeC parameter of your overridden CExtCustomizeSite::DoDragCmdNode() method.

If you encounter any difficulties, just send us your test project and a detailed description so that we can help you.


Stephan Finkler Dec 22, 2004 - 6:24 AM

I do not want to prevent only the drag-and-drop operations of the commands but the context menu to change menu items.
See your Style Editor sample:
- click Menu View\Customize --> dlg opens
- right click on menu --> context menu is shown
- now you can edit the menu items

I would like to prevent that this context menu is shown. The user is not allowed to change the menu.

Technical Support Dec 23, 2004 - 1:17 AM

To disable this feature for any toolbar button or menu item, please override the CExtCustomizeSite::OnCustomizeTreeNode() virtual method and analyze the identifier of the pNodeC command tree node. To get the command tree node identifier, call pNodeC->GetCmdID( false ). If the customization menu is suppressed for this node, then your OnCustomizeTreeNode() method should return false. Otherwise, it should call the parent method.

Stephan Finkler Dec 23, 2004 - 6:42 AM

Thanks a lot. This works good for the sub menu items.

But how can I get the CmdID of top menu items like "File", "Edit", "Help" and so on... they have no IDs in the resource but with pNodeC->GetCmdID( false ) I get one. How can I prevent them from editing?

by the way:
+++ I wish you a merry christmas +++

Technical Support Dec 23, 2004 - 8:26 AM

Dear Stephan,

In Win32’s menu resources, the pop-up items have no command identifiers. In Prof-UIS command trees, however, they do have identifiers that are allocated dynamically. This is essential for the customization subsystem because each command tree node must be identified uniquely so that it can be possible to implement the operations like resetting a single command tree node or menu sub tree. In the CMainFrame::OnCreate() method, before invoking CExtCustomizeSite::CustomizeStateLoad(), the customization subsystem is already completely initialized. At this point, you can find and store the identifiers of the File, Edit and Help nodes. You need to use the following code:

// for example, we will access the default menu line’s items
CExtCustomizeSite::CCmdMenuInfo * pCmdMenuInfo =
    CExtCustomizeSite::MenuInfoGetByName( "Default" );
ASSERT( pCmdMenuInfo != NULL );
CExtCustomizeCmdTreeNode * pMenuRootNode =
    pCmdMenuInfo->GetNode();
ASSERT_VALID( pMenuRootNode );
// "File" command tree item
CExtCustomizeCmdTreeNode * pNode_File =
    pMenuRootNode->ElementAt( 0 );
ASSERT_VALID( pNode_File );
UINT nID_File = pNode_File->GetCmdID( false );
// "Edit" command tree item
CExtCustomizeCmdTreeNode * pNode_Edit =
    pMenuRootNode->ElementAt( 1 );
ASSERT_VALID( pNode_Edit );
UINT nID_Edit = pNode_Edit->GetCmdID( false );

The order of the File, Edit and Help nodes is the same as the order of the top pop-up items in the menu resource.