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 General Discussion » Problem in adding dynamic Menu(help) Collapse All
Subject Author Date
ven rag Dec 21, 2005 - 5:03 AM

Hi ppl,


 


    I have created a Dynamic menu for MDI Application.


    I load my Dynamic menu When I open a New Document.This works fine in in the MDI Application.


    The problem that I got now is that When I add " ProfUIS" for my MDI Application I could not use that Dynamic Menu.


    What Happens is that the Menu that I give in the DocTemplate Adds to the ChildFrame.


    While using "ProfUIS"    I think some where the menu that is added to the Child Frame is Registered.So I could not remove the menu and add my Own


    Dynamic Menu.Can any one have solution for this.


 


  


 


 


 


 

ven rag Dec 26, 2005 - 12:19 AM

Hi Tect support,


  Sorry.


  Now I got ur code in correct format.


  The Pop Up is working fine.


  Now the code that I need to Do is that I need to overwrite


 CExtMenuControlBar::_UpdateMenuBar() internal virtual method.So that I can load my Dynamic Menu instead of the Menu that is there in Resource.


  How to Over Write CExtMenuControlBar::_UpdateMenuBar() funtion.


 //////////////////////////////


  I have Derived in the CMainFrame Class like this


class CMainFrame
 : public CMDIFrameWnd
 , public CExtDynamicBarSite


{


 protected:  // control bar embedded members
 CExtMenuControlBar         m_wndMenuBar;
}


I think I have to Overwrite the function in the CMainFrame.


"How to Dynamically create the MenuBar and add PopMenu in that Dynamically Created MenuBar and How to overwrite


CExtMenuControlBar::_UpdateMenuBar() "


Thank u.


 


 


 


 


 


 

Technical Support Dec 26, 2005 - 7:15 AM

You should use your CExtMenuControlBar-derived class like as follows:

