FAQ VC++ et MFCConsultez toutes les FAQ

Nombre d'auteurs : 20, nombre de questions : 546, 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


SommaireClasses Fenêtres et FrameWorkCStatusBar (6)
précédent sommaire suivant
 

Les traitements liés à la CStatusBar sont situés dans la classe de fenêtre principale CMainFrame.
Dans un projet classique on doit trouver un tableau initialisé avec les valeurs standard des indicateurs claviers :

ID_INDICATOR_CAPS : Majuscule/Minuscule
ID_INDICATOR_NUM, : Verrou Numérique
ID_INDICATOR_SCRL, :

Pour personnaliser ce tableau procédez comme suit :
Dans tous les cas la première ligne du tableau indicators doit comporter ID_SEPARATOR

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
  
static UINT indicators[] = 
{ 
ID_SEPARATOR,           // status line indicator 
ID_INDICATOR_1,            
ID_INDICATOR_2, 
ID_INDICATOR_3 
};
ID_INDICATOR_x sont des valeurs à rajouter dans les ressources, sous Visual 6 voir menu View option Resources Symbols.
Ajouter dans la String Table l'ID_INDICATOR_x que l'on vient de créer (on va le chercher dans la liste)
Ensuite dans l'entête mainframe.h rajouter la ligne

Code c++ : Sélectionner tout
1
2
  
void OnUpdatePane (CCmdUI *pCmdUI)  {     pCmdUI->Enable ();
dans le source mainframe.cpp rajouter:

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
  
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 
//{{AFX_MSG_MAP(CMainFrame) 
// NOTE - the ClassWizard will add and remove mapping macros here. 
//    DO NOT EDIT what you see in these blocks of generated code ! 
ON_WM_CREATE() 
//}}AFX_MSG_MAP 
ON_UPDATE_COMMAND_UI ( ID_INDICATOR_1, OnUpdatePane ) 
ON_UPDATE_COMMAND_UI ( ID_INDICATOR_2, OnUpdatePane ) 
ON_UPDATE_COMMAND_UI ( ID_INDICATOR_3, OnUpdatePane ) 
  
END_MESSAGE_MAP() 
// dans oncreate  
//................ 
// ********** Status Bar ************************************** 
m_wndStatusBar.SetPaneInfo(1, ID_INDICATOR_1, SBPS_NORMAL ,50); 
m_wndStatusBar.SetPaneInfo(2, ID_INDICATOR_2, SBPS_NORMAL,50); 
m_wndStatusBar.SetPaneInfo(3, ID_INDICATOR_3, SBPS_NORMAL,50); 
  
// affectation d'une valeur a un panneau  
m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_1), "Valeur 1");

Mis à jour le 19 septembre 2005 farscape

Si vous avez décoché l'option "initial status bar" à l'étape 4 de la création de votre projet, alors vous n'aurez pas de barre d'état. Que faire si votre projet, déjà bien avancé, nécessite finalement la barre d'état ? La solution tient en quelques lignes.

1. Déclarer une donnée membre CStatusBar dans la classe CMainFrame

Code c++ : Sélectionner tout
1
2
private: 
CStatusBar  m_wndStatusBar;
2. Définir le tableau statique indicators qui donne les panneaux de la barre d'état

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
  
static UINT indicators[] = 
{ 
ID_SEPARATOR, 
ID_INDICATOR_CAPS, 
ID_INDICATOR_NUM, 
ID_INDICATOR_SCRL, 
};
3. Créer la barre d'état dans la fonction OnCreate de CMainFrame

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
if (!m_wndStatusBar.Create(this) || 
      !m_wndStatusBar.SetIndicators(indicators, 
      sizeof(indicators) / sizeof(UINT))) 
{ 
   TRACE0("Impossible de créer la barre d'état\n"); 
   return -1; 
}
Notez que l'identifiant donné à la barre d'état est AFX_IDW_STATUS_BAR (cf. doc BOOL CStatusBar::Create(...)). L'architecture d'application recherche cette identifiant lorsqu'elle doit afficher un libellé associé à une commande de menu.

Mis à jour le 27 novembre 2005 bigboomshakala

La barre d'état par défaut est constituée d'un panneau de message (ID_SEPARATOR) et de trois panneaux d'indicateurs:
ID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL.
Un panneau d'indicateur est lié à une unique chaîne de caractère, fournie par une ressource (String Table), affichée ou cachée suivant le gestionnaire d'actualisation de l'interface associée.
La dimension du panneau est égale à la largeur de la chaîne de caractères.
Si l'on veut par exemple afficher "Ctrl/Ret" si Control et Return sont pressés (en même temps ou séparément) :

