Professional UI Solutions
Site Map   /  Register
 
 
 

Pop-Up Menus

How to customize or disable sounds used in pop-up menus?

The Prof-UIS menus support the standard Windows sounds when changing menu levels and clicking menu items. The standard PlaySound() API allows you to invoke any appropriate registered sound. Each sound is played in a newly created standalone and absolutely isolated thread. The PlaySound() API often takes the execution control up for half a second if it is invoked for playing the sound asynchronously. It is not possible to use this API in the same thread with the UI thread where the menu is created and tracked. The threads are created even if there are no sounds assigned to menu events in Windows settings because there is no API available to detect whether a sound is assigned. This thread should not cause any problems in your application. But the sound mixer which mixes a menu sound with some other sound stream in the system may bring on a problem depending on the installed drivers. So you can customize and even turn off the sounds. Just create your own sound player class and install it. The CExtSoundPlayer::PlaySound method is invoked when the certain event is triggered and the sound should be played:
class CSilencePlayer : public CExtSoundPlayer
{
    void PlaySound( CExtSoundPlayer::e_ui_sounds_t ) 
    { 
        // do nothing
    }
};

g_SoundPlayer.InstallSoundPlayer( new CSilencePlayer );
You can put this code into the main frame's constructor or application's constructor.

How to implement custom drawing for menu items?

You can customize the look of any menu item or subitem to make it fit your taste. This can be done using custom drawing. For example, the CPagePopupMenus::OnDrawPopupMenuItem() method in the ProfUIS_Controls sample handles the CExtPopupMenuWnd::g_nMsgPopupDrawItem registered windows message and performs custom drawing of the menu item specified with ID_OWNERDRAW_ITEM. So, if you select the Popup Menu page in this application and invoke the context menu, you will see that this custom menu item features a gradient background. The pointer to the CExtPopupMenuWnd::DRAWITEMDATA structure is passed in the WPARAM parameter of the CExtPopupMenuWnd::g_nMsgPopupDrawItem message. So, first of all, your painting code should invoke pDrawItemData->PaintDefault( false, true ) to draw the entire menu item but its text. To compute the text rectangle, use this code:
CRect rcText = *pDrawItemData->m_pRectItem;
rcText.left = pDrawItemData->m_pItemData->GetIconAreaWidth();
After that you can draw a text string using your custom font. Please do not forget to add the definition below to the message map of the window class that repaints menu items:
ON_REGISTERED_MESSAGE(
        CExtPopupMenuWnd::g_nMsgPopupDrawItem,
        OnDrawPopupMenuItem
        )

How to modify or suppress entirely built-in pop-up menus available in Prof-UIS?

The constants specifying built-in pop-up menus are listed in the internal enumeration of the CExtControlBar::POPUP_MENU_EVENT_DATA structure in the ExtControlBar.h file:

enum // Prof-UIS notification types
{
__PMED_DOCKBAR_CTX           =  0, // dockbar context menu
__PMED_CONTROLBAR_CTX        =  1, // any control bar context menu (client area)
__PMED_CONTROLBAR_NC_CTX     =  2, // any control bar context menu (non-client area)
__PMED_STATUSBAR_CTX         =  3, // statusbar context menu
__PMED_AUTOHIDESLIDER_CTX    =  4, // autohide slider window context menu
__PMED_MINIFRAME_NC_CTX      =  5, // miniframe context menu (non-client area)
__PMED_MDICLIAREA_CTX        =  6, // MDI client area context menu
__PMED_MDITABS_CTX           =  7, // MDI-tabs window
__PMED_AUTOHIDETABS_CTX      =  8, // autohide-tabs window
__PMED_DYNCBCTABS_CTX        =  9, // dynamic control bar container tabs window
__PMED_CONTROLBAR_NCBTNMENU_TOP   = 10, // control bar nc-area-menu-button - top level
__PMED_CONTROLBAR_NCBTNMENU_BARS  = 11, // control bar nc-area-menu-button - control bars list 
__PMED_CTXEXPBTN_TOP        = 12, // content expand button - top level
__PMED_CTXEXPBTN_APPEND     = 13, // content expand button - append to buttons list
__PMED_CTXEXPBTN_BARS       = 14, // content expand button - control bars list
__PMED_CONTROLBAR_NCBTNMENU_DYNSTATE = 15, // dynamic resizable control bar nc-area-menu-button
__PMED_TAB_PAGE_CONTAINER_TABS_CTX   = 16, // page-container-as-main-view-tabs window
};
You can modify, completely recreate, or entirely suppress any built-in Prof-UIS pop-up menu. The CExtControlBar::g_nMsgConstructPopupMenu registered windows message is sent twice to the main frame window for each of built-in pop-up menus. When the message is sent for the first time, you can create a pop-up menu from scratch. When it is sent for the second time, you can modify the pop-up menu created by default. So, your handler method may look like:
// Message map
ON_REGISTERED_MESSAGE( CExtControlBar::g_nMsgConstructPopupMenu, OnConstructPopupMenuCB )


