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 » Adding to right-click menus on ribbon bar Collapse All
Subject Author Date
Robert Webb Mar 16, 2009 - 8:20 PM

Hi,


Is there a way to add or modify items on the menu that appears when you right-click on a control in the ribbon bar?  I’d like to be able to tell which control was clicked and add different stuff accordingly.  And I guess since I would add the same menu item for many controls, I’d like the callback when selected to also be able to tell which control was right-clicked.


Thanks,


Rob.

Robert Webb Mar 19, 2009 - 2:11 AM

Thanks, CExtControlBar::g_nMsgConstructPopupMenu looks good, because it allows me to edit the existing default menus.  But it can’t be used (can it?) for ribbon bar menus.


However, CExtRibbonBar::OnRibbonTrackButtonContextMenu() doesn’t allow the same flexibility.  The base version creates the menu and also opens the menu for tracking, so there’s no way to get in between and alter it.  I want to keep the existing menus, but add an item or two.  Is this not possible without first copying all the code from the base class?  I really don’t want to do that.



Thanks,


Rob.


 


 


Technical Support Mar 20, 2009 - 1:41 PM

In the case of ribbon bar, you should use the CExtRibbonBar::OnRibbonTrackButtonContextMenu() virtual method, which is invoked for context menus displayed over any button or the CExtRibbonBar::OnRibbonTrackBarContextMenu() virtual method which is invoked for other context menus. So, the CExtRibbonBar class allows you to implement completely new context menus using these virtual methods:

   virtual bool OnRibbonTrackButtonContextMenu(
                        CExtBarButton * pTBB,
                        UINT nFlags,
                        CPoint point
                        );
            virtual bool OnRibbonTrackBarContextMenu(
                        UINT nFlags,
                        CPoint point
                        );

But the CExtRibbonBar class does not have similar virtual methods invoked from the methods above for modifying created by default context menus. You was right. We think this is not a good design. So, we added two new virtual methods into the CExtRibbonBar class:
   virtual bool OnRibbonPrepareButtonContextMenu(
                        CExtPopupMenuWnd * pWndPopupMenu,
                        CExtBarButton * pTBB,
                        UINT nFlags,
                        CPoint point
                        );
            virtual bool OnRibbonPrepareBarContextMenu(
                        CExtPopupMenuWnd * pWndPopupMenu,
                        UINT nFlags,
                        CPoint point
                        );

bool CExtRibbonBar::OnRibbonPrepareButtonContextMenu(
            CExtPopupMenuWnd * pWndPopupMenu,
            CExtBarButton * pTBB,
            UINT nFlags,
            CPoint point
            )
{
            ASSERT_VALID( this );
            ASSERT_VALID( pWndPopupMenu );
            ASSERT_VALID( pTBB );
            pWndPopupMenu;
            pTBB;
            nFlags;
            point;
            return true;
}

bool CExtRibbonBar::OnRibbonPrepareBarContextMenu(
            CExtPopupMenuWnd * pWndPopupMenu,
            UINT nFlags,
            CPoint point
            )
{
            ASSERT_VALID( this );
            ASSERT_VALID( pWndPopupMenu );
            pWndPopupMenu;
            nFlags;
            point;
            return true;
}