class CMyMenuBar : CExtMenuControlBar
{
public:
    virtual BOOL _UpdateMenuBar(
        BOOL bDoRecalcLayout = TRUE
        );
};
The _UpdateMenuBar() method implementation should be coped from original method with adding your custom menu bar buttons into required locations:
BOOL CMyMenuBar::_UpdateMenuBar(
    BOOL bDoRecalcLayout // = TRUE
    )
{
    SetButtons(); // remove all buttons
    // remove all previously allocated command identifiers
    // for menu buttons
    VERIFY(
        g_CmdManager->CmdRemoveByMask(
            g_CmdManager->ProfileNameFromWnd( GetSafeHwnd() ),
            (DWORD)CExtCmdItem::STATE_MENUBAR_TMP
            )
        );
CMenu * pMenu = GetMenu();
    if( pMenu->GetSafeHmenu() != NULL )
    {
        bool bRevertRTL = OnQueryRevertRTL();
        UINT nMenuItemCount = pMenu->GetMenuItemCount();
        for( UINT nMenuItemIndex = 0; nMenuItemIndex < nMenuItemCount; nMenuItemIndex++ )
        {
            UINT nInsertButtonLocation =
                bRevertRTL
                    ? 0
                    : nMenuItemIndex
                    ;
            MENUITEMINFO mii;
            ::memset( &mii, 0, sizeof(MENUITEMINFO) );
            mii.cbSize = sizeof(MENUITEMINFO);
            mii.fMask =
                MIIM_CHECKMARKS
                |MIIM_DATA
                |MIIM_ID
                |MIIM_STATE
                |MIIM_SUBMENU
                |MIIM_TYPE
                ;
            mii.cch = __MAX_UI_ITEM_TEXT;
            CExtSafeString sText;
            mii.dwTypeData =
                sText.GetBuffer( __MAX_UI_ITEM_TEXT );
            ASSERT( mii.dwTypeData != NULL );
            if( mii.dwTypeData == NULL )
            {
                ASSERT( FALSE );
                return FALSE;
            }
            if( ! pMenu->GetMenuItemInfo(
                    nMenuItemIndex,
                    &mii,
                    TRUE
                    )
                )
            {
                sText.ReleaseBuffer();
                ASSERT( FALSE );
                return false;
            }
            sText.ReleaseBuffer();

            BOOL bAppendMdiWindowsMenu = FALSE;
            UINT nCmdID = 0;
            CExtCmdItem * pCmdItem = NULL;
            if( mii.hSubMenu == NULL )
            {
                nCmdID = mii.wID;
                if( nCmdID == ID_SEPARATOR )
                {
                    if( ! InsertButton(
                            nInsertButtonLocation,
                            nCmdID,
                            FALSE
                            )
                        )
                    {
                        ASSERT( FALSE );
                        return FALSE;
                    }
                    continue;
                } // if( nCmdID == ID_SEPARATOR )
                ASSERT( CExtCmdManager::IsCommand(nCmdID) );
                pCmdItem =
                    g_CmdManager->CmdGetPtr(
                        g_CmdManager->ProfileNameFromWnd( GetSafeHwnd() ),
                        nCmdID
                        );
                ASSERT( pCmdItem != NULL );
            } // if( mii.hSubMenu == NULL )
            else
            {
                pCmdItem =
                    g_CmdManager->CmdAllocPtr(
                        g_CmdManager->ProfileNameFromWnd( GetSafeHwnd() )
                        );
                if( pCmdItem == NULL )
                {
                    ASSERT( FALSE );
                    return FALSE;
                } // if( pCmdItem == NULL )
                nCmdID = pCmdItem->m_nCmdID;
                ASSERT( CExtCmdManager::IsCommand(nCmdID) );
                pCmdItem->StateSetMenubarTemp();
                pCmdItem->StateSetBasic();

                if( _IsMdiApp() && (! m_sMdiWindowPopupName.IsEmpty() ) )
                {
                    CExtSafeString _sText(sText);
                    _sText.TrimLeft();
                    _sText.TrimRight();
                    while( _sText.Replace(_T("&"),_T("")) > 0 )
                    {
                        _sText.TrimLeft();
                        _sText.TrimRight();
                    } // while( _sText.Replace(_T("&"),_T("")) > 0 )
                    if( _sText == m_sMdiWindowPopupName )
                        bAppendMdiWindowsMenu = TRUE;
                } // if( _IsMdiApp() && (! m_sMdiWindowPopupName.IsEmpty() ) )
            } // else from if( mii.hSubMenu == NULL )
            ASSERT( pCmdItem != NULL );
            if( pCmdItem->m_sToolbarText.IsEmpty() )
                pCmdItem->m_sToolbarText = sText;
            if( pCmdItem->m_sMenuText.IsEmpty() )
                pCmdItem->m_sMenuText = sText;

            if( ! InsertButton(
                    nInsertButtonLocation,
                    nCmdID,
                    FALSE
                    )
                )
            {
                ASSERT( FALSE );
                return FALSE;
            }

            if( mii.hSubMenu != NULL )
            {
                ASSERT( ::IsMenu(mii.hSubMenu) );
                SetButtonMenu(
                    nInsertButtonLocation,
                    mii.hSubMenu,
                    FALSE,
                    FALSE,
                    FALSE
                    );
            } // if( mii.hSubMenu != NULL )
            if( bAppendMdiWindowsMenu )
            {
                VERIFY(
                    MarkButtonAsMdiWindowsMenu(
                        nInsertButtonLocation,
                        TRUE
                        )
                    );
            } // if( bAppendMdiWindowsMenu )
        } // for( UINT nMenuItemIndex = 0; nMenuItemIndex < nMenuItemCount; nMenuItemIndex++ )

        ASSERT( m_pRightBtn == NULL );
        m_pRightBtn = OnCreateBarRightBtn();
        if( m_pRightBtn != NULL )
        {
            ASSERT_VALID( m_pRightBtn );
            ASSERT_KINDOF( CExtBarContentExpandButton, m_pRightBtn );
            m_buttons.Add( m_pRightBtn );
        } // if( m_pRightBtn != NULL )
    } // if( pMenu->GetSafeHmenu() != NULL )

    /////////////////////////////////////////////////////
    //
    // TO DO:
    // insert custom menu bar’s buttons here
    //
    /////////////////////////////////////////////////////

    if( _IsMdiApp() )
    {
        if( !IsOleIpObjActive() )
            if( _InstallMdiDocButtons( FALSE ) )
                bDoRecalcLayout = TRUE;
        VERIFY( _SyncActiveMdiChild() );
    }
    if( bDoRecalcLayout )
    {
        Invalidate();
        _RecalcLayoutImpl();
        UpdateWindow();
        if( m_pDockSite != NULL )
        {
            CFrameWnd * pFrame = GetParentFrame();
            ASSERT_VALID( pFrame );
            if( pFrame->IsKindOf(RUNTIME_CLASS(CExtMiniDockFrameWnd)) )
                pFrame->SetWindowPos(
                    NULL, 0, 0, 0, 0,
                    SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE
                        |SWP_NOZORDER|SWP_NOOWNERZORDER
                        |SWP_FRAMECHANGED
                    );
        } // if( m_pDockSite != NULL )
    } // if( bDoRecalcLayout )
    return TRUE;
}
Please note each button requires a unique command identifier. You should allocate it in the command manager as the method above performs for each popup sub-menu button:
CExtCmdItem * pCmdItem =
        g_CmdManager->CmdAllocPtr(
            g_CmdManager->ProfileNameFromWnd( GetSafeHwnd() )
            );
    if( pCmdItem == NULL )
    {
        ASSERT( FALSE );
        return FALSE;
    } // if( pCmdItem == NULL )
    pCmdItem->StateSetMenubarTemp();
    pCmdItem->StateSetBasic();
