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 FrameWorkGestion du frameworkCSplitterWnd (6)
précédent sommaire suivant
 

En utilisant la classe CSplitterWnd :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
  
BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, 
                                 CCreateContext* pContext) 
{ 
   BOOL bCreateSpltr = m_wndSplitter.CreateStatic( this, 2, 1); 
   // COneView et CAnotherView sont des classes utilisateurs derivées de CView 
   m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(COneView), CSize(0,0),pContext); 
   m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CAnotherView),CSize(0,0),pContext); 
  
   return (bCreateSpltr); 
}
Sur le OnCreate de la MDIChild associée ou sur la MainFrame dans un projet SDI on déclare une donnée membre m_wndSplitter de la classe CSplitterWnd , et sur le OnCreateClient on initialise les différentes views comme dans l'exemple ci dessus.
(Voir doc MSDN pour la gestion des lignes et colonnes.)

Mis à jour le 5 avril 2013 farscape

La mise en place d'un splitter (ou rideau) est facile à mettre en place.
L'exemple qui suit montre comment intégrer deux fenêtres séparées par un splitter .
Etapes :
Il faut disposer d'une seconde fenêtre à générer avec l'aide ClassWizard au choix :CFormView ,CScrollView ,CEditView etc…

Le traitement d'initialisation se passe dans la classe CMainFrame :
Déclarer une donnée membre m_wndSplitter de la classe CSplitterWnd dans la classe CMainFrame :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
class CMainFrame : public CFrameWnd 
{ 
protected: // create from serialization only 
CMainFrame(); 
DECLARE_DYNCREATE(CMainFrame) 
  
// Attributes 
public: 
CSplitterWnd m_wndSplitter;
Avec l'aide de ClassWizard générer la fonction virtuelle :

Code c++ : Sélectionner tout
1
2
  
virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
Initialisation du Splitter :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)  
{ 
// TODO: Add your specialized code here and/or call the base class 
if (!m_wndSplitter.CreateStatic(this, 1, 2))return FALSE; 
  
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSdiSplitterView), CSize(100, 100), pContext) || 
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMyFormView), CSize(100, 100), pContext)) 
{ 
m_wndSplitter.DestroyWindow(); 
return FALSE; 
} 
return TRUE; 
}
La première ligne CreateStatic initialise le splitter avec une ligne et deux colonnes ce qui correspond ici à deux fenêtres séparées verticalement par le splitter.
Les lignes suivantes correspondent aux classes fenêtres associées au splitter.
Dans la fonction CreateView on spécifie la ligne et colonne de la fenêtre sa surface d'affichage initiale et bien sur le runtime de la classe fenêtre.
C'est tout.

Note : Une des deux classes doit être celle qui est déclarée dans la fonction InitInstance de la classe d'application :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
// Extrait InitInstance de CSdiSplitterApp dérivée de CWinApp. 
  
CSingleDocTemplate* pDocTemplate; 
pDocTemplate = new CSingleDocTemplate( 
IDR_MAINFRAME, 
RUNTIME_CLASS(CSdiSplitterDoc), 
RUNTIME_CLASS(CMainFrame),       // main SDI frame window 
RUNTIME_CLASS(CSdiSplitterView)); 
AddDocTemplate(pDocTemplate);
Le lien ci-dessus illustre le sujet avec deux fenêtres : une CListView à gauche et une CFormView à droite :

Mis à jour le 4 avril 2005 farscape

Pour bloquer le splitter il faut faire une classe dérivée de CSplitterWnd et surchargée la fonction StartTracking et faire un return .

La classe ci-dessus permet :
De définir un splitter fin (thinframe),fonction: SetThinFrame
D'empêcher le fonctionnement normal du splitter et bloquer le curseur spécifique, fonction :SetTracking

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
  
#define PANE_BORDER 1 
#define PANE_SHARE  0 
#define PANE_GAP 1 
  
