FAQ VC++ et MFCConsultez toutes les FAQ
Nombre d'auteurs : 20, nombre de questions : 545, dernière mise à jour : 5 avril 2013 Ajouter une question
Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++
Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.
Sur ce, je vous souhaite une bonne lecture. Farscape
- Comment ajouter une CToolbar sur une fenêtre ?
- Comment rendre inactif un bouton dans une CToolBar ?
- Comment insérer une CComboBox dans une CToolBar ?
- Comment redimensionner une CToolBar sur l'insertion dynamique d'un bouton ?
- Comment enlever le bouton de fermeture sur une CToolBar ?
- Comment construire une barre d'outils contenant n'importe quel contrôle ?
- Comment provoquer l'affichage d'une CToolbar ou CDialogBar ?
- Comment mémoriser l'emplacement des barres d'outils?
- Comment faire un bouton à deux états dans une barre d'outils ?
- Comment rafraîchir une barre d'outils flottante ?
- Comment positionner deux barres d'outils sur la même ligne ?
Commencer par la définir dans l'éditeur de ressources.
Puis procéder à son initialisation dans la fonction OnCreate de la MdiChild qui est la classe parent (au sens Windows) de la fenêtre.
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | int CMyMDIChildWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CMDIChildWnd::OnCreate(lpCreateStruct) == -1) return -1; // CToolBar m_ToolBar; if(!m_ToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP) || !m_ToolBar.LoadToolBar(IDR_TOOLBAR)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } return 0; } |
Il faut gérer la notification de message ON_UPDATE_COMMAND_UI .
Avec l'aide de ClassWizard :
- Sélectionner la classe fenêtre concernée.
- Sélectionner l'id de la toolbar concernée
Dans la partie droite de l'écran deux notifications sont disponibles :
- COMMAND: pour gérer l'action du click sur le bouton.
- UPDATE_COMMAND_UI : pour gérer l'activité du bouton.
Exemple de notification générée par ClassWizard sur l'id ID_EDIT_CUT
Code c++ : | Sélectionner tout |
1 2 3 4 5 | BEGIN_MESSAGE_MAP(CTestdlgBarMDIApp, CWinApp) //{{AFX_MSG_MAP(CTestdlgBarMDIApp) ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) ………. |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 | void CTestdlgBarMDIApp::OnUpdateEditCut(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->Enable(m_bTestCut); // si m_bTestCut=false bouton grisé sinon actif. } |
Principe : A la place du code classique de création de la toolbar dans la mainframe à partir de la fonction OnCreate , on écrira ceci :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if(!CreateToolBar()) return -1; if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); return 0; } |
Code c++ : | Sélectionner tout |
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 33 34 35 36 37 38 39 40 | // ----------------------------------------------- BOOL CMainFrame::CreateToolBar() { 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(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return FALSE; // fail to create } TBBUTTON button; button.iBitmap=NULL; button.idCommand=0; button.fsStyle=TBSTYLE_SEP; button.dwData=0; button.iString=NULL; m_wndToolBar.GetToolBarCtrl().InsertButton(0,&button); m_wndToolBar.GetToolBarCtrl().InsertButton(0,&button); m_wndToolBar.SetButtonInfo(0,1,TBBS_SEPARATOR,100); CRect rect; m_wndToolBar.GetItemRect(0,&rect); rect.top=2; rect.bottom=rect.top+100; if(!m_ComboBox.Create(CBS_DROPDOWNLIST | WS_VISIBLE | WS_TABSTOP,rect,&m_wndToolBar,1)) { TRACE0("Failed to create combobox\n"); return FALSE; // fail to create } m_ComboBox.AddString("item 0"); m_ComboBox.AddString("item 1"); m_ComboBox.AddString("item 2"); m_ComboBox.AddString("item 3"); return TRUE; } |
On fixe ensuite les infos sur le bouton à savoir son identifiant ici 1 et sa largeur en pixels :100.
Note : dans le cas d'un séparateur la fonction SetButtonInfo accepte la largeur en pixels au lieu de l'indice de l'image.
Voir documentation MSDN pour plus de détails.
Ensuite on récupère la place de l'item 0 et on lui recalcule sa hauteur.
On crée la ComboBox.
Et pour finir on l'alimente par AddString.
Pour manipuler les notifications on pourra rajouter la notification OnComboChange directement sur le message map de la mainframe :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_WM_GETMINMAXINFO() //}}AFX_MSG_MAP ON_CBN_SELCHANGE(1,OnComboChange) END_MESSAGE_MAP() void CMainFrame::OnComboChange() { // int nSel=m_ComboBox.GetCurSel(); if(nSel!=CB_ERR) { CString str; m_ComboBox.GetLBText(nSel,str); TRACE("\nCombo Sel:%s",(const char *)str); } } |
Proposition de classe :
Code c++ : | Sélectionner tout |
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | ///////////////////////////////////////////////////////////////////////////// // CToolBarEx window class CToolBarEx : public CToolBar { // Construction public: CToolBarEx(); // Attributes public: void SetSizes(SIZE sizeButton, SIZE sizeImage) { GetToolBarCtrl( ).SetButtonSize(sizeButton); if(GetToolBarCtrl( ).SetBitmapSize(sizeImage)) m_sizeImage=sizeImage; } inline void InitSizes(CSize cSizeBitmapSize) { m_SizeButton=cSizeBitmapSize; SetSizes(CSize(cSizeBitmapSize.cx+7,cSizeBitmapSize.cy+6),cSizeBitmapSize); GetToolBarCtrl().AutoSize(); } bool SetButtonWidth(UINT nMinWidth,UINT nMaxWidth); CSize GetButtonsWidth() const; CSize GetButtonsSize() const; bool AddButtonToolBar(int nIndexPos,int nidCommand,UINT nIdbitmap,int istring=0); bool DeleteButtonToolBar(int nIndexPos); void RedrawToolBar(BOOL bRecalcLayout=TRUE,BOOL bOnlyFrame=FALSE); void RedrawButton(int nIndex); void UpdateSizes(); void ReCalcDynamicLayout(CRect rect,int nIndexPos=-1); // Attributes private: CSize m_sizeMiniMaxi; CSize m_SizeButton; CSize m_sizeImage; // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CToolBarEx) //}}AFX_VIRTUAL // Implementation public: virtual ~CToolBarEx(); // Generated message map functions protected: //{{AFX_MSG(CToolBarEx) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// // CToolBarEx CToolBarEx::CToolBarEx() { m_SizeButton.cx=16; m_SizeButton.cy=15; } CToolBarEx::~CToolBarEx() { } BEGIN_MESSAGE_MAP(CToolBarEx, CToolBar) //{{AFX_MSG_MAP(CToolBarEx) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CToolBarEx message handlers bool CToolBarEx::SetButtonWidth(UINT nMinWidth,UINT nMaxWidth) { ASSERT(::IsWindow(GetSafeHwnd())); ASSERT(nMaxWidth-m_sizeImage.cx>=7); if(SendMessage(TB_SETBUTTONWIDTH, 0, MAKELPARAM(nMinWidth, nMaxWidth))) { m_sizeMiniMaxi.cx=nMinWidth; m_sizeMiniMaxi.cy=nMaxWidth; return true; } return false; } //---------------------------------------------------------------- CSize CToolBarEx::GetButtonsWidth() const { ASSERT(::IsWindow(GetSafeHwnd())); return m_sizeMiniMaxi; } //---------------------------------------------------------------- CSize CToolBarEx::GetButtonsSize() const { ASSERT(::IsWindow(GetSafeHwnd())); DWORD result=(DWORD)::SendMessage(m_hWnd,TB_GETBUTTONSIZE,0,(LPARAM)0); return CSize(LOWORD(result),HIWORD(result)); } //---------------------------------------------------------------- void CToolBarEx::RedrawToolBar(BOOL bRecalcLayout/*=TRUE*/, BOOL bOnlyFrame/*=FALSE*/) { ASSERT(::IsWindow(GetSafeHwnd())); if(!IsWindowVisible())return; if(bRecalcLayout) { CWnd *pParent=GetToolBarCtrl( ).GetParent(); CFrameWnd* pFrameWnd=(CFrameWnd *)pParent->GetParent(); if(pFrameWnd!=NULL) { pFrameWnd->RecalcLayout(); for(int nIndex=0; nIndex<GetToolBarCtrl( ).GetButtonCount(); nIndex++) { RedrawButton(nIndex); CRect rect; GetItemRect(nIndex,rect); ValidateRect(rect); } } } else { if(!bOnlyFrame) { GetToolBarCtrl( ).RedrawWindow(NULL,NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME|RDW_ALLCHILDREN); } } if(bOnlyFrame) { GetToolBarCtrl( ).SetWindowPos(NULL,0,0,0,0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_DRAWFRAME); } } //---------------------------------------------------------------- void CToolBarEx::RedrawButton(int nIndex) { ASSERT(::IsWindow(GetSafeHwnd())); if(nIndex<0 || nIndex>GetToolBarCtrl().GetButtonCount()) { return; } CRect rect; GetToolBarCtrl( ).GetItemRect(nIndex,rect); GetToolBarCtrl( ).RedrawWindow(rect); } //---------------------------------------------------------------- void CToolBarEx::UpdateSizes() { SetSizes(GetButtonsSize(),m_sizeImage); GetToolBarCtrl().AutoSize(); } //---------------------------------------------------------------- bool CToolBarEx::DeleteButtonToolBar(int nIndexPos) { CRect rect; GetToolBarCtrl( ).GetWindowRect(&rect); if(!GetToolBarCtrl( ).DeleteButton(nIndexPos)) return false; // resize window rect.right-=(m_SizeButton.cx+7); SetWindowPos(NULL,0,0,rect.Width(),rect.Height(), SWP_NOMOVE|SWP_NOZORDER|SWP_DRAWFRAME|SWP_FRAMECHANGED); ReCalcDynamicLayout(rect); return true; } //---------------------------------------------------------------- void CToolBarEx::ReCalcDynamicLayout(CRect rect,int nIndexPos/*=-1*/) { SetWindowPos(NULL,0,0,rect.Width(),rect.Height(), SWP_NOMOVE|SWP_NOZORDER|SWP_DRAWFRAME|SWP_FRAMECHANGED); if(IsFloating()) { CPoint newPos(0,0); ClientToScreen(&newPos); CRect rcNew; // GetToolBarCtrl().SetRows(GetToolBarCtrl().GetRows(),TRUE, &rcNew); CalcDynamicLayout(rect.Width(),LM_HORZ | LM_COMMIT); CWnd *pParent=GetToolBarCtrl( ).GetParent(); CFrameWnd* pFrameWnd=(CFrameWnd *)pParent->GetParent(); if(pFrameWnd) pFrameWnd->FloatControlBar(this, newPos,CBRS_ALIGN_TOP | CBRS_SIZE_DYNAMIC); } RedrawToolBar(); if(nIndexPos>0)RedrawButton(nIndexPos); } //---------------------------------------------------------------- bool CToolBarEx::AddButtonToolBar(int nIndexPos,int nidCommand,UINT nIdbitmap,int istring/*=0*/) { BOOL bok; CRect rect; GetToolBarCtrl( ).GetWindowRect(&rect); TBBUTTON Buttons; GetToolBarCtrl( ).AddBitmap(1,nIdbitmap); Buttons.iBitmap=nIndexPos; Buttons.idCommand=nidCommand; Buttons.fsState=TBSTATE_ENABLED; Buttons.fsStyle=TBSTYLE_BUTTON; Buttons.dwData=0; Buttons.iString=istring; bok=GetToolBarCtrl( ).AddButtons(1,&Buttons); SetButtonWidth(0,m_SizeButton.cx+7); InitSizes(m_SizeButton); // resize window rect.right+=(m_SizeButton.cx+7); ReCalcDynamicLayout(rect,nIndexPos); return (bok?true:false); } |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // portion de code relatif à la CToolbarEx if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } m_wndToolBar.InitSizes(CSize(16,15)); m_wndToolBar.SetWindowText(_T("Toolbar")); m_wndToolBar.UpdateSizes(); m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); |
l'utilisation de la fonction InitSizes pour spécifier la taille des boutons , et la fonction UpdateSizes() pour la prise en compte des modifications.
Utilisation:
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 | // rajout d'un bouton par un bitmap IDB_BITMAP1 a la position 8 associé a la commande ID_BUTTONADD CMainFrame * pMain=(CMainFrame *)AfxGetMainWnd(); pMain->m_wndToolBar.AddButtonToolBar(8,ID_BUTTONADD,IDB_BITMAP1); // del d'un bouton CMainFrame * pMain=static_cast<CMainFrame *>(AfxGetMainWnd()); pMain->m_wndToolBar.DeleteButtonToolBar(8); |
Deux méthodes sont utilisées suivant que la CToolBar est ancrée ou non ,le détail du traitement est visible dans la fonction ReCalcDynamicLayout.
En surchargeant la fonction virtuelle CalcFixedLayout pour enlever le style WS_SYSMENU à la fenêtre.
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 | CControlBar::CalcFixedLayout Cette méthode calcul la taille horizontal d'une barre de contrôle virtual CSize CalcFixedLayout( BOOL bStretch, BOOL bHorz ); |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 | CSize CMyToolBar::CalcFixedLayout( BOOL bStretch, BOOL bHorz ) { if ( IsFloating() ) // only when we float GetParent()->GetParent()->ModifyStyle( WS_SYSMENU, 0 ); return CToolBar::CalcFixedLayout( bStretch, bHorz ); } |
Visual C++ reconnaît les contrôles communs d'Internet Explorer. Parmi eux, la rebar (CRebar).
Ce contrôle est en fait un conteneur dans lequel on peut mettre des barres d'outils (CToolBar et CDialogBar).
On appelle bande chaque barre d'outils, et on désignera par barre d'outils l'ensemble des bandes.
Pour que l'application intègre une rebar, il faut cocher l'option "Internet Explorer Rebars" à l'étape 4 de l'AppWizard dans la section "How do you want your toolbars look ?".
A l'exécution, on voit que la barre d'outils comporte 2 bandes : la toolBar classique avec ses boutons, et une dialogBar avec la mention "A FAIRE : Disposez la barre de dialogue".
La classe MainFrame possède les données membres suivantes :
Code c++ : | Sélectionner tout |
1 2 3 4 5 | protected: // control bar embedded members CStatusBar m_wndStatusBar; // barre d'état CToolBar m_wndToolBar; // barre d'outils classique CReBar m_wndReBar; // la rebar CDialogBar m_wndDlgBar; // la barre de dialogue |
Code c++ : | Sélectionner tout |
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 33 | int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... // création de la toolbar if (!m_wndToolBar.CreateEx(this) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } // création de la dialogbar if (!m_wndDlgBar.Create(this, IDR_MAINFRAME, CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR)) { TRACE0("Failed to create dialogbar\n"); return -1;// fail to create } // création de la rebar et ajout de la toolbar et de la dialogbar if (!m_wndReBar.Create(this) || !m_wndReBar.AddBar(&m_wndToolBar) || !m_wndReBar.AddBar(&m_wndDlgBar)) { TRACE0("Failed to create rebar\n"); return -1; // fail to create } ... return 0; } |
A l'invite suivante, choisissez CMainFrame dans la liste puis validez.
On choisit CMainFrame et non une nouvelle classe de dialogue car on veut ajouter une barre d'outils et non pas une nouvelle classe de dialogue.
Ensuite, programmez les gestionnaires des contrôles de la rebar (i.e. de la dialogbar de la rebar).
Les barres de dialogue ou barres d'outils sont créées habituellement dans la fonction OnCreate de la mainframe de l'application et éventuellement dans la MDIChild (en plus) dans un contexte MDI.
Ce cas de figure fonctionne très bien si le composant est visible dès sa création.
Si celui-ci est créé en mode caché ou s'il est créé à un autre moment que la fonction OnCreate celui-ci n'apparaît pas.
On utilisera alors la fonction RecalcLayout pour provoquer le rafraîchissement des barres d'outils ou barre de dialogue.
Exemple avec la création dynamique d'une barre de dialogue:
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 | void CMyMDIChild::CreateDialogBar() { m_pDlgBar = new CDialogBar(); m_pDlgBar->Create(this,IDD_CHILDBAR,CBRS_TOP,115); RecalcLayout(); } |
Ou plutôt comment sauvegarder automatiquement et à chaque fermeture du programme la dernière position de toutes ses barres d'outils et de barres de dialogue? Et pas seulement la position, sa visibilité, si elle était flottante ou non, etc... Pour cela, il suffit tout simplement d'utiliser les fonctions SaveBarState() et LoadBarState() de la classe CFrameWnd.
Lorsque l'on ferme l'application, il suffit de surcharger la fonction OnClose() de la classe CMainFrame() comme suit :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void CMainFrame::OnClose() { // TODO: Add your message handler code here and/or call default /* * Ici on ajoute la sauvegarde de toutes les barres d'outils présentes * dans le projet grâce à la fonction SaveBarState. Cette fonction * prend comme argument le nom de la clef dans lequel sera stocké * les informations dans la base de registres. */ this->SaveBarState("Clef_Ammont\\Ici_Ma_Sauvegarde"); CMDIFrameWnd::OnClose(); // appel de la fonction de base } |
Cette fonction n'est pas présente par défaut, il faut rajouter un "handler" en utilisant le wizard de visual c++ sur le message WM_CLOSE.
Voilà pour la sauvegarde, et maintenant pour récupérer les données il suffit de faire lors de la création des barres d'outils dans la MainFrame l'opération inverse à un détail près.
Il faut effectivement lors de la création des barres d'outils renseigner celles-ci de leur propre ID, car hélas, pour des raisons obscures, ils ne sont pas mémorisés lors de l'appel de la fonction Create()...
Pour cela, il suffit d'appeler la fonction SetDlgCtrlID du contrôle de la barre pour leur affecter leur propre ID après que celle-ci ait été créée.
Le plus souvent, la création des toolbars se fait dans la fonction OnCreate() du MainFrame.
Ainsi, il suffit de la modifier comme suit pour obtenir le fonctionnement désiré :
Code c++ : | Sélectionner tout |
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; 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(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } /* * Attribution de l'ID au control car n'est pas effectué lors de la * création. Il faut impérativement le faire sinon cela fera planter * le programme lorsque plusieurs toolbars seront flottantes!! * Il faut également s'assurer que les ids soient différents d'une * barre à l'autre!! */ m_wndToolBar.SetDlgCtrlID(IDR_MAINFRAME); if (!m_wndToolBar2.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar2.LoadToolBar(IDR_MAINFRAME2)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } /* * Attribution de l'ID au control car n'est pas effectué lors de la * création. Il faut impérativement le faire sinon cela fera planter * le programme lorsque plusieurs toolbars seront flottantes!! * Il faut également s'assurer que les ids soient différents d'une * barre à l'autre!! */ m_wndToolBar2.SetDlgCtrlID(IDR_MAINFRAME2); if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } /* * La barre de status n'a pas besoin d'être mémorisée, sa position * ne varie pas car elle n'est pas "Dockable". */ // TODO: Delete these three lines if you don't want the toolbar to // be dockable EnableDocking(CBRS_ALIGN_ANY); m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); m_wndToolBar2.EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); DockControlBar(&m_wndToolBar2); /* * C'est ici, APRES toutes les initialisations que doit être effectué * la récupération des positions des barres d'outils. Assurez-vous * que les barres soient créées avant que cette fonction soit appellée * et avant que EnableDocking soit appellé également. */ LoadBarState("Clef_Ammont\\Ici_Ma_Sauvegarde"); return 0; } |
Voilà, il n'y a plus qu'à compiler et à essayer!! Je n'ai eu aucun problème avec Visual C++ V6.
Ceci fonctionne avec toutes les classes dérivées de CControlBar.
Note : Cela n'a d'intérêt que si les barres d'outils sont "Dockables"!! Voir la fonction EnableDocking() pour plus d'infos.
Il est parfois utile de disposer pour le bouton d'une barre d'outils d'un deuxième état.
L'exemple le plus simple étant par exemple un bouton avec une icône de lecture par défaut et lorsqu'il est actionné l'image stop apparaît.
Ou un cadenas ouvert puis fermé indiquant visuellement qu'une action est interdite.
Le principe :
Il suffira de rajouter un bitmap pour visualiser le nouvel état du bouton dans la barre d'outils
Et de le permuter avec l'image initiale après que le bouton ait été pressé .
Concrètement le traitement se passera dans la MDIChild dans le cas d'un projet MDI où la MainFrame pour un projet SDI.
On pourra aussi faire une classe dérivée de CToolBar et inclure ces fonctionnalités dedans..
Code C++ : | Sélectionner tout |
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | class CChildFrame : public CMDIChildWnd { DECLARE_DYNCREATE(CChildFrame) public: CChildFrame(); // Attributes public: CToolBar m_wndToolBar; // Operations public: struct CUSTOMBT { int nIndiceOrg; int nIndiceNew; CString strNewTxt; CString strOldtxt; }; // fixe le deuxieme etat (bitmap) pour le bouton nIDBt. void SetButton(int nIDBt,UINT nBitmapID,const char *szNextText); // mise à jour de l'état du bouton int UpdateButton(int nIDBt); // fixe le numero d'image pour le bouton nIDBt BOOL SetButtonImage(int nIDBt,int nImage); // recupere le numero d'image pour le bouton nIDBt BOOL GetButtonImage(int nIDBt,int &rnImage); // rajoute un bitmap à la barre d'outils. BOOL AddBitmapToolBar(int nNumButtons,UINT nBitmapID ); // fixe l'etat visuel du bouton dans la barre d'outils pressé/non préssé. BOOL SetButtonPressed(int nIDBt,bool bPressed=true); // met a jour le statut du bouton et renvoie TRUE si il est pressé. BOOL IsButtonPressed(int nIDBt,bool bMajBt=true); // renvoie le nombre de button dans la barre d'outil. int GetButtonCount(); private: CMap<UINT ,UINT ,struct CUSTOMBT ,struct CUSTOMBT> m_mapCustomBt; //...................... |
code :
Code C++ : | Sélectionner tout |
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | //---------------------------------------------------------------- int CChildFrame::UpdateButton(int nIDBt) { struct CUSTOMBT custom; if(!m_mapCustomBt.Lookup(nIDBt,custom)) return -1; int rnImage; if(GetButtonImage(nIDBt,rnImage)) { rnImage=(rnImage==custom.nIndiceNew?custom.nIndiceOrg:custom.nIndiceNew); SetButtonImage(nIDBt,rnImage); // met le bouton enfoncé dans le cas du deuxieme etat. SetButtonPressed(nIDBt,rnImage==custom.nIndiceNew); return (rnImage==custom.nIndiceNew); } return -1; } //---------------------------------------------------------------- void CChildFrame::SetButton(int nIDBt,UINT nBitmapID,const char *szNextText) { struct CUSTOMBT custom; int nNumButtons=m_wndToolBar.GetToolBarCtrl().GetImageList()->GetImageCount(); custom.nIndiceNew=AddBitmapToolBar(nNumButtons,nBitmapID); custom.strNewTxt=szNextText; GetButtonImage(nIDBt,custom.nIndiceOrg); m_mapCustomBt.SetAt(nIDBt,custom); } //---------------------------------------------------------------- BOOL CChildFrame::SetButtonImage(int nIDBt,int nImage) { TBBUTTONINFO tbbi; tbbi.dwMask = TBIF_IMAGE; tbbi.cbSize = sizeof tbbi; BOOL b=m_wndToolBar.GetToolBarCtrl().GetButtonInfo(nIDBt, &tbbi ); if(b) { tbbi.iImage=nImage; b=m_wndToolBar.GetToolBarCtrl().SetButtonInfo(nIDBt,&tbbi); m_wndToolBar.GetToolBarCtrl().RedrawWindow(); } return (b && b!=-1); } //---------------------------------------------------------------- BOOL CChildFrame::GetButtonImage(int nIDBt,int &rnImage) { char sztext[256]; TBBUTTONINFO tbbi; tbbi.dwMask = TBIF_IMAGE; tbbi.cbSize = sizeof tbbi; BOOL b= m_wndToolBar.GetToolBarCtrl().GetButtonInfo(nIDBt, &tbbi ); rnImage=tbbi.iImage; return (b && b!=-1); } //---------------------------------------------------------------- BOOL CChildFrame::AddBitmapToolBar(int nNumButtons,UINT nBitmapID ) { return m_wndToolBar.GetToolBarCtrl().AddBitmap(nNumButtons,nBitmapID); } //---------------------------------------------------------------- int CChildFrame::GetButtonCount() { // nombre de boutons dans la toolbar separateur compris. int nct=m_wndToolBar.GetToolBarCtrl().GetButtonCount(); int nCount=0; TBBUTTON tb; for(int i=0;i<nct;i++) { m_wndToolBar.GetToolBarCtrl().GetButton(i,&tb); // si l'indice commande du bouton est valide ok on a bien un bouton. if(tb.idCommand) nCount++; } return nCount; } //---------------------------------------------------------------- BOOL CChildFrame::SetButtonPressed(int nIDBt,bool bPressed/*=true*/) { int nState=TBSTATE_ENABLED ; if(bPressed) nState|=TBSTATE_PRESSED; return m_wndToolBar.GetToolBarCtrl().SetState(nIDBt,nState); } //---------------------------------------------------------------- BOOL CChildFrame::IsButtonPressed(int nIDBt,bool bMajBt/*=true*/) { if(bMajBt) UpdateButton(nIDBt); return m_wndToolBar.GetToolBarCtrl().IsButtonPressed(nIDBt); } |
Utilisation dans la vue :
Code C++ : | Sélectionner tout |
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 33 34 35 36 37 38 39 40 41 42 43 | void CTestToolBarView::OnInitialUpdate() { CFormView::OnInitialUpdate(); ResizeParentToFit(); // acces à la frame (parent de la classe fenetre). CChildFrame *pChild=static_cast<CChildFrame *>(GetParentFrame()); // ajout du bitmap en fin de toolbar . pChild->SetButton(ID_BUTTONOPENCLOSE,IDB_BITMAPCLOSE,""); pChild->SetButton(ID_BUTTONOPENCLOSE2,IDB_BITMAPCLOSE2,""); } //---------------------------------------------------------------- void CTestToolBarView::OnButtonopenclose() { // TODO: Add your command handler code here int rnImage; CChildFrame *pChild=static_cast<CChildFrame *>(GetParentFrame()); if(pChild->IsButtonPressed(ID_BUTTONOPENCLOSE)) { TRACE("\nID_BUTTONOPENCLOSE:Pressé"); } else { TRACE("\nID_BUTTONOPENCLOSE:relaché"); } } void CTestToolBarView::OnButtonopenclose2() { // TODO: Add your command handler code here int rnImage; CChildFrame *pChild=static_cast<CChildFrame *>(GetParentFrame()); if(pChild->IsButtonPressed(ID_BUTTONOPENCLOSE2)) { TRACE("\nID_BUTTONOPENCLOSE2:Pressé"); } else { TRACE("\nID_BUTTONOPENCLOSE2:relaché"); } } |
L'utilisateur définit pour le bouton spécifié le nouveau bitmap.
Exemple: TestsToolbar.zip
On procédera comme suit :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | if(pToolBar->IsFloating()) { CRect rect; pToolBar->GetWindowRect(rect); pToolBar->SetWindowPos(NULL,0,0,rect.Width(),rect.Height(), SWP_NOMOVE|SWP_NOZORDER|SWP_DRAWFRAME|SWP_FRAMECHANGED); CPoint newPos(0,0); pToolBar->ClientToScreen(&newPos); CRect rcNew; pToolBar->CalcDynamicLayout(rect.Width(),LM_HORZ | LM_COMMIT); ParentWindow->FloatControlBar(pToolBar, newPos, CBRS_ALIGN_TOP | CBRS_SIZE_DYNAMIC); } |
Par défaut lorsqu'on déclare deux barres d'outils dans la MainFrame le positionnement se fait sur deux lignes.
Pour positionner les deux barres d'outils sur la même ligne on procédera comme suit :
Code c++ : | Sélectionner tout |
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } m_wndToolBar.SetWindowText(_T("Toolbar")); m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); // deuxieme toolbar . if (!m_wndToolBar2.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar2.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } m_wndToolBar2.SetWindowText(_T("Toolbar2")); m_wndToolBar2.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); m_wndToolBar2.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); //placement 1 toolbar CRect RectOne,RectTwo; RecalcLayout(); m_wndToolBar.GetWindowRect(&RectOne); m_wndToolBar2.GetWindowRect(&RectTwo); int nWidth=RectTwo.Width(); int nHeight=RectTwo.Height(); // calcul emplacement de la toolbar2 a droite de la 1 toolbar RectTwo.left=RectOne.right; RectTwo.right=RectTwo.left+nWidth; RectTwo.top=RectOne.top; RectTwo.bottom=RectTwo.top+nHeight; // placement final. DockControlBar(&m_wndToolBar2,(UINT)0,RectTwo); RecalcLayout(); return 0; } |
Dans mon exemple c'est la même barre d'outils qui est associée à deux variables différentes.
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.