// Handler
LRESULT CMainFrame::OnConstructPopupMenuCB( WPARAM wParam, LPARAM lParam )
{
   ASSERT_VALID( this );
   lParam;
   CExtControlBar::POPUP_MENU_EVENT_DATA * p_pmed =
      CExtControlBar::POPUP_MENU_EVENT_DATA::FromWParam( wParam );
   ASSERT( p_pmed != NULL );
   ASSERT_VALID( p_pmed->m_pPopupMenuWnd );
   ASSERT_VALID( p_pmed->m_pWndEventSrc );
   ASSERT( p_pmed->m_pWndEventSrc->GetSafeHwnd() != NULL );
   ASSERT( ::IsWindow(p_pmed->m_pWndEventSrc->GetSafeHwnd()) );
   if( p_pmed->m_bPostNotification )
   {
      // p_pmed->m_pPopupMenuWnd contains default items
      // you can change this menu here
   }
   else
   {
      // initialize the p_pmed->m_pPopupMenuWnd menu
      // from scratch
      // otherwise return 0 to get this method called for the second time
   }
   return (!0);
}

The p_pmed->m_nHelperNotificationType variable specifies the type of the built-in pop-up menu to be initialized or modified (see the enumeration above).

For example, the ProfStudio sample handles the CExtControlBar::g_nMsgConstructPopupMenu registered Windows message in the CMainFrame::OnConstructPopupMenuCB() method.

As another example, you can suppress the menu to be appeared over the dock site by using the following code:
LRESULT LRESULT CMainFrame::OnConstructPopupMenuCB(
    WPARAM wParam, LPARAM lParam
    )
{
   ASSERT_VALID( this );
   lParam;
   CExtControlBar::POPUP_MENU_EVENT_DATA * p_pmed =
      CExtControlBar::POPUP_MENU_EVENT_DATA::FromWParam( wParam );
   ASSERT( p_pmed != NULL );
   ASSERT_VALID( p_pmed->m_pPopupMenuWnd );
   ASSERT_VALID( p_pmed->m_pWndEventSrc );
   ASSERT( p_pmed->m_pWndEventSrc->GetSafeHwnd() != NULL );
   ASSERT( ::IsWindow(p_pmed->m_pWndEventSrc->GetSafeHwnd()) );

   if( ( !p_pmed->m_bPostNotification)
       && p_pmed->m_nHelperNotificationType ==
         CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_DOCKBAR_CTX
      )
      return (!0);

   return 0;
}
If you do not want this kind of menu at all, use the code like this:
LRESULT CMainFrame::OnConstructPopupMenuCB(
   WPARAM wParam, LPARAM lParam
   )
{
   ASSERT_VALID( this );
   lParam;
   CExtControlBar::POPUP_MENU_EVENT_DATA * p_pmed =
      CExtControlBar::
         POPUP_MENU_EVENT_DATA::
            FromWParam( wParam );
   ASSERT( p_pmed != NULL );
   ASSERT_VALID( p_pmed->m_pPopupMenuWnd );
   ASSERT_VALID( p_pmed->m_pWndEventSrc );
   ASSERT( p_pmed->m_pWndEventSrc->GetSafeHwnd() != NULL );
   ASSERT( ::IsWindow(p_pmed->m_pWndEventSrc->GetSafeHwnd()) );

   return (!0); // Leaves any built-in menu empty (i.e. suppress any built-in menu)

}

Is there a way to handle the highlighting of menu items and toolbar buttons?

Prof-UIS sends the CExtPopupMenuWnd::g_nMsgItemCoveringNotification notification message, which is sent to the parent window when the user highlights a menu item with the mouse pointer or keyboard or hovers the mouse pointer over a toolbar button. For menu items, this message is similar to the standard windows message WM_MENUSELECT. For example, you can implement a handler for this message to show custom tooltips (as it is done in the HelpNotes sample).
// method's declaration in class scope
afx_msg LRESULT OnItemCoveringNotification(
   WPARAM wParam,
   LPARAM lParam 
);
 
// message map entry
ON_REGISTERED_MESSAGE(
    CExtPopupMenuWnd::g_nMsgItemCoveringNotification,
    OnItemCoveringNotification
    )
 

// method's body
LRESULT CMainFrame::OnItemCoveringNotification(
    WPARAM wParam, LPARAM lParam );
{
    lParam;
    CExtPopupMenuWnd::ITEMCOVERINGNOTIFICATON * pICN =
        CExtPopupMenuWnd::
            ITEMCOVERINGNOTIFICATON::
                FromWPARAM( wParam );
    ASSERT( pICN != NULL );
    UINT nCmdID = 0;
    if( pICN->m_pPopup != NULL )
    { // if notification from popup menu item
        ASSERT_VALID( pICN->m_pPopup );
        ASSERT( pICN->m_pTBB == NULL );
        nCmdID =
            pICN->m_pPopup->ItemGetInfo(
                pICN->m_nPopupItemIndex
                ).GetCmdID()
    } // if notification from popup menu item
    else
    { // if notification from toolbar button
        ASSERT_VALID( pICN->m_pTBB );
        ASSERT( pICN->m_pPopup == NULL );
        nCmdID =
            m_pTBB->GetCmdID( true );
    } // if notification from toolbar button

    // TO DO: alalyze help information for
    //        nCmdID command here

    return 0L;
}