They are invoked from the modified CExtRibbonBar::OnRibbonTrackButtonContextMenu() and CExtRibbonBar::OnRibbonTrackBarContextMenu() methods:
 bool CExtRibbonBar::OnRibbonTrackButtonContextMenu(
            CExtBarButton * pTBB,
            UINT nFlags,
            CPoint point
            )
{
            ASSERT_VALID( this );
            ASSERT_VALID( pTBB );
            nFlags;
            if( GetSafeHwnd() == NULL )
                        return false;
            if(                     pTBB->IsKindOf( RUNTIME_CLASS( CExtRibbonButtonFile ) )
                        ||           pTBB->IsKindOf( RUNTIME_CLASS( CExtRibbonButtonQuickAccessContentExpand ) )
                        ||           pTBB->IsKindOf( RUNTIME_CLASS( CExtRibbonButtonTabPage ) )
                        ||           RibbonRightButton_GetIndexOf( pTBB ) >= 0
                        )
                        return false;
CExtBarButton * pCtxTBB = NULL;
CExtRibbonButtonDialogLauncher * pDlbTBB = DYNAMIC_DOWNCAST( CExtRibbonButtonDialogLauncher, pTBB );
            if( pDlbTBB != NULL )
                        pTBB = pDlbTBB->ParentButtonGet();
CExtRibbonButtonGroup * pGroupTBB = DYNAMIC_DOWNCAST( CExtRibbonButtonGroup, pTBB );
            if( pGroupTBB != NULL )
            {
                        for( ; pTBB != NULL; )
                        {
                                    ASSERT_VALID( pGroupTBB );
                                    CExtBarButton * pTBB2 = pGroupTBB->ParentButtonGet();
                                    if( pTBB2 == NULL )
                                                break;
                                    ASSERT_VALID( pTBB2 );
                                    pGroupTBB = DYNAMIC_DOWNCAST( CExtRibbonButtonGroup, pTBB2 );
                                    if( pGroupTBB == NULL )
                                                break;
                        }
                        if( pGroupTBB == NULL )
                                    return false;
                        pCtxTBB = pGroupTBB;
            }
            else
            {
                        if( pTBB->ChildButtonGetCount() != 0 )
                                    return false;
                        pCtxTBB = pTBB;
            }
            ASSERT( pCtxTBB != NULL );
            ASSERT_VALID( pCtxTBB );
            ClientToScreen( &point );
DWORD dwTrackFlags = TPMX_OWNERDRAW_FIXED|TPMX_COMBINE_NONE|TPMX_RIBBON_MODE|TPMX_NO_HIDE_RARELY|TPMX_FORCE_NO_ANIMATION;
CExtPopupMenuWnd * pPopup = CExtPopupMenuWnd::InstantiatePopupMenu( GetSafeHwnd(), RUNTIME_CLASS(CExtPopupMenuWnd), this );
            if( ! pPopup->LoadMenu( GetSafeHwnd(), IDR_EXT_RIBON_CTX_MENU, true, true ) )
            {
                        delete pPopup;
                        return false;
            }
bool bQaButton = ( RibbonQuickAccessButton_GetIndexOf( pCtxTBB ) >= 0 ) ? true : false;
bool bRibbonQuickAccessBarIsAboveTheRibbon = RibbonQuickAccessBar_AboveTheRibbonGet();
INT nIndexInQA = RibbonQuickAccessButton_GetIndexOf( pCtxTBB );
INT nIndex, nCount = pPopup->ItemGetCount();
            for( nIndex = 0; nIndex < nCount; )
            {
                        UINT nCmdID = pPopup->ItemGetCmdID( nIndex );
                        switch( nCmdID )
                        {
                        case ID_EXT_RIBBON_QATB_ADD_TO:
                                    if( nIndexInQA >= 0 )
                                                break;
                                    pPopup->ItemInsert( 0, nIndex + 1 );
                                    nIndex += 2;
                                    nCount ++;
                                    continue;
                        case ID_EXT_RIBBON_QATB_REMOVE_FROM:
                                    if( nIndexInQA < 0 )
                                                break;
                                    pPopup->ItemInsert( 0, nIndex + 1 );
                                    nIndex += 2;
                                    nCount ++;
                                    continue;
                        case ID_EXT_RIBBON_MINIMIZE:
                                    {
                                                CExtPopupMenuWnd::MENUITEMDATA & mi = pPopup->ItemGetInfo( nIndex );
                                                mi.SetNoCmdUI( true );
                                                mi.Enable( true );
                                                mi.Check( ! RibbonPage_ExpandedModeGet() );
                                                if( nIndex > 0 )
                                                {
                                                            pPopup->ItemInsert( ID_SEPARATOR, nIndex );
                                                            nIndex ++;
                                                }
                                                nIndex ++;
                                                continue;
                                    }
                                    break;
                        case ID_EXT_RIBBON_QATB_PLACE_BELOW:
                                    if( bRibbonQuickAccessBarIsAboveTheRibbon && bQaButton )
                                    {
                                                nIndex ++;
                                                continue;
                                    }
                                    break;
                        case ID_EXT_RIBBON_QATB_PLACE_ABOVE:
                                    if( ( ! bRibbonQuickAccessBarIsAboveTheRibbon ) && bQaButton )
                                    {
                                                nIndex ++;
                                                continue;
                                    }
                                    break;
                        case ID_EXT_RIBBON_QATB_RESET:
                        case ID_EXT_RIBBON_QATB_CUSOMIZE:
                                    nIndex ++;
                                    continue;
                        }
                        pPopup->ItemRemove( nIndex );
                        nCount --;
            }
            m_nHelperCtxIndexQA = _GetIndexOf( pCtxTBB );
            pPopup->m_hWndNotifyMenuClosed = GetSafeHwnd();
            if( ! OnRibbonPrepareButtonContextMenu( pPopup, pTBB, nFlags, point ) )
            {
                        delete pPopup;
                        return false;
            }
            if( pPopup->ItemGetCount() == 0 ) 
            {
                        delete pPopup;
                        return false;
            }
            if( ! pPopup->TrackPopupMenu( dwTrackFlags, point.x, point.y ) )
            {
                        delete pPopup;
                        return false;
            }
            return true;
}