class CSplitterWndEx : public CSplitterWnd 
{ 
// Construction 
public: 
   CSplitterWndEx() 
   { 
       m_bExTracking=true; 
   } 
   void SetThinFrame() 
   { 
        m_cxSplitter=PANE_BORDER;      
        m_cySplitter=PANE_BORDER;      
        m_cxBorderShare=PANE_SHARE;    
        m_cyBorderShare=PANE_SHARE;    
        m_cxSplitterGap=PANE_GAP;      
        m_cySplitterGap=PANE_GAP;    
   } 
// Operations 
public: 
    void SetTracking(bool bEnable=true){m_bExTracking=bEnable;} 
  
    virtual void StartTracking(int ht) 
    { 
        if(!m_bExTracking) return ; 
        CSplitterWnd::StartTracking(ht); 
    }  
   // Overrides 
// ClassWizard generated virtual function overrides 
//{{AFX_VIRTUAL(CSplitterWndEx) 
public: 
//}}AFX_VIRTUAL 
  
// Attributes 
public: 
  
bool m_bExTracking; 
  
// Generated message map functions 
protected: 
//{{AFX_MSG(CSplitterWndEx) 
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); 
afx_msg void OnMouseMove(UINT nFlags, CPoint point); 
//}}AFX_MSG 
DECLARE_MESSAGE_MAP() 
}; 
// .cpp 
BEGIN_MESSAGE_MAP(CSplitterWndEx, CSplitterWnd) 
//{{AFX_MSG_MAP(CSplitterWndEx) 
ON_WM_SETCURSOR() 
ON_WM_MOUSEMOVE() 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
//------------------------------------------------- 
BOOL CSplitterWndEx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)  
{ 
// TODO: Add your message handler code here and/or call default 
    if(!m_bExTracking) return FALSE; 
    return CSplitterWnd::OnSetCursor(pWnd, nHitTest, message); 
} 
//--------------------------------------- 
void CSplitterWndEx::OnMouseMove(UINT nFlags, CPoint point)  
{ 
// TODO: Add your message handler code here and/or call default 
   if(!m_bExTracking) return ; 
   CSplitterWnd::OnMouseMove(nFlags, point); 
}
utilisation dans CMainFrame:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)  
{ 
    // TODO: Add your specialized code here and/or call the base class 
    m_wndSplitter.SetThinFrame(); // bordure fine 
    m_wndSplitter.SetTracking(false);// pas de tracking. 
    if (!m_wndSplitter.CreateStatic(this, 1, 2)) 
        return FALSE; 
  
    if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSdiSplitterView), CSize(100, 100), pContext) || 
        !m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMyFormView), CSize(100, 100), pContext)) 
    { 
        m_wndSplitter.DestroyWindow(); 
        return FALSE; 
    } 
    return TRUE; 
}

Mis à jour le 19 septembre 2005 farscape

Pour accéder aux données d'une vue séparée par un splitter,
Il faut accéder à l'emplacement ou est stocké le splitter à savoir la mainframe dans le cas d'un projet SDI et de la CMDIChildWnd en MDI:
On utilisera respectivement :
AfxGetMainWnd() en SDI
GetParentFrame() en MDI .
Le pointeur obtenu devra être convertit avec la classe utilisateur correspondante (CMainFrame ou CChildFrame)
Une fois l'accès au splitter on peut utiliser la méthode:
GetPane(int row,col) qui renvoie un pointeur sur une CWnd * ,a convertir sur la classe correspondante.

Exemple SDI :
Dans ma CMainFrame j'ai :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
class CMainFrame : public CFrameWnd 
{ 
protected: // create from serialization only 
CMainFrame(); 
DECLARE_DYNCREATE(CMainFrame) 
  
// Attributes 
public: 
CSplitterWnd m_wndSplitter;
mon splitter est créé de la manière suivante :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)  
{ 
// TODO: Add your specialized code here and/or call the base class 
if (!m_wndSplitter.CreateStatic(this, 1, 2))return FALSE; 
  
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSdiSplitterView), CSize(100, 100), pContext) || 
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMyFormView), CSize(100, 100), pContext)) 
{ 
m_wndSplitter.DestroyWindow(); 
return FALSE; 
} 
return TRUE; 
}
Code pour accéder à la vue CMyFormView à partir de CSdiSplitterView

