Nous voulons placer des petites images à gauche des commandes de menus de nos menus contextuels afin qu'ils aient un look and feel de VS 2005 ou d'Office 2003, 2007 ou XP.

Pour y parvenir nous avons besoin :

1. D'un gestionnaire de menus contextuels le manager CContextMenuManager qui appliquera notre look.
2. D'une bande de petites images placées sur un seul bitmap (en 24 bits c'est plus jolie) afin de définir notre collection d'images.
3. D'une resource de type barre d'outils dans l'éditeur de resource qui identifiera les IDs des items des menus aux images sur ces items de menus.
4. Et enfin de la classe CMFCToolBar qui chargera nos images.

Premièrement pour pouvoir utiliser le gestionnaire des menus :

5. Nous avons besoin que l'objet application puisse dériver de CWinAppEx qui initialise correctement toute la famille des classes des gestionnaires dont l'un d'eux est le CContextMenuManager. Et donc on remplace toutes les occurences de CWinApp en CWinAppEx.

6. Dans la méthode InitInstance() de notre objet application nous insérons le code juste un peu avant la construction de notre frame principale ou de notre boite de dialogue :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 
	InitContextMenuManager();    // construit l'unique objet gestionnaire de menus contextuels
7. Ensuite dans l'éditeur de resource nous nous mettons à contruire nos différents menus contextuels dont voici trois menus d'exemples IDR_MENU1, IDR_MENU2 et IDR_MENU3
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
IDR_MENU1 MENU 
BEGIN
    POPUP "Menu1"
    BEGIN
        MENUITEM "Utilisateur",                 ID_USER
        MENUITEM "Maison",                      ID_HOUSE
        MENUITEM "Information",                 ID_INFORMATION
        MENUITEM "Fenêtre",                     ID_WINDOWS
    END
END
 
IDR_MENU2 MENU 
BEGIN
    POPUP "Menu2"
    BEGIN
        MENUITEM "Vraie",                       ID_TRUE
        MENUITEM "False",                       ID_FALSE
    END
END
 
IDR_MENU3 MENU 
BEGIN
    POPUP "Menu3"
    BEGIN
        MENUITEM "Exclamation",                 ID_EXCLAMATION
        MENUITEM "Question",                    ID_QUESTION
        MENUITEM "Actualiser",                  ID_REFRESH
        MENUITEM "Aller",                       ID_GO
        MENUITEM "Message",                     ID_MESSAGE
    END
END
8. Toujours dans l'éditeur de resource on prépare nos petites images (bitmap) de 16 X 16. Soient peut être 11 petites images pour chaque item de nos 3 menus contextuels. (Il n'est pas dit que chaque item de menu doit avoir une image).
On ajoute donc dans les ressources un long bitmap en 24 bits IDB_MENUS_IMAGES de (Height = 16, Width =176) pour contenir nos 11 petites images. Les petites images sont placées côte à côte sur le long bitmap (par copie-coler) dont le nom est MenuImages.bmp dans le sous dossier res de notre projet.

9. Dans l'éditeur de resource on ajoute une nouvelle barre d'outils IDR_TOOLBAR_MENUS_IMAGES. Et on se met à créer les 11 petits boutons en leur attribuant juste les IDs seulement (sans se préoccuper de l'image qui est dessus).
Ici il faut faire attention, l'ordre d'affectation des IDs des boutons de la barre d'outils doivent correspondre à 2 choses :
9a. Ils doivents impérativement êtres un des IDs des items de vos menus sinon ça ne fonctionnera pas et le menu item sera sans image.
9b. Ils doivents correspondre à l'ordre de succession des petites images qui se suivent sur le IDB_MENUS_IMAGES.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
IDR_TOOLBAR_MENUS_IMAGES TOOLBAR  16, 15
BEGIN
    BUTTON      ID_USER
    BUTTON      ID_HOUSE
    BUTTON      ID_INFORMATION
    BUTTON      ID_WINDOWS
    BUTTON      ID_TRUE
    BUTTON      ID_FALSE
    BUTTON      ID_EXCLAMATION
    BUTTON      ID_QUESTION
    BUTTON      ID_REFRESH
    BUTTON      ID_GO
    BUTTON      ID_MESSAGE
END
10. Pour garantie notre look and feel nous devons inscrire nos menus contextuels dans le CContextMenuManager.
Une méthode candidate est la méthode virtuelle PreLoadState() qui surcharge celle de CWinAppEx de notre classe application.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
virtual void PreLoadState();
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
 
void CMyApp::PreLoadState()
{
	CContextMenuManager* pMgr = GetContextMenuManager();
 
	pMgr->AddMenu("Menu1", IDR_MENU1);
	pMgr->AddMenu("Menu2", IDR_MENU2);
	pMgr->AddMenu("Menu3", IDR_MENU3);
}
11. Dans le cas d'une application SDI ou MDI nous pouvons charger nos images dans le OnCreate() de la frame principale alors que pour une boite de dialogue dans son OnInitDialog() ainsi nous commençons par définir la taille des boutons de nos menu images
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 
CMFCToolBar::SetMenuSizes(CSize(22,22), CSize(16, 16));
12. Ensuite pour le cas d'une application basé sur une boite de dialogue nous avons :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 
CMFCToolBar::AddToolBarForImageCollection(IDR_TOOLBAR_MENUS_IMAGES, 0, 0, IDB_MENUS_IMAGES);
13. Pour le cas des applications SDI ou MDI. La méthode CMainFrame::OnCreate() a déjà crée la toolbar principale (standard) de l'application. Nous allons juste modifier le code légèrement en insérant dans les ressources le bitmap IDB_MAINFRAME_256 à partir du fichier existant Toolbar256.bmp de la toolbar IDR_MAINFRAME_256. Et ensuite on réécrit le code de chargement de la toolbar standard
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	//...       
             CMFCToolBar::SetMenuSizes(CSize(22,22), CSize(16, 16));

	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME, 0, IDB_MAINFRAME_256))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}
             //...
             CMFCToolBar::AddToolBarForImageCollection(IDR_TOOLBAR_MENUS_IMAGES, 0, 0, IDB_MENUS_IMAGES);
	return 0;
}
14. Et dans la vue (ici une formview) nous avons nos menus contextuels que nous affichons à l'aide du gestionnaire de menu pour nous garantir un bon look and feel en interceptant le click droit (bouton droit de la souris relevé).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
 
void CMyView::OnRButtonUp(UINT nFlags, CPoint point)
{
	ClientToScreen(&point);
	theApp.GetContextMenuManager()->ShowPopupMenu(m_nMenuID, point.x, point.y, this, TRUE);
}
où m_nMenuID est un des id des menus soit IDR_MENU1 ou IDR_MENU2 ou IDR_MENU3 que nous permuttons par double click.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
void CMyView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	switch(m_nMenuID)
	{
	case IDR_MENU1:
		m_nMenuID = IDR_MENU2;
		break;
 
	case IDR_MENU2:
		m_nMenuID = IDR_MENU3;
		break;
 
	case IDR_MENU3:
		m_nMenuID = IDR_MENU1;
		break;
	}
 
	CFormView::OnLButtonDblClk(nFlags, point);
}
m_nMenuID est initialisé à IDR_MENU1 dans le constructeur de la vue.
N'oubliez pas d'ajouter des gestionnaires de commandes aux menus sinon les menus items sont désactivés par défaut.

Et voilà