bool CExtRibbonBar::OnRibbonTrackBarContextMenu(
            UINT nFlags,
            CPoint point
            )
{
            ASSERT_VALID( this );
            nFlags;
            if( GetSafeHwnd() == NULL )
                        return false;
            ClientToScreen( &point );
            if(                     RibbonLayout_IsFrameIntegrationEnabled()
                        &&        RibbonQuickAccessBar_AboveTheRibbonGet()
                        &&        (! m_rcHelperEmbeddedCaptionText.IsRectEmpty() )
                        &&        m_rcHelperEmbeddedCaptionText.PtInRect( point )
                        )
                        return false;
            else if( GetParent()->SendMessage( WM_NCHITTEST, 0, MAKELPARAM( point.x, point.y ) ) != HTCLIENT )
                        return false;
DWORD dwTrackFlags = TPMX_OWNERDRAW_FIXED|TPMX_COMBINE_NONE|TPMX_RIBBON_MODE|TPMX_NO_HIDE_RARELY|TPMX_FORCE_NO_ANIMATION;
CExtPopupMenuWnd * pPopup = CExtPopupMenuWnd::InstantiatePopupMenu( GetSafeHwnd(), RUNTIME_CLASS(CExtPopupMenuWnd), this );
            if( ! pPopup->LoadMenu( GetSafeHwnd(), IDR_EXT_RIBON_CTX_MENU, true, true ) )
            {
                        delete pPopup;
                        return false;
            }
bool bRibbonQuickAccessBarIsAboveTheRibbon = RibbonQuickAccessBar_AboveTheRibbonGet();
INT nIndex, nCount = pPopup->ItemGetCount();
            for( nIndex = 0; nIndex < nCount; )
            {
                        UINT nCmdID = pPopup->ItemGetCmdID( nIndex );
                        switch( nCmdID )
                        {
                        case ID_EXT_RIBBON_MINIMIZE:
                                    {
                                                CExtPopupMenuWnd::MENUITEMDATA & mi = pPopup->ItemGetInfo( nIndex );
                                                mi.SetNoCmdUI( true );
                                                mi.Enable( true );
                                                mi.Check( ! RibbonPage_ExpandedModeGet() );
                                                if( nIndex > 0 )
                                                {
                                                            pPopup->ItemInsert( ID_SEPARATOR, nIndex );
                                                            nIndex ++;
                                                }
                                                nIndex ++;
                                                continue;
                                    }
                                    break;
                        case ID_EXT_RIBBON_QATB_PLACE_BELOW:
                                    if( bRibbonQuickAccessBarIsAboveTheRibbon )
                                    {
                                                nIndex ++;
                                                continue;
                                    }
                                    break;
                        case ID_EXT_RIBBON_QATB_PLACE_ABOVE:
                                    if( ! bRibbonQuickAccessBarIsAboveTheRibbon )
                                    {
                                                nIndex ++;
                                                continue;
                                    }
                                    break;
                        case ID_EXT_RIBBON_QATB_RESET:
                        case ID_EXT_RIBBON_QATB_CUSOMIZE:
                                    nIndex ++;
                                    continue;
                        } // switch( nCmdID )
                        pPopup->ItemRemove( nIndex );
                        nCount --;
            } // for( nIndex = 0; nIndex < nCount; )
            pPopup->m_hWndNotifyMenuClosed = GetSafeHwnd();
            if( ! OnRibbonPrepareBarContextMenu( pPopup, nFlags, point ) )
            {
                        delete pPopup;
                        return false;
            }
            if( pPopup->ItemGetCount() == 0 )
            {
                        delete pPopup;
                        return false;
            }
            if( ! pPopup->TrackPopupMenu( dwTrackFlags, point.x, point.y ) )
            {
                        delete pPopup;
                        return false;
            }
            return true;
}

The and CExtRibbonBar::OnRibbonTrackButtonContextMenu() and CExtRibbonBar::OnRibbonTrackBarContextMenu() allow you to modify created by default context menus. You can return false from these methods to cancel context menus.


Robert Webb Mar 19, 2009 - 6:36 PM

