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 :
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 InitContextMenuManager(); // construit l'unique objet gestionnaire de menus contextuels
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).
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
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.
10. Pour garantie notre look and feel nous devons inscrire nos menus contextuels dans le CContextMenuManager.
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
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();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
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); }
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::SetMenuSizes(CSize(22,22), CSize(16, 16));
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 CMFCToolBar::AddToolBarForImageCollection(IDR_TOOLBAR_MENUS_IMAGES, 0, 0, IDB_MENUS_IMAGES);
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
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; }
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 void CMyView::OnRButtonUp(UINT nFlags, CPoint point) { ClientToScreen(&point); theApp.GetContextMenuManager()->ShowPopupMenu(m_nMenuID, point.x, point.y, this, TRUE); }
m_nMenuID est initialisé à IDR_MENU1 dans le constructeur de la vue.
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); }
N'oubliez pas d'ajouter des gestionnaires de commandes aux menus sinon les menus items sont désactivés par défaut.
Et voilà
Partager