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
Par défaut ce bouton est inactif.
Pour l'activer, il faut initialiser l'indicateur de modification de la page via SetModified(TRUE) lorsque l'utilisateur a modifié une page.
On surcharge pour cela la fonction OnCommand de chaque CPropertyPage.
Code c++ : | Sélectionner tout |
1 2 3 4 5 | BOOL CMyPropertyPage::OnCommand(WPARAM wParam, LPARAM lParam) { SetModified(TRUE); return CPropertyPage::OnCommand(wParam, lParam); } |
Il n'est pas besoin de redéfinir OnApply pour les autres pages.
Deux possibilités :
soit on traite l'action engendrée par le clic sur le bouton "Appliquer" (et "OK") dans OnApply (ce qui suppose de caster le CWnd* en la classe dérivée de CWnd qui gère la propertysheet et d'inclure le .h correspondant), solution moche
soit on utilise le message personnalisé que peut envoyer la propertypage à la classe dérivée de CWnd réceptrice.
On va utiliser la 2ème solution et laisser le soin à la classe dérivée de CWnd de gérer ce qui doit être fait après que l'utilisateur a appuyé sur "Appliquer" ou "OK".
On définit le message personnalisé dans le source de la propertypage
Code c++ : | Sélectionner tout |
1 2 | // par exemple #define WM_USERAPPLY WM_USER+5 |
Code c++ : | Sélectionner tout |
1 2 3 4 5 | BOOL CMyPropertyPage::OnApply() { m_pReceiver->SendMessage(WM_USERAPPLY); return CPropertyPage::OnApply(); } |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 | BEGIN_MESSAGE_MAP(CMyView, CView) //{{AFX_MSG_MAP(CMyView) ON_COMMAND(ID_MENU_MACHIN, OnMenuMachin) //}}AFX_MSG_MAP ON_MESSAGE(WM_USERAPPLY, OnUserApply) END_MESSAGE_MAP() |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 | protected: //{{AFX_MSG(CMyView) afx_msg void OnMenuMachin(); afx_msg LRESULT OnUserApply(WPARAM wParam, LPARAM lParam); //}}AFX_MSG DECLARE_MESSAGE_MAP() |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | LRESULT CMyView::OnUserApply(WPARAM wParam, LPARAM lParam) { TRACE("CMyView::OnUserApply -- wParam = %x\n", wParam); // on utilise les valeurs des membres des pages de m_pPS // pour faire quelquechose :-) ... return 0; } |
Une feuille de propriétés est une boîte de dialogue à onglets (pages de propriétés) possédant 3 boutons "OK", "Annuler" et "Appliquer".
Pour construire une feuille de propriétés il faut :
utiliser l'éditeur de ressources pour créer un modèle de dialogue par onglet. Le titre des boîtes de dialogue (Caption) sera le titre des onglets.
générer une classe dérivant de CPropertyPage pour chaque modèle de dialogue, ajouter des membres pour les contrôles. Si on compte implémenter l'action du bouton "Appliquer" alors ajouter la fonction CWndReceiver et un membre CWnd* dans l'une des classes pages.
Code c++ : | Sélectionner tout |
1 2 3 4 5 | private: CWnd* m_pReceiver; public: void CWndReceiver(CWnd* pReceiver) { m_pReceiver = pReceiver; } |
Code c++ : | Sélectionner tout |
1 2 3 | public: CMyPropertyPage1 m_page1; CMyPropertyPage2 m_page2; |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | CMyPropertySheet::CMyPropertySheet(LPCTSTR pszCaption, CWnd *pParentWnd = NULL, UINT iSelectPage = 0) { AddPage(&m_page1); AddPage(&m_page2); // si CWndReceiver a été implémenté // attention : pParentWnd ne devra jamais être NULL // le mieux est d'enlever la valeur NULL par défaut m_page1.CWndReceiver(pParentWnd); } |
Par exemple dans une classe vue CMyView
Code c++ : | Sélectionner tout |
1 2 | private: CMyPropertySheet * m_pPS; |
Code c++ : | Sélectionner tout |
1 2 3 4 | CMyView::CMyView(...):CView(...) { m_pPS = new CMyPropertySheet("Titre",this); } |
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 | // événement de clic sur le menu ouvrant la propertysheet CMyView::OnMenuMachin() { ... // On peut modifier le titre m_pPS ->SetTitle("Eventuellement, modification du titre"); // On peut donner des valeurs aux membres des pages // Si on ne le fait pas avant le DoModal, les valeurs seront // celles par défaut ou celles données dans le constructeur // de chaque page m_pPS ->m_page1.m_attr1 = ... ; m_pPS ->m_page1.m_attr2 = ... ; m_pPS ->m_page2.m_attr1 = ... ; m_pPS ->m_page2.m_attr2 = ... ; // On fait apparaître la propertysheet m_pPS->DoModal(); } |
Code c++ : | Sélectionner tout |
1 2 3 4 | CMyView::~CMyView() { delete m_pPS; } |
Exemple:
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | BOOL CMyPropSheet::OnInitDialog () { BOOL bResult = CPropertySheet::OnInitDialog(); int ids [] = {IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP }; CWnd *pWnd; for(int i=0;i<sizeof(ids)/sizeof(int);i++) { pWnd = GetDlgItem( ids[i] ); if(pWnd) { pWnd->EnableWindow(FALSE); pWnd->ShowWindow( SW_HIDE ); } } //................. |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 | //CPropertySheet dlgPropertySheet("Simple"); dlgPropertySheet.m_psh.dwFlags |= PSH_NOAPPLYNOW; //..... dlgPropertySheet.DoModal(); |
Le lancement d'une boîte d'une CPropertySheetne permet pas de spécifier l'emplacement de celle-ci à l'écran.
La solution consistera à surcharger la fonction DoModal pour positionner notre fenêtre à l'emplacement voulu.
Exemple sur une classe dérivée de CPropertySheet:
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 | #include <afxpriv.h> #include <AFXIMPL.H> // attention ce header est definit dans les sources des MFC ,on peut rajouter le chemin des src MFC dans la recherche des includes... int CMyPropertySheet::DoModal() { ASSERT_VALID(this); ASSERT(m_hWnd == NULL); // register common controls VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG)); AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG); // finish building PROPSHEETHEADER structure BuildPropPageArray(); // allow OLE servers to disable themselves CWinApp* pApp = AfxGetApp(); if (pApp != NULL) pApp->EnableModeless(FALSE); // find parent HWND HWND hWndTop; HWND hWndParent = CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &hWndTop); AFX_OLDPROPSHEETHEADER* psh = GetPropSheetHeader(); psh->hwndParent = hWndParent; BOOL bEnableParent = FALSE; if (hWndParent != NULL && ::IsWindowEnabled(hWndParent)) { ::EnableWindow(hWndParent, FALSE); bEnableParent = TRUE; } HWND hWndCapture = ::GetCapture(); if (hWndCapture != NULL) ::SendMessage(hWndCapture, WM_CANCELMODE, 0, 0); // setup for modal loop and creation m_nModalResult = 0; m_nFlags |= WF_CONTINUEMODAL; // hook for creation of window AfxHookWindowCreate(this); psh->dwFlags |= PSH_MODELESS; m_nFlags |= WF_CONTINUEMODAL; HWND hWnd = (HWND)::PropertySheet((PROPSHEETHEADER*)psh); if(m_nx || m_ny) // ma modification, trés modeste ... ::SetWindowPos(hWnd,NULL,m_nx,m_ny,0,0,SWP_NOSIZE); #ifdef _DEBUG DWORD dwError = ::GetLastError(); #endif psh->dwFlags &= ~PSH_MODELESS; AfxUnhookWindowCreate(); // handle error if (hWnd == NULL || hWnd == (HWND)-1) { TRACE1("PropertySheet() failed: GetLastError returned %d\n", dwError); m_nFlags &= ~WF_CONTINUEMODAL; } int nResult = m_nModalResult; if (ContinueModal()) { // enter modal loop DWORD dwFlags = MLF_SHOWONIDLE; if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; nResult = RunModalLoop(dwFlags); } // hide the window before enabling parent window, etc. if (m_hWnd != NULL) { SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW| SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); } if (bEnableParent) ::EnableWindow(hWndParent, TRUE); if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) ::SetActiveWindow(hWndParent); // cleanup DestroyWindow(); // allow OLE servers to enable themselves if (pApp != NULL) pApp->EnableModeless(TRUE); if (hWndTop != NULL) ::EnableWindow(hWndTop, TRUE); return nResult; } |
l'include de la classe :
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 | ///////////////////////////////////////////////////////////////////////////// // CMyPropertySheet class CMyPropertySheet : public CPropertySheet { DECLARE_DYNAMIC(CMyPropertySheet) // Construction public: CMyPropertySheet(CWnd* pWndParent = NULL); virtual int DoModal(); void SetCoord(int x,int y){m_nx=x;m_ny=y;} // Attributes public: CMyPropertyPage1 m_Page1; CMyPropertyPage2 m_Page2; CMyPropertyPage3 m_Page3; // Operations public: int m_nx,m_ny; // Attention : Initialisé a 0 dans le constructeur .... // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMyPropertySheet) //}}AFX_VIRTUAL // Implementation public: virtual ~CMyPropertySheet(); virtual void PostNcDestroy(); // Generated message map functions protected: //{{AFX_MSG(CMyPropertySheet) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; |
Utilisation dans le cadre de mon exemple:
Code c++ : | Sélectionner tout |
1 2 3 4 | CMyPropertySheet dlg; dlg.SetCoord(500,200); dlg.DoModal(); |
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.