Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

Vous n'avez pas encore de compte Developpez.com ? L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Developpez.com

C++

Choisissez la catégorie, puis la rubrique :

logo
Sommaire > Classes Fenêtres et FrameWork > Gestion du framework > CSplitterWnd
        Comment faire pour séparer une fenêtre en deux ?
        Comment mettre en place un splitter dans un projet SDI ?
        Comment figer un splitter ?
        Comment communiquer entre des vues d'un splitter ?
        Comment supprimer une vue dans un CSplitterWnd ?
        Comment implémenter plusieurs splitters dans un projet SDI ?



Comment faire pour séparer une fenêtre en deux ?
auteur : Farscape
En utilisant la classe CSplitterWnd :

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.)


Comment mettre en place un splitter dans un projet SDI ?
Créé le 04/04/2005[haut]
auteur : 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 :

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 :

virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
Initialisation du Splitter :

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 :

// 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 : http://farscape.developpez.com/Samples/SdiSplitter.zip


Comment figer un splitter ?
Créé le 19/09/2005[haut]
auteur : 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

#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:

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;
}

Comment communiquer entre des vues d'un splitter ?
Créé le 27/11/2005[haut]
auteur : 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 :

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 :

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

CMainFrame *pFrame=static_cast<CMainFrame*>( AfxGetMainWnd());

CMyFormView  *pView=static_cast<CMyFormView  *>(pFrame-> m_wndSplitter.GetPane(0,1));
ASSERT(pView->IsKindOf(RUNTIME_CLASS(CMyFormView)));

Comment supprimer une vue dans un CSplitterWnd ?
Créé le 17/09/2007[haut]
auteur : 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.


Comment implémenter plusieurs splitters dans un projet SDI ?
Créé le 07/07/2008[haut]
auteur : Farscape
Pour la création simple d'un splitter on se reportera à ce post de la faq : faq Comment mettre en place un splitter dans un projet SDI ?
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 :

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 :

/////////////////////////////////////////////////////////////////////////////
// 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:

/////////////////////////////////////////////////////////////////////////////
// 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:http://farscape.developpez.com/Samples/SdiSplitters.zip

lien : faq Comment mettre en place un splitter dans un projet SDI ?


Consultez les autres F.A.Q.


Valid XHTML 1.0 TransitionalValid CSS!

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 © 2004 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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++

Partenaire : Hébergement Web