Code c++ : Sélectionner tout
1
2
3
4
5
  
CMainFrame *pFrame=static_cast<CMainFrame*>( AfxGetMainWnd()); 
  
CMyFormView  *pView=static_cast<CMyFormView  *>(pFrame-> m_wndSplitter.GetPane(0,1)); 
ASSERT(pView->IsKindOf(RUNTIME_CLASS(CMyFormView)));

Mis à jour le 27 novembre 2005 farscape

Il suffit d'utiliser la méthode DeleteView de la classe CSplitterWnd, si c'est la vue active qui est détruite, la vue suivante devient active.

Mis à jour le 17 septembre 2007 farscape

Pour la création simple d'un splitter on se reportera à ce post de la faq :
Pour créer un autre splitter dans une vue on utilisera la classe CMiniFrameWnd
Pour la mise en place du splitter principal on procède comme suit :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)  
{ 
	// TODO: Add your specialized code here and/or call the base class 
	if (!m_wndSplitter_v.CreateStatic(this, 1, 2)) 
	{ 
		return FALSE; 
	} 
	if (!m_wndSplitter_v.CreateView(0, 0, RUNTIME_CLASS(CMyMiniFrame), CSize(100, 100), pContext) || 
		!m_wndSplitter_v.CreateView(0,1, RUNTIME_CLASS(CSdiSplitterView), CSize(100, 100), pContext)) 
	{ 
		return FALSE; 
	}	 
	return TRUE; 
}
Pas de grand changement par rapport au post cité de la faq , si ce n'est qu'une des vues est une classe héritée de CMiniFrameWnd.
Il faudra donc créer avec l'assistant une classe héritée de CMiniFrameWnd :

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
  
///////////////////////////////////////////////////////////////////////////// 
// CMyMiniFrame frame 
  
class CMyMiniFrame : public CMiniFrameWnd 
{ 
	DECLARE_DYNCREATE(CMyMiniFrame) 
protected: 
	CMyMiniFrame();           // protected constructor used by dynamic creation 
  
// Attributes 
public: 
	CSplitterWnd m_wndSplitter; 
// Operations 
public: 
  
// Overrides 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CMyMiniFrame) 
	protected: 
	virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); 
	//}}AFX_VIRTUAL 
  
// Implementation 
protected: 
	virtual ~CMyMiniFrame(); 
  
	// Generated message map functions 
	//{{AFX_MSG(CMyMiniFrame) 
		// NOTE - the ClassWizard will add and remove member functions here. 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
  
/////////////////////////////////////////////////////////////////////////////
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
  
///////////////////////////////////////////////////////////////////////////// 
// CMyMiniFrame 
  
IMPLEMENT_DYNCREATE(CMyMiniFrame, CMiniFrameWnd) 
  
CMyMiniFrame::CMyMiniFrame(){} 
CMyMiniFrame::~CMyMiniFrame(){} 
  
BEGIN_MESSAGE_MAP(CMyMiniFrame, CMiniFrameWnd) 
	//{{AFX_MSG_MAP(CMyMiniFrame) 
		// NOTE - the ClassWizard will add and remove mapping macros here. 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
  
BOOL CMyMiniFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)  
{ 
	// TODO: Add your specialized code here and/or call the base class 
	if (!m_wndSplitter.CreateStatic(this, 2, 1)) 
		return FALSE; 
  
	if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSdiSplitterView), CSize(100, 100), NULL) || 
		!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CMyFormView), CSize(100, 100), NULL)) 
	{ 
		m_wndSplitter.DestroyWindow(); 
		return FALSE; 
	} 
  
	m_wndSplitter.RecalcLayout();	 
	return TRUE; 
}
Et sur le OnCreatClient on met en place nos vues splittées.
l'exemple en action:

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++