| auteur : Farscape | En utilisant la classe CSplitterWnd :
BOOL CChildFrame:: OnCreateClient (LPCREATESTRUCT lpcs,
CCreateContext* pContext)
{
BOOL bCreateSpltr = m_wndSplitter.CreateStatic ( this , 2 , 1 );
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.)
|
| 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 :
CMainFrame ();
DECLARE_DYNCREATE (CMainFrame)
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)
{
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 :
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate (
IDR_MAINFRAME,
RUNTIME_CLASS (CSdiSplitterDoc),
RUNTIME_CLASS (CMainFrame),
RUNTIME_CLASS (CSdiSplitterView));
AddDocTemplate (pDocTemplate);
|
|
| 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
{
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;
}
public :
void SetTracking (bool bEnable= true ){ m_bExTracking= bEnable;}
virtual void StartTracking (int ht)
{
if (! m_bExTracking) return ;
CSplitterWnd:: StartTracking (ht);
}
public :
public :
bool m_bExTracking;
protected :
afx_msg BOOL OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnMouseMove (UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP ()
} ;
BEGIN_MESSAGE_MAP (CSplitterWndEx, CSplitterWnd)
ON_WM_SETCURSOR ()
ON_WM_MOUSEMOVE ()
END_MESSAGE_MAP ()
BOOL CSplitterWndEx:: OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)
{
if (! m_bExTracking) return FALSE;
return CSplitterWnd:: OnSetCursor (pWnd, nHitTest, message);
}
void CSplitterWndEx:: OnMouseMove (UINT nFlags, CPoint point)
{
if (! m_bExTracking) return ;
CSplitterWnd:: OnMouseMove (nFlags, point);
}
|
utilisation dans CMainFrame:
BOOL CMainFrame:: OnCreateClient (LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
m_wndSplitter.SetThinFrame ();
m_wndSplitter.SetTracking (false );
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;
}
|
|
| 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 :
CMainFrame ();
DECLARE_DYNCREATE (CMainFrame)
public :
CSplitterWnd m_wndSplitter;
|
mon splitter est créé de la manière suivante :
BOOL CMainFrame:: OnCreateClient (LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
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)));
|
|
| 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.
|
| auteur : Farscape |
BOOL CMainFrame:: OnCreateClient (LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
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 :
class CMyMiniFrame : public CMiniFrameWnd
{
DECLARE_DYNCREATE (CMyMiniFrame)
protected :
CMyMiniFrame ();
public :
CSplitterWnd m_wndSplitter;
public :
protected :
virtual BOOL OnCreateClient (LPCREATESTRUCT lpcs, CCreateContext* pContext);
protected :
virtual ~ CMyMiniFrame ();
DECLARE_MESSAGE_MAP ()
} ;
|
Code:
IMPLEMENT_DYNCREATE (CMyMiniFrame, CMiniFrameWnd)
CMyMiniFrame:: CMyMiniFrame (){ }
CMyMiniFrame:: ~ CMyMiniFrame (){ }
BEGIN_MESSAGE_MAP (CMyMiniFrame, CMiniFrameWnd)
END_MESSAGE_MAP ()
BOOL CMyMiniFrame:: OnCreateClient (LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
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;
}
|
|
lien : Comment mettre en place un splitter dans un projet SDI ?
|
Consultez les autres F.A.Q.
|
|