Further to my above message, you could extend Prof-UIS to make modification of ribbon bar context menus rather easily in CExtRibbonBar::OnRibbonTrackButtonContextMenu() by adding a call to a new virtual function like this (with some surrounding context):



   	 case ID_EXT_RIBBON_QATB_RESET:
        case ID_EXT_RIBBON_QATB_CUSOMIZE:
            nIndex ++;
            continue;
        } // switch( nCmdID )
        pPopup->ItemRemove( nIndex );
        nCount --;
    } // for( nIndex = 0; nIndex < nCount; )
    
    m_nHelperCtxIndexQA = _GetIndexOf( pCtxTBB );
    ////////////////////////////////////////////////////////////
    // Call a new virtual function here.  Something like this:
    // if (!OnRibbonContextMenuModify(pPopup, pTBB, nFlags, point))
    // {
    //	 delete pPopup;
    //	 return false;
    // }
    ////////////////////////////////////////////////////////////
    pPopup->m_hWndNotifyMenuClosed = GetSafeHwnd();
    if( ! pPopup->TrackPopupMenu(
            dwTrackFlags,
            point.x,
            point.y
            )
        )
    {
        delete pPopup;
        return false;
    }
    return true;

The new function could return false to disable the menu, or true otherwise.  Similar code would have to be added to CExtRibbonBar::OnRibbonTrackBarContextMenu().  I’d suggest just using the same new virtual function with the pTBB arg set to NULL.


Any chance you could add this?  Or explain how I should be doing it (modifying the existing ribbon context menus).


Rob.


PS. You desperately need to ditch whatever software you use for this forum and use something less frustrating like phpBB!

Technical Support Mar 20, 2009 - 2:15 PM

You wrote "the new function could return false to disable the menu, or true otherwise". Yes, that’s true. This design is somehow supererogatory. The OnRibbon***ContextMenu***Modify*** (or OnRibbon***ContextMenu***Prepare***) methods does not need to return any flag at all. Such methods can simply remove all the popup menu items using the CExtPopupMenuWnd::ItemRemove() method and, as result, context menu will not be displayed. But, according to our experience, customers often prefer to just to return true or false from similar virtual methods. Please consider this explanation is not a final answer in this thread - we are waiting for your reply.

P.S. We merged two types of forums into one and running on this mixed forum system:

1) One is PhpBB like plain, but with message indents inside each thread. It’s loved by indexer bots. It’s displayed by default forum view.

2) Second one is what we really love. It’s tree like discussion where you can see what is related to what. Please try to switch to this tree view and let us know what you think about it.

Robert Webb Mar 23, 2009 - 1:39 AM

Your changes look good.  Basically the same as the hack I made to my local copy.  So I hope it will be part of the next official release.


Regarding the forum, I see no way to obtain a tree view.  Either way, there are many problems still in terms of usability.  It is NOT like phpBB.  I posted about this before: http://www.prof-uis.com/prof-uis/tech-support/support-forum/suggestion-switch-to-a-more-usable-forum-like-phpbb-62439.aspx#@lt;/p>

But techical support did not reply to that one.  Another really difficult thing when editing messages here is highlighting.  I often spend ages trying to get the right words highlighted the right way and end up giving up.  Eg if I highlight some text and select a different style, it isn’t applied.  If I have the cursor after a block of one style, select a different style, then start typing, it never comes out in the right style.  Etc, etc, etc.


Just switch to phpBB and everyone will be happy.


Rob.

Technical Support Mar 17, 2009 - 10:16 AM

Prof-UIS allows to modify or re-create any of the built in popup menus displayed over different control bars and frame window areas. For instance the ProfStudio sample application completely recreates the context menus displayed over control bars, main frame window and menus displayed from toolbar chevron button. This is possible via handling the CExtControlBar::g_nMsgConstructPopupMenu registered message like demonstrated in the CMainFrame::OnConstructPopupMenuCB() method in the ProfStudio sample application. The CExtControlBar::g_nMsgConstructPopupMenu registered message is sent twice. First time it allows to construct entire menu from scratch. Second time it allows to modify constructed by default menu. If you need simply to hide some Prof-UIS based control bar from the context menus displayed over bars and frame, then you simply should set the bar’s CExtControlBar::m_bAppearInDockSiteControlBarPopupMenu property to false. If you are using dynamic resizable control bars and you need to modify menu displayed over dynamic bar’s caption or from its Window Options caption button, then you should create and you own CExtDynamicControlBar-derived class which implements the CExtDynamicControlBar::OnInitDbsMenu() virtual method. The CExtRibbonBar control uses its specific context menus. To modify the ribbon bar’s context menus you should override the CExtRibbonBar::OnRibbonTrackButtonContextMenu() virtual method.