After that you can use the allocated command identifier to crate the button in menu bar:
INT nInsertButtonPosition = . . .
LPCTSTR sText = _T("Button name");
    pCmdItem->m_sToolbarText = sText;
    pCmdItem->m_sMenuText = sText;
    if( ! InsertButton(
              nInsertButtonPosition,
              pCmdItem->nCmdID,
              FALSE
              )
          )
    {
        ASSERT( FALSE );
        return FALSE;
    }
Finally, you can assign HMENU to inserted button:
HMENU hMenu = . . .
    SetButtonMenu(
        nInsertButtonLocation,
        hMenu,
        FALSE,
        FALSE,
        FALSE
        );

ven rag Dec 27, 2005 - 6:52 AM

Iam calling the  _UpdateMenuBar(TRUE); from CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) function


This is How I call.


CExtCmdItem * pCmdItem =  g_CmdManager->CmdAllocPtr(g_CmdManager->ProfileNameFromWnd( GetSafeHwnd() )            );
if( pCmdItem == NULL )  
 {        ASSERT( FALSE );  
          return FALSE;
 } // if( pCmdItem == NULL ) 
pCmdItem->StateSetMenubarTemp();
pCmdItem->StateSetBasic();


CMyMenuBar m_menubar;
m_menubar._UpdateMenuBar(TRUE);


After this I get the Error as


ExtCmdManager.cpp


Line :2589


When I Ignore the Program is running .But no change in the Menu Bar


 


Ater Calling _UpdateMenuBar(TRUE) I am inserting as u have said


INT nInsertButtonPosition = 1;
LPCTSTR sText = _T("File");
    pCmdItem->m_sToolbarText = sText;
    pCmdItem->m_sMenuText = sText;
    if( ! InsertButton(
              nInsertButtonPosition,
              pCmdItem->nCmdID,
              FALSE
              )
          )
    {
        ASSERT( FALSE );
        return FALSE;
    }


I get an error as InsertButton undeclared identifier


nCmdID is not the member of CExtCmdItem.


How to solve these problem.Also I want to know that Whether I can Create the Menu that I want to create Dynamically in the Menu bar.


Suppose I want the Menu Bar to contain


/////////////////////////////


File       View------------------------>Root Menu in the Menu bar


New     Large--------------------------------->Sub Menu Under the Root.


Open    Small


Exit


//////////////////////////////


How to do these things Dynamically.


If I want to "File"(in the Menu) to there it as to be added in the Dynamic Menu and All the SubMenu Menu under the File(New,Open,Exit) should.


Suppose I don’t File to be not to be added it should not be added and also the SubMenu shold not be added.


Suppose I don’t want to add a particular SubMenu(for eg: New under File)then I should remove it.


This is what I like to do.


"I did  solve this problem using MFC".But now I want to do it using PRO-UIS.


How to solve this problem?


Thank u


 


 


 


 


 


 


 


 


 



 

Technical Support Dec 27, 2005 - 9:34 AM

You did not follow what described earlier. Your code allocates a command identifier marked as the command which is used internally by the menu bar by calling the pCmdItem->StateSetMenuBarTemp() code, invokes the CExtMenuControlBar::_UpdateMenuBar() method where all the marked commands are removed from the command manager and finally tries to use the command identifier (which is not available in the command manager) to create the menu bar button. Please re-arrange these steps:

1) invoke _UpdateMenuBar()

2) allocate a command item as you did

3) create a button in the menu bar as you did

ven rag Dec 27, 2005 - 11:18 PM

 VERIFY(
      g_CmdManager->CmdRemoveByMask(
       g_CmdManager->ProfileNameFromWnd( GetSafeHwnd() ),
       (DWORD)CExtCmdItem::STATE_MENUBAR_TMP ));--------------------->Error in this line.This code comes inside _UpdateMenuBar().


Assertion Error comes after this line.(HOW TO SOLVE THIS ERROR)


