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
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); } |
(Voir doc MSDN pour la gestion des lignes et colonnes.)
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 | 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 |
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 | 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 | // 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 : SdiSplitter.zip
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); } |
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; } |
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; |
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 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))); |
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.
Pour la création simple d'un splitter on se reportera à ce post de la 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 :
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_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 | ///////////////////////////////////////////////////////////////////////////// // 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 | ///////////////////////////////////////////////////////////////////////////// // 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 : SdiSplitters.zip
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.