1. On définit ID_IND_CTRL_RET dans la String Table, associé à la chaîne "Ctrl/Ret"

2.

Code c++ : Sélectionner tout
1
2
3
// MainFrm.h 
public: 
void OnUpdateKeyReturn(CCmdUI* pCmdUI);
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
// MainFrm.cpp 
  
static UINT indicators[] = 
{ 
   ID_SEPARATOR, 
   ID_INDICATOR_CAPS, 
   ID_INDICATOR_NUM, 
   ID_IND_CTRL_RET, 
}; 
  
... 
  
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 
   //{{AFX_MSG_MAP(CMainFrame) 
   ON_WM_CREATE() 
   ... 
   //}}AFX_MSG_MAP 
   ON_UPDATE_COMMAND_UI(ID_INDICATOR_ENT,OnUpdateKeyReturn) 
END_MESSAGE_MAP() 
  
... 
  
void CMainFrame::OnUpdateKeyReturn(CCmdUI* pCmdUI) 
{ 
pCmdUI->Enable(::GetKeyState(VK_RETURN) & ::GetKeyState(VK_CONTROL) & 1); 
}

Mis à jour le 27 novembre 2005 bigboomshakala

Comme on a changé l'ID de la barre d'état pour gérer soi-même l'affichage, la commande Affichage/Barre d'état, gérée par l'architecture d'application, n'agit plus. On va donc devoir gérer soi-même la commande.

On déclare une variable booléenne dans la classe CMainFrame. Cet booléen indique si la barre d'état est visible ou non, et si un check doit apparaître devant la commande Affichage/Barre d'état :

Code c++ : Sélectionner tout
1
2
3
//MainFrm.h 
private: 
bool m_bStatusBarIsVisible;
On initialise le booléen dans OnCreate, aprèsavoir créé la barre d'état :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
if (!m_wndStatusBar.Create(this,WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR) 
|| !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators) / sizeof(UINT))) 
{ 
TRACE0("Impossible de créer la barre d'état\n"); 
return -1; 
}  
  
m_bStatusBarIsVisible = (m_wndStatusBar.IsWindowVisible() == 0);
On intercepte ensuite le message ON_COMMAND de ID_VIEW_STATUS_BAR :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
void CMainFrame::OnViewStatusBar()  
{ 
if(m_bStatusBarIsVisible) 
m_wndStatusBar.ShowWindow(SW_HIDE); 
else 
m_wndStatusBar.ShowWindow(SW_SHOW); 
  
RecalcLayout(); 
m_bStatusBarIsVisible = !m_bStatusBarIsVisible; 
}
puis on implémente le gestionnaire de mise à jour du menu (message ON_COMMAND_UPDATE_UI) :

Code c++ : Sélectionner tout
1
2
3
4
5
void CMainFrame::OnUpdateViewStatusBar(CCmdUI* pCmdUI)  
{ 
pCmdUI->SetCheck(m_bStatusBarIsVisible); 
  
}
A présent la commande Affichage/Barre d'état joue son rôle habituel.

Mis à jour le 27 novembre 2005 bigboomshakala

On procédera comme suit :
Avec l'assistant générez une classe dérivée de la classe CStatusbar.
Générez ensuite les fonctions de réponse pour les messages WM_CREATE et WM_SIZE.
Rajoutez une variable contrôle CProgressCtrl comme donnée membre de la classe.
Enfin il faudra utiliser cette classe dans votre Mainframe en modifiant la déclaration de la variable initiale (CStatusBar).

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
#pragma once 
// CStatusBarEx 
class CStatusBarEx : public CStatusBar 
{ 
    DECLARE_DYNAMIC(CStatusBarEx) 
  
public: 
    CStatusBarEx(); 
    virtual ~CStatusBarEx(); 
  
protected: 
    CProgressCtrl             m_Progress; 
  
    DECLARE_MESSAGE_MAP() 
public: 
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 
    afx_msg void OnSize(UINT nType, int cx, int cy); 
};
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
  
// StatusBarEx.cpp : fichier d'implémentation 
// 
  
#include "stdafx.h" 
#include "StatusBarEx.h" 
  
// CStatusBarEx 
  
IMPLEMENT_DYNAMIC(CStatusBarEx, CStatusBar) 
CStatusBarEx::CStatusBarEx() 
{ 
} 
  
CStatusBarEx::~CStatusBarEx() 
{ 
} 
  
  
BEGIN_MESSAGE_MAP(CStatusBarEx, CStatusBar) 
    ON_WM_CREATE() 
    ON_WM_SIZE() 
