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
- Comment avoir plusieurs fenêtres de type View dans un projet MDI ?
- Comment avoir plusieurs fenêtres différentes sur un objet document ?
- Comment maximiser une fenêtre fille (Child)?
- Comment restaurer une fenêtre fille(Child) ?
- Comment récupérer la MDIChild active ?
- Comment savoir si une fenêtre fille est iconisée ?
- Comment activer une fenêtre fille (child)?
- Comment activer et faire passer en premier plan une fenêtre fille (Child)?
- Comment faire pour qu'un projet MDI soit toujours en avant plan ?
- Comment changer la taille d'une View dans un contexte MDI?
- Comment mémoriser la position des fenêtres dans une application MFC ?
- Comment s'affranchir du mécanisme par défaut pour les titres des fenêtres dans un contexte document/view ?
- Comment griser le bouton et le menu fermeture d'une fenêtre MDI ?
- Comment créer une fenêtre MDI que l'on ne peut bouger ?
- Comment accéder à la vue active dans un projet SDI ?
La gestion de plusieurs fenêtres dans un projet MDI passe par la déclaration dans la fonction InitInstance (classe d'application CWinApp ) d'objets de la classe CMultiDocTemplate.
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 | BOOL CTestMdiApp::InitInstance() { AfxEnableControlContainer(); #ifdef _AFXDLL Enable3dControls();// Call this when using MFC in a shared DLL #else Enable3dControlsStatic();// Call this when linking to MFC statically #endif // Change the registry key under which our settings are stored. // TODO: You should modify this string to be something appropriate // such as the name of your company or organization. SetRegistryKey(_T("Local AppWizard-Generated Applications")); LoadStdProfileSettings(); // Load standard INI file options (including MRU) // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views. // CMultiDocTemplate *m_pTplMdiView; m_pTplMdiView = new CMultiDocTemplate ( IDR_TESTMDTYPE, RUNTIME_CLASS(CTestMdiDoc), // custom MDI child frame RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CTestMdiView)); AddDocTemplate(m_pTplMdiView); // deuxième document // stockage du CMultiDocTemplate dans la classe application pour appel ultérieur. // CMultiDocTemplate * m_pTplEditView; dans le header. m_pTplEditView= new CMultiDocTemplate ( IDR_TESTMDTYPE, RUNTIME_CLASS(CTestMdiDoc), // custom MDI child frame RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CEditView)); AddDocTemplate(m_pTplEditView); // create main MDI Frame window CMainFrame* pMainFrame= new CMainFrame; if(!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; // Parse command line for standard shell commands, DDE, file open CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // Dispatch commands specified on the command line if(!ProcessShellCommand(cmdInfo)) return FALSE; // The main window has been initialized, so show and update it. pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE; } |
La création de la deuxième fenêtre pourra se faire comme suit :
Code c++ : | Sélectionner tout |
1 2 | ((CTestMdiApp *)AfxGetApp())->m_pTplEditView->OpenDocumentFile(NULL) ; |
D'abord pour fixer les idées, dans quel cas a-t-on besoin d'avoir des fenêtres différentes pour un même document ?
Chaque fois que l'on voudra avoir un lien entre plusieurs fenêtres pour des échanges de données ou des représentations de données d'une manière différente, le document donnant, par ses méthodes, un point d'accès pratique et facile aux différentes fenêtres.
Exemple :
Dans une « CFormView » je saisis des données pour l'affichage d'un graphe,dans une CView je les dessine sous forme de tableau récapitulatif , et dans une autre « CView » je les représente sous forme de diagrammes ,histogrammes etc..
L'association de plusieurs fenêtres sur un seul document s'effectue sur la déclaration du document template dans la fonction InitInstance de la classe d'application.
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 | /* à declarer dans la classe app en tant que données membres CMultiDocTemplate* m_pTwoDocTemplate; CMultiDocTemplate* m_pFirstTemplate; */ // La définition principale m_pFirstTemplate= new CMultiDocTemplate(IDR_TESTMDTYPE, RUNTIME_CLASS(CTestMdiDoc), // custom MDI child frame RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CTestMdiView)); AddDocTemplate(m_pFirstTemplate); // la fenêtre supplémentaire. m_pTwoDocTemplate=new CMultiDocTemplate(IDR_TESTMDTYPE, RUNTIME_CLASS(CTestMdiDoc), // custom MDI child frame RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CMyEditView)); // pas de AddocTemplate. |
le deuxième juste une déclaration du template sans faire l'appel à AddDocTemplate .
Pour rajouter un objet de la class CMyEditView par exemple dans la fonction OnInitialUpdate de la classe CTestMdiView on procédera comme suit:
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | void CTestMdiView::OnInitialUpdate() { CView::OnInitialUpdate(); // TODO: Add your specialized code here and/or call the base class CTestMdiApp *TheApp=(CTestMdiApp*)AfxGetApp(); CFrameWnd * pFrame =TheApp->m_pTwoDocTemplate->CreateNewFrame(GetDocument(),GetParentFrame()); TheApp->m_pFirstTemplate->InitialUpdateFrame(pFrame,GetDocument()); } |
Les étapes du traitement:
Récupération de la classe application pour accéder au pointeur sur document template (m_pFirstTemplate)
Création d'une « Mdi » à partir du deuxième document template (m_pTwoDocTemplate)
Rattacher la MDI avec sa fenêtre CMyEditView au premier document template avec la fonction InitialUpdateFrame .
On répétera le même processus pour la description et la création d'une fenêtre supplémentaire.
Au final on aura bien un objet document avec plusieurs Fenêtres.
C'est vérifiable par exemple en parcourant les fenêtres à partir de l'objet document :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void CMyEditView::OnInitialUpdate() { CEditView::OnInitialUpdate(); // TODO: Add your specialized code here and/or call the base class POSITION pos=GetDocument()->GetFirstViewPosition(); CView *pView; do { pView=GetDocument()->GetNextView(pos); } while(pView); } |
Notes:
On n'est pas pour autant obligé de stocker des données communes dans le document.
Le document n'a pas de partie graphique visible.
En passant par les fonctions de la CMDIChildWnd .
A partir de la fenêtre fille dans la fonction OnInitialUpdate() on commence par récupérer le pointeur sur la MDI avec la fonction GetParentFrame() pour appeler MDIMaximize( );
Code c++ : | Sélectionner tout |
1 2 | ((CMDIChildWnd *)GetParentFrame())->MDIMaximize( ); |
En passant par les fonctions de la CMDIChildWnd .
A partir de la fenêtre fille dans la fonction OnInitialUpdate() on commence par récupérer le pointeur sur la MDI avec la fonction GetParentFrame() pour appeler MDIRestore( );
Code c++ : | Sélectionner tout |
1 2 | ((CMDIChildWnd *)GetParentFrame())->MDIRestore( ); |
Code c++ : | Sélectionner tout |
1 2 3 | CMDIFrameWnd::MDIGetActive CMDIChildWnd* MDIGetActive( BOOL* pbMaximized = NULL ) const; |
On commence par récupérer le pointeur sur la MainFrame avec AfxGetMainWnd().
Code c++ : | Sélectionner tout |
1 2 3 4 5 | BOOL maximized; CMDIChildWnd* child =((CMDIFrameWnd *)AfxGetMainWnd())->MDIGetActive(&maximized); if (child && (!maximized)) child->MDIMaximize(); // ou MDIMaximize(child); |
En utilisant la fonction IsIconic() de la classe CWnd.
Code c++ : | Sélectionner tout |
1 2 3 4 | CWnd::IsIconic BOOL IsIconic( ) const; |
Code c++ : | Sélectionner tout |
1 2 3 4 5 | BOOL maximized; CMDIChildWnd* child =((CMDIFrameWnd *)AfxGetMainWnd())-> MDIGetActive(&maximized); if (child && (maximized || child->IsIconic())) child->MDIRestore(); // ou ((CMDIFrameWnd *)AfxGetMainWnd())->MDIRestore(child); |
En passant par les fonctions de la CMDIChildWnd .
A partir de la fenêtre fille dans la fonction OnInitialUpdate() on commence par récupérer le pointeur sur la MDI avec la fonction GetParentFrame() pour appeler MDIActivate( );
Code c++ : | Sélectionner tout |
1 2 | GetParentFrame()->MDIActivate( ); |
En passant par les fonctions de la CMDIChildWnd .
A partir de la fenêtre fille dans la fonction OnInitialUpdate() on commence par récupérer le pointeur sur la MDI avec la fonction GetParentFrame() pour appeler ActivateFrame:
Code c++ : | Sélectionner tout |
1 2 3 4 | CFrameWnd::ActivateFrame virtual void ActivateFrame( int nCmdShow = - 1); |
Code c++ : | Sélectionner tout |
1 2 | GetParentFrame()->ActivateFrame(SW_RESTORE); |
On rajoutera la séquence SetWindowPos dans la fonction OnCreate de la classe CMainFrame juste après les initialisations classiques toolbar dialogbar etc...
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 | int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } 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 } // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); // MainFrame Always on Top ! CRect rect; GetWindowRect( rect ); ::SetWindowPos(m_hWnd , HWND_TOPMOST, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW); return 0; } |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 | CRect RectFrame; // Récupération de la taille de la mdi GetParentFrame()->GetWindowRect(&RectFrame); // changement de la hauteur sans bouger la fenêtre . GetParentFrame()->SetWindowPos(NULL,0,0,RectFrame.Width(),lParam,SWP_NOMOVE | SWP_NOZORDER); |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 | BOOL SetWindowPos ( const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags ); |
Dans une application MFC il n' y a pas de mécanismes standard pour la mémorisation des fenêtres.
Pour remédier à ce problème il faudra mettre en place une sauvegarde de la position et taille de la fenêtre principale (MainFrame) et des fenêtres Filles (MDIChild).
Le code qui suit est une implémentation de ces fonctionnalités avec une classe template permettant l'insertion dans un projet existant sans modifications excessives de 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 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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | // TplMDIFrame.hpp : interface of the CTplMDIFrame class // ///////////////////////////////////////////////////////////////////////////// #if !defined(AFX_TPLMDIFRAME_H__59DC7C67_79D6_4082_A38B_4CD17E8257C1__INCLUDED_) #define AFX_TPLMDIFRAME_H__59DC7C67_79D6_4082_A38B_4CD17E8257C1__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // Farscape : le 22/02/2005 Beta 1.0 // classe de base et traitement sur la MainFrame. template <class GENERIC_FRAME> class CTplMDIFrame : public GENERIC_FRAME { public: CTplMDIFrame() { m_rectFrame=CRect(0,0,0,0); m_bMaximized=FALSE; m_bInitPos=false; SetSectionName(); } //------------------------ virtual ~CTplMDIFrame(){SaveFramePos();} void SetSectionName(const char *szSection="AppPos") { m_strSection=szSection; } //------------------------ void SaveFramePos() { MakeSection(); AfxGetApp()->WriteProfileInt(m_strSection, "Maximized", m_bMaximized); AfxGetApp()->WriteProfileBinary(m_strSection, "FrameRect", (BYTE*)&m_rectFrame,sizeof(CRect)); AfxGetApp()->WriteProfileBinary(m_strSection, "InitialFrameRect", (BYTE*)&m_rectInitialFrame,sizeof(CRect)); } //------------------------ virtual void MakeSection(){} //------------------------ voidLoadFramePos() { BYTE* pb = NULL; UINT nLen = 0; MakeSection(); m_bMaximized = AfxGetApp()->GetProfileInt(m_strSection, "Maximized", (int)FALSE); m_rectFrame.SetRect(0,0,0,0); m_rectInitialFrame.SetRect(0,0,0,0); if (AfxGetApp()->GetProfileBinary(m_strSection, "FrameRect", &pb, &nLen)) { ASSERT(nLen == sizeof(CRect)); memcpy(&m_rectFrame, pb, sizeof(CRect)); delete pb; } if (AfxGetApp()->GetProfileBinary(m_strSection, "InitialFrameRect", &pb, &nLen)) { ASSERT(nLen == sizeof(CRect)); memcpy(&m_rectInitialFrame, pb, sizeof(CRect)); delete pb; } CRect rectScreen(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); CRect rectInt; rectInt.IntersectRect(&rectScreen, &m_rectFrame); if (rectInt.Width() < 10 || rectInt.Height() < 10) m_rectFrame.SetRect(0, 0, 0, 0); } //------------------------ voidShowMainFrame(int nCmdShow) { ASSERT(this->IsKindOf( RUNTIME_CLASS(CMDIFrameWnd))); AfxGetApp()->m_nCmdShow =nCmdShow; if (m_bMaximized) AfxGetApp()->m_nCmdShow = SW_SHOWMAXIMIZED; ShowWindow(AfxGetApp()->m_nCmdShow); UpdateWindow(); } //------------------------ virtual BOOL PreCreateWindow(CREATESTRUCT& cs) { if(cs.lpszClass && !m_bInitPos) { LoadFramePos(); m_bInitPos=true; if(m_rectFrame.Width() > 0 && m_rectFrame.Height() > 0) { cs.x = m_rectFrame.left; cs.y = m_rectFrame.top; cs.cx = m_rectFrame.Width(); cs.cy = m_rectFrame.Height(); } } // MainFrame if(this->IsKindOf( RUNTIME_CLASS(CMDIFrameWnd))) { if(!GENERIC_FRAME::PreCreateWindow(cs) ) return FALSE; } else { // child if(GENERIC_FRAME::PreCreateWindow(cs) ) return FALSE; } // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return TRUE; } // --------------------------- CRect &GetInitialRectFrame(){return m_rectInitialFrame;} // --------------------------- void SetInitialRectFrame(CRect Rect){m_rectInitialFrame=Rect;} // --------------------------- void GetWndPos() { WINDOWPLACEMENT wp; wp.length = sizeof(wp); GetWindowPlacement(&wp); m_rectFrame = wp.rcNormalPosition; } //------------------------ virtual LRESULT DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { if(nMsg==WM_DESTROY ) { m_bMaximized = (GetStyle() & WS_MAXIMIZE); GetWndPos(); } if(nMsg==WM_MOVE) { GetWndPos(); } if(nMsg==WM_SIZE) { GetWndPos(); } return GENERIC_FRAME::DefWindowProc( nMsg, wParam,lParam); } // Attributes public: bool m_bInitPos; BOOL m_bMaximized; CRect m_rectFrame; CRect m_rectInitialFrame; CString m_strSection; }; // classe pour les MDIChild. class CMDIChildEx : public CTplMDIFrame<CMDIChildWnd> { public: CMDIChildEx() { m_nPosCurrent=-1; SetSectionName("Child"); } ~CMDIChildEx() { POSITION pos=m_ListSection.Find(m_strSection); if(pos) m_ListSection.RemoveAt(pos); } //------------------------ virtual void ActivateFrame( int nCmdShow = -1 ) { if(m_bMaximized ) nCmdShow = SW_MAXIMIZE; CMDIChildWnd::ActivateFrame(nCmdShow); } virtual void MakeSection() { CString str; str.Format("%s-%d",(const char *)m_strSection,m_nIDHelp); m_strSection=str; if(m_nPosCurrent==-1) { int i=0; while(1) { str.Format("%s:%d",(char *)(const char *)m_strSection,i); if(m_ListSection.Find(str)) i++; else { m_ListSection.AddTail(str); break; } } m_nPosCurrent=i; } m_strSection=str; } public: static CList<CString ,CString&> m_ListSection; protected: int m_nPosCurrent; }; #endif // !defined(AFX_TPLMDIFRAME_H__59DC7C67_79D6_4082_A38B_4CD17E8257C1__INCLUDED_) // TplMDIFrame.cpp #include "stdafx.h" #include "TplMDIFrame.hpp" CList<CString ,CString&> CMDIChildEx::m_ListSection; |
Utilisation: au niveau de la classe CMainframe:
Code C++ : | Sélectionner tout |
1 2 3 4 5 | #include "TplMDIFrame.hpp" class CMainFrame : public CTplMDIFrame<CMDIFrameWnd> { .......... |
au niveau de la classe CChildFrame
Code C++ : | Sélectionner tout |
1 2 3 4 | #include "TplMDIFrame.hpp" class CChildFrame : public CMDIChildEx { ........ |
au niveau de la classe d'application dans la fonction initInstance :
Code C++ : | Sélectionner tout |
1 2 3 4 5 | // The main window has been initialized, so show and update it. pMainFrame->ShowMainFrame(m_nCmdShow); // la ligne du dessous remplace ces deux lignes //pMainFrame->ShowWindow(m_nCmdShow); //pMainFrame->UpdateWindow(); |
au niveau des View il faudra enlever la ligne ResizeParentToFit():
Code C++ : | Sélectionner tout |
1 2 3 4 5 6 7 | void CTestMdILayoutView::OnInitialUpdate() { CFormView::OnInitialUpdate(); // ne pas appeler //ResizeParentToFit(); } |
Fonctionnalités : Ces classes template permettent la gestion de la taille et position de la fenêtre principale ainsi que le mode maximiser de l'application.
Au niveau des fenêtres filles, on retrouve les mêmes fonctionnalités plus la gestion des positions pour plusieurs fenêtres de la même classe.
La différenciations des views se fait grâce à leur numéro d'identifiant dans les ressources.
Ces informations sont stockées dans le .ini de l'application qui ressemblera à ça :
Code ini : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | [AppPos] Maximized=16777216 FrameRect=EIAAAAAAOKAAAAAAEIDAAAAAHNCAAAAA [Child-129:0] Maximized=0 FrameRect=HMBAAAAAHABAAAAAKPDAAAAACKCAAAAA [Child-129:1] Maximized=0 FrameRect=PPPPPPPPPPPPPPPPNMBAAAAAFABAAAAA |
L'application est référencée par AppPos et les fenêtres filles par Child suivi du numéro d'identifiant et le numéro d'appel.
Un exemple complet : TestMdiLayout.zip
Dans un contexte SDI/MDI, le titre d'une fenêtre est régi par le document auquel elle se rattache. Ce comportement est dû au style FWS_ADDTOTITLE, activé par défaut, du cadre affichant la vue.
Le nom du document est demandé à la création du projet. A l'étape 4 de l'AppWizard, cliquez sur "Advanced..." :
- le champ "Main frame caption" détermine le début du titre du cadre principal
- le champ "Doc type name" détermine la racine du nom par défaut du document. Si on ne met rien la racine sera "sans nom".
le nom du document peut aussi être modifié dans le code par l'appel de la fonction CDocument::SetTitle(LPCTSTR lpszTitle).
Le titre sera formaté ainsi :
- SDI : pour le cadre principal : "nom par défaut du document - nom du cadre"
- MDI :
pour le cadre principal :
- sans document ouvert : "titre cadre principal"
- avec document ouvert : "titre cadre principal - racine du nom du document actif et n°"
- avec document ouvert et vue maximisée : "titre cadre principal - [racine du nom du document actif et n°]" pour une vue : "racine du nom du document actif et n°"
On peut vouloir modifier ce mécanisme pour personnaliser le titre d'une vue. Cela peut-être intéressant dans un contexte SDI ou MDI à document à vues multiples. Pour cela, chaque vue doit être associée à une ressource IDR (menu, icône, ...) différente (ce qui donnera lieu à une chaîne par ressource dans la String Table).
1. On modifie la chaîne de la String Table associée à chaque ressource ( Comment changer le filtre de l'ouverture de fichiers dans une application MFC ?) :
SDI
Code c++ : | Sélectionner tout |
1 2 3 4 5 | ID Value Caption IDR_MAINFRAME 128 Titre main frame\nRacine nom doc par défaut\n\nFichier machin (*.m)\n.m\nM.Document\nM Document IDR_TATA 129 Titre perso de la 1ère vue\n\n\n\n\n\n IDR_TITI 130 Titre perso de la 2ème vue\n\n\n\n\n\n IDR_TOTO 131 Titre perso de la 3ème vue\n\n\n\n\n\n |
Code c++ : | Sélectionner tout |
1 2 3 4 5 | ID Value Caption IDR_MAINFRAME 128 Titre main frame\n\nRacine nom doc par défaut\nFichier machin (*.m)\n.m\nM.Document\nM Document IDR_TATA 129 Titre perso de la 1ère vue\n\n\n\n\n\n IDR_TITI 130 Titre perso de la 2ème vue\n\n\n\n\n\n IDR_TOTO 131 Titre perso de la 3ème vue\n\n\n\n\n\n |
SDI
On surchargera CMainFrame:reCreateWindow(CREATESTRUCT& cs).
MDI
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) { // le titre de la fenêtre ne correspond plus au titre du document // si la ressource ne définit pas le champ titre, la fenêtre aura // comme titre "sans nom" cs.style &= ~(LONG)FWS_ADDTOTITLE; // Appelle la fonction de la classe mère return CMDIChildWnd::PreCreateWindow(cs); } |
Pour empêcher la fermeture d'une fenêtre il faut intercepter la commande SC_CLOSE comme dans Comment intercepter la fermeture de l'application ?
Pour griser l'option fermeture du menu système et griser la croix de la fenêtre on procédera comme suit :
Code C++ : | Sélectionner tout |
1 2 3 4 5 | // exemple à partir de la view. CMenu *pSysMenu =GetParentFrame()->GetSystemMenu(FALSE); ASSERT(pSysMenu != NULL); pSysMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND |MF_GRAYED ); |
On commence par récupérer le menu système de la MDI, ensuite on règle le statut grisé avec la fonction EnableMenuItem pour l'identifiant SC_CLOSE.
Il faut intercepter le message WM_WINDOWPOSCHANGING sur la MDIChild. Exemple:
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 | void CChildFrame::OnWindowPosChanging(WINDOWPOS* lpwndpos) { if(!m_rect.IsRectEmpty()) // empeche de bouger... { lpwndpos->x=m_rect.left; lpwndpos->y=m_rect.top; CRect rectBarPos; static_cast<CMainFrame *>(AfxGetMainWnd())->m_wndToolBar.GetWindowRect(&rectBarPos); lpwndpos->y-=rectBarPos.Height(); } CMDIChildWnd::OnWindowPosChanging(lpwndpos); // TODO: Add your message handler code here } //------------------------------------------------------------ void CChildFrame::OnSize(UINT nType, int cx, int cy) { CMDIChildWnd::OnSize(nType, cx, cy); if(m_rect.IsRectEmpty()) // position initiale { GetWindowRect(&m_rect); AfxGetMainWnd()->ScreenToClient(&m_rect); } // TODO: Add your message handler code here } |
Il se peut que le message ne soit pas implémenté avec VC 6.
Il faudra le rajouter manuellement
Le cas typique est l'accès de la vue à partir d'une boîte de dialogue.
On pourra procéder comme suit :
Code C++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | BOOL CMyDialog::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here // acces à la seule vue active CView *pView=static_cast<CFrameWnd *>(AfxGetMainWnd())->GetActiveView(); // transformation sur la classe de la vue. CSampleSDIView * pSDIView= static_cast<CSampleSDIView *>(pView); pSDIView->m_Edit.SetWindowText("essai"); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } |
Pourquoi ne pas faire GetParent() ? Hé bien dans un projet SDI GetParent() dans la boîte de dialogue renvoie le pointeur sur la CMainFrame.
Voir aussi Comment récupérer la fenêtre parent dans une boîte de dialogue ?
Note : la méthode pourra aussi être appliquée sur un projet MDI.
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.