The Error is in ExtCmdManager.cpp file.


By the way I followed the  steps that u have told me.Please read the errors that I mentioned  in the Last Message also.


Thank u.


 



 

ven rag Dec 24, 2005 - 1:41 AM

"The Problem with the code that u have sent."


The problem with this is that it insert the item in the existing Menu.


for eg:I have the Menu like this.(IDR_MDIMENTYPE )


In this Menu I have the Following Menu


File           Edit          View ------------------->Root Menu


Open        Draw        Large-------------------->Sub Menu Under each Root


New         Paste         Small


Exit


This the Menu that is Created in the Resourse


////////////////////////////////////


nItemPos = pPopup->ItemFindPosForCmdID( __ID_MDIWND_DLGWINDOWS );


pPopup->ItemInsertCommand(        ID_APP_ABOUT,        nNewPos,        "About (1)"        );


//////////////////////////////


After Adding this code the About Box is Added to All the Root Menu .The Out put is given below.


File           Edit          View ------------------->Root Menu


Open        Draw        Large-------------------->Sub Menu Under each Root


New         Paste         Small


About(1)  About(1)    About(1)


Exit


//////////////////////////////


What I want to Do is .I don’t want the Default Menu that is (IDR_MDIMENTYPE ) which I added in the Resource.


================================================


I don’t want this Menu to be added in the Menu 


File           Edit          View ------------------->Root Menu


Open        Draw        Large-------------------->Sub Menu Under each Root


New         Paste         Small


About(1)  About(1)    About(1)


Exit


 


===================================================


The Below Menu is the One That I need to add Dynamically in the Menu Bar while I Open a New Document.


Shape  Help-------------------------------->Root Menu


Circle   About------------------------------>Sub Menu under the Root


Rect     


Square


How Solve this Problem.Hope this time I am clear.

Technical Support Dec 24, 2005 - 11:10 AM

It seems you did not follow exactly what we’d described in our message. Here is the code from your message:

nItemPos = pPopup->ItemFindPosForCmdID( __ID_MDIWND_DLGWINDOWS );
pPopup->ItemInsertCommand( ID_APP_ABOUT, nNewPos, "About (1)" ); 
The first line searches for the __ID_MDIWND_DLGWINDOWS command in the popup menu being displayed. The search result is not analyzed in your code. The nItemPos variable is -1 if the __ID_MDIWND_DLGWINDOWS command is not found. Your code ignores this and simply adds the ID_APP_ABOUT command regardless of any conditions. Your code should look like as follows:
nItemPos = pPopup->ItemFindPosForCmdID( __ID_MDIWND_DLGWINDOWS );
if( nItemPos >= 0 )
{
    pPopup->ItemRemove( nItemPos );
    int nNewPos = nItemPos;
    pPopup->ItemInsertCommand( ID_APP_ABOUT, nNewPos, "About (1)" ); 
}

ven rag Dec 23, 2005 - 3:41 AM

//The Menu IDR_MDIMENUTYPE is the Menu that is added in the Childframe.
                pDocTemplate = new CMultiDocTemplate(
  IDR_MDIMENTYPE,//The Menu that Will be added whenever I open a New Document
  RUNTIME_CLASS(CMDIMENUDoc),
  RUNTIME_CLASS(CChildFrame), // custom MDI child frame
  RUNTIME_CLASS(CMDIMENUView));


 


 


//This is how I add the Dynamic Menu


        CMenu m_MenuMain;
 CMenu *m_pMainMenu;
 CMenu m_menuPopup;
 CMenu m_submenu;
        m_MenuMain.CreateMenu();
 m_menuPopup.CreatePopupMenu();
 m_menuPopup.AppendMenu (MF_STRING, 12, "E&xit");
 m_MenuMain.AppendMenu (MF_POPUP,(UINT)m_menuPopup.Detach (),"&File");
 m_menuPopup.CreatePopupMenu ();
 m_submenu.CreateMenu();
 m_submenu.AppendMenu (MF_STRING,(UINT)m_menuPopup.m_hMenu,"&Square\tF9");
 m_submenu.AppendMenu (MF_STRING, (UINT)m_menuPopup.m_hMenu, "&Rectangle\tF10");
 m_submenu.AppendMenu (MF_STRING, (UINT)m_menuPopup.m_hMenu, "&Circle\tF12");
 m_menuPopup.AppendMenu (MF_POPUP, (UINT) m_submenu.Detach(),"&Shapes");
 m_MenuMain.AppendMenu  (MF_POPUP,(UINT) m_menuPopup.Detach (),"&Options");
 AfxGetMainWnd()->SetMenu(&m_MenuMain);
 AfxGetMainWnd()->DrawMenuBar();