How to set pop-up menu visualization options?

The pop-up menu class CExtPopupMenuWnd has the following properties:

Property Default Value Meaning
static bool g_bMenuWithShadows; true Shadow is turned on
static bool g_bMenuExpanding; true Rarely used items are initially hidden
static bool g_bMenuHighlightRarely; true Rarely used items are displayed in a different style
static bool g_bMenuShowCoolTips; true Cool tooltips are turned on
static bool g_bMenuExpandAnimation; true Animation for expanding rarely used items is turned on
static bool g_bUseDesktopWorkArea; true If true, menu is aligned to the desktop work area, otherwise — to the screen area
static e_animation_type_t g_DefAnimationType; __AT_FADE Default menu animation. Acceptable values: __AT_NONE __AT_RANDOM __AT_ROLL __AT_SLIDE __AT_FADE __AT_ROLL_AND_SREETCH __AT_SLIDE_AND_SREETCH __AT_NOISE __AT_BOXES __AT_CIRCLES __ AT_HOLES

How to implement expandable menus?

You can take a look at how to do this in the DRAWCLI sample. When you open any menu from the menu bar, the only items that are visible at first correspond to basic commands. You will see other items when you click on the Expand button at the bottom of the menu or when you press the CTLT+DOWN_ARROW key combination. The frequently used or basic commands are those that do not depend on usage statistics or a number of clicks. All application commands are registered in the command manager (CExtCmdManager), whose members and methods can be accessed via the global smart pointer variable g_CmdManager with operator ->. The SetBasicCommands() method allows you to replenish the basic commands list. The system commands (from the window's system menu), OLE commands and the commands relating to MRU files and to MDI windows are automatically considered to be basic.

Prof-UIS expandable menu: folded Prof-UIS expandable menu: unfolded
If you want to disable the most recently used menu items, there are two ways to do this:
  • add the following lines to your initialization code
    CExtPopupMenuWnd::g_bMenuExpanding = false;
    CExtPopupMenuWnd::g_bMenuHighlightRarely = false;
    This way is preferable.
  • use g_CmdManager->SetBasicCommands to make all your commands basic i.e. initially visible in your menus.

How to insert menu items at run time?

You need to override the CExtPopupMenuWnd::g_nMsgPrepareMenu registered message in the frame window so that you can modify menus. This message is generated each time before any pop-up menu appears on the screen. Please add this line to the message map of the frame:
ON_REGISTERED_MESSAGE
   ( 
     CExtPopupMenuWnd::g_nMsgPrepareMenu,
     OnExtMenuPrepare
   )
Then, add this method to your frame window:
LRESULT CMainFrame::OnExtMenuPrepare(WPARAM wParam, LPARAM lParam)

{

  lParam;

  CExtPopupMenuWnd::MsgPrepareMenuData_t * pData =

  reinterpret_cast< CExtPopupMenuWnd::MsgPrepareMenuData_t * >
               (wParam);                                         

  ASSERT( pData != NULL );

  CExtPopupMenuWnd * pPopup = pData->m_pPopup;

  ASSERT( pPopup != NULL );

  // HERE IS YOUR CODE 
  // TO MODIFY pPopup (insert or remove anything)   

}
You may add some commands to the menu in resources so that these commands can be replaced with other commands in the CMainFrame::OnExtMenuPrepare() method. If you don’t need to replace these commands, you may simply remove them.
For example, if we added an ID_MY_REPLACE_CMD command to the File menu, you can use the following code in the CMainFrame::OnExtMenuPrepare() method:
INT nReplacePos = pPopup->ItemFindPosForCmdID(ID_MY_REPLACE_CMD);

if(  nReplacePos >= 0 )

{

   // USER SHOULD NOT SEE THIS COMMAND

   VERIFY( pPopup->ItemRemove(nReplacePos) );

   // YOU ALSO MAY INSERT SOME COMMANDS TO THIS POSITION

   VERIFY( pPopup->ItemInsert( 
         (UINT)CExtPopupMenuWnd::TYPE_SEPARATOR, nReplacePos) 
   );

   VERIFY( pPopup->ItemInsert( ID_SOME_COMMAND, nReplacePos) );

}
Please note that all the commands should be registered in the command manager.The DRAWCLI sample carefully uses this technique to handle OLE menus and insert pop-up submenus for handling colors.

If you have any questions, please visit our forum or contact our technical support team at support@prof-uis.com.