END_MESSAGE_MAP() 
  
// Gestionnaires de messages CStatusBarEx 
int CStatusBarEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{ 
    if (CStatusBar::OnCreate(lpCreateStruct) == -1) 
        return -1; 
  
    // Initialise controls 
    CRect rect( 0, 0, 100, 16); 
    m_Progress.Create( WS_VISIBLE | WS_CHILD, rect, this, IDC_PROGRESS ); 
    m_Progress.SetRange( static_cast<short>(0), static_cast<short>(100) ); 
  
    return 0; 
} 
  
void CStatusBarEx::OnSize(UINT nType, int cx, int cy) 
{ 
    CStatusBar::OnSize(nType, cx, cy); 
  
    // Initially create progress control in horizontal position 
    CWnd* pWnd = (CWnd*)this; 
    CRect rect; 
    pWnd->GetWindowRect( &rect ); 
    ScreenToClient( &rect ); 
  
    if( m_Progress.GetSafeHwnd()) 
    { 
        m_Progress.SetWindowPos( &CWnd::wndTop, 0, 0, 100, 16, SWP_NOMOVE | SWP_NOZORDER); 
        m_Progress.SetPos( 16); 
    } 
  
}

Mis à jour le 17 septembre 2007 farscape zebiloute

On pourra se reporter à ce post de la faq pour informations :

On commence par créer un nouveau panneau dans le tableau indicators de la CMainFrame.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
  
static UINT indicators[] = 
{ 
	ID_SEPARATOR,           // status line indicator 
	ID_INDICATOR_BMP,		// panneau bitmap 
	ID_INDICATOR_CAPS, 
	ID_INDICATOR_NUM, 
	ID_INDICATOR_SCRL, 
};
Le nouvel identifiant doit être préalablement rajouté dans les ressources :
Sur le fichier .rc dans les ressources : clic droit ressources symbols.
On rajoutera aussi cet identifiant dans la string table.

L'étape suivante est de faire apparaitre le bitmap dans la barre d'états.
Pour cela il va falloir créer une classe héritée de CStatusbar pour placer notre traitement dans la méthode DrawItem , notre barre d'états devra donc posséder le style OwnerDraw pour le panneau concerné, ici le numéro 1.
La classe:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
#pragma once 
// CStatusBarEx 
class CStatusBarEx : public CStatusBar 
{ 
	DECLARE_DYNAMIC(CStatusBarEx) 
  
public: 
	CStatusBarEx(); 
	virtual ~CStatusBarEx(); 
	void SetBitmap(UINT nId){m_BitmapId=nId;} 
  
protected: 
	UINT m_BitmapId; 
	DECLARE_MESSAGE_MAP() 
public: 
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); 
};
Le 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
  
#include "StatusBarEx.h" 
// CStatusBarEx 
IMPLEMENT_DYNAMIC(CStatusBarEx, CStatusBar) 
  
CStatusBarEx::CStatusBarEx():m_BitmapId(0) 
{ 
} 
CStatusBarEx::~CStatusBarEx() 
{ 
} 
BEGIN_MESSAGE_MAP(CStatusBarEx, CStatusBar) 
END_MESSAGE_MAP() 
// CStatusBarEx message handlers 
void CStatusBarEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{ 
	// TODO:  Add your code to draw the specified item 
	if(!m_BitmapId) return; 
	CRect rect(lpDrawItemStruct->rcItem); 
	CDC Memdc,barDC; 
  
	barDC.Attach(lpDrawItemStruct->hDC); 
	Memdc.CreateCompatibleDC(NULL); 
  
	CBitmap Bmp; 
	Bmp.LoadBitmap(m_BitmapId); 
    BITMAP bmpInfo; 
    Bmp.GetBitmap(&bmpInfo); 
  
	CBitmap *poldBmp=Memdc.SelectObject(&Bmp); 
	barDC.StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&Memdc,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); 
	Memdc.SelectObject(poldBmp); 
}
Enfin il faut indiquer que le panneau 1 de notre barre d'état est OwnerDraw, on placera ce code dans la méthode OnCreate de la Mainframe :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
	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_wndStatusBar.SetBitmap(IDB_BITMAP1); // affectation de l'identifiant du Bitmap dans les ressources 
	m_wndStatusBar.SetPaneStyle(1,SBT_OWNERDRAW); // le panneau OwnerDraw.

Mis à jour le 7 juillet 2008 farscape

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 ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les 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 © 2017 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.

 
Contacter le responsable de la rubrique C++