After I add the Dynamic menu the Menu that I was added in the Resource will not be there.
The Menu that I added in Dynamically will be added.  


This works fine in my MFC MDI Applcation.
Now I add "ProfUIS" to my MFC MDI Application.The Menu(IDR_MDIMENTYPE) is displayed
always.I could not add my Dynamic menu.
I want Prof UIS  and also the Dynamic menu.
I want to add the Dynamic menu in place of IDR_MDIMENTYPE and add ProUIS to it
How to rectify this problem.


 


 


 



 

Technical Support Dec 23, 2005 - 12:15 PM

We explained you how to modify popup menus on-the-fly in our previous message. The top level menu line is controlled by the CExtMenuControlBar window which is a kind of the CExtToolControlBar toolbar window. The top level menu is a set of toolbar buttons which are instances of the CExtBarButton objects. The CExtMenuControlBar::UpdateMenuBar() method tells the menu bar to rebuilt its buttons. This method invokes the CExtMenuControlBar::_UpdateMenuBar() internal virtual method which does this work. You can override the CExtMenuControlBar::_UpdateMenuBar() internal virtual method in your own CExtMenuControlBar-derived class. In this method please invoke the parent method and insert any dynamically created buttons into any location you need. This can be done easier if the menu resource contains all the "dynamic" popup sub menus and your _UpdateMenuBar() method just removes them when they are redundant.

ven rag Dec 21, 2005 - 9:36 PM

I want my menu to be in ProfUIS fromat only.


How to create "CExtMenuControlBar"  Menu "Dynamically".


 


 


 


 

Technical Support Dec 22, 2005 - 12:46 PM

Please open the menu resource which is used for the Prof-UIS menu bar and insert some ID_MY_MENU_MARKER command in some popup menu. The menu item text and tip text properties of this item are not important. This command item in menu will be used for replacing it with a set of dynamic menu items on-the-fly immediately before the menu appears on the screen. Now, we need to handle the CExtPopupBaseWnd::g_nMsgPrepareOneMenuLevel registered windows message in your application. The message handler function, which should be added to the main frame or dialog window, will search for the ID_MY_MENU_MARKER menu item in each displayed sub menu. If this menu item is found successfully, then the handler method removes this menu item and inserts some items instead. Here is the method declaration, message map’s entry and implementation:

afx_msg LRESULT OnExtMenuPrepareOneLevel(WPARAM wParam, LPARAM lParam);
ON_REGISTERED_MESSAGE(
    CExtPopupBaseWnd::g_nMsgPrepareOneMenuLevel,
    OnExtMenuPrepareOneLevel
    )
LRESULT CPageButtons::OnExtMenuPrepareOneLevel(WPARAM wParam, LPARAM lParam)
{
    lParam; // unused parameter
CExtPopupMenuWnd::MsgPrepareMenuData_t * pData =
        reinterpret_cast
        < CExtPopupMenuWnd::MsgPrepareMenuData_t * >
        ( wParam );
    ASSERT( pData != NULL );
CExtPopupMenuWnd * pPopup = pData->m_pPopup;
    ASSERT( pPopup != NULL );
 
INT nReplacePos =
    pPopup->ItemFindPosForCmdID( ID_MY_MENU_MARKER );
    if( nReplacePos < 0 )
        return 0;
 
    VERIFY( pPopup->ItemRemove(nReplacePos) );
    // insert one command
    pPopup->ItemInsertCommand(
        ID_APP_ABOUT,
        nReplacePos,
        "About (1)"
        );
    // insert one more command
    pPopup->ItemInsertCommand(
        ID_APP_ABOUT,
        nReplacePos + 1,
        "About (2)"
        );
    // and insert one more command
    pPopup->ItemInsertCommand(
        ID_APP_ABOUT,
        nReplacePos + 2,
        "About (3)"
        );
    return ( ! 0 );
}
Now please compile and run your program, open the menu bar’s menu which contains the ID_MY_MENU_MARKER command item. You should see three "About" commands instead of the ID_MY_MENU_MARKER command.

Technical Support Dec 21, 2005 - 10:38 AM

The CExtMenuControlBar window kills the standard menu line in the main frame window and builds its buttons with sub menus to emulate the standard menu line. So, you cannot access the HMENU/CMenu of the main frame window. Please let us know which menu you wish to build dynamically and we will provide you with a solution.