[VC++, MFC] Comment deriver une classe a partir de sa propre classe?

Comment deriver une classe a partir de sa propre classe? [VC++, MFC] - C++ - Programmation

Marsh Posté le 11-09-2002 à 17:11:40    

Je cree une boite de dialogue et avec le wizard de VC je cree une classe. Mais j'aimerai que celle ci derive d'une autre classe que j'ai deja cree. Malheureusement, cette derniere n'apparait pas dans la liste que me propose le wizard. Comment je peux faire?


Message édité par try58 le 11-09-2002 à 17:30:33

---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 11-09-2002 à 17:11:40   

Reply

Marsh Posté le 13-09-2002 à 09:44:56    

:bounce:


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 13-09-2002 à 11:51:33    

try58 a écrit a écrit :

Je cree une boite de dialogue et avec le wizard de VC je cree une classe. Mais j'aimerai que celle ci derive d'une autre classe que j'ai deja cree. Malheureusement, cette derniere n'apparait pas dans la liste que me propose le wizard. Comment je peux faire?




 
Tu choisis "Generic" quand tu crées ta classe avec le wizard et tu as la liste des classes que tu as déjà ajoutées au projet.

Reply

Marsh Posté le 13-09-2002 à 12:01:19    

Smaragdus a écrit a écrit :

 
 
Tu choisis "Generic" quand tu crées ta classe avec le wizard et tu as la liste des classes que tu as déjà ajoutées au projet.




Le pb c'est que je veux que cette nouvelle classe que je veux creer soit attache a une dialogue!!


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 13-09-2002 à 12:04:34    

try58 a écrit a écrit :

 
Le pb c'est que je veux que cette nouvelle classe que je veux creer soit attache a une dialogue!!




 
"soit attaché" : ?

Reply

Marsh Posté le 13-09-2002 à 12:31:29    

Smaragdus a écrit a écrit :

 
 
"soit attaché" : ?  




C'est chaud a expliquer!
Je vais detailler ce que j'ai fais.
J'ai cree une boite de dialogue avec l'editeur de resource. Je lui affecte (ou rattache) une classe avec le wizard qui derive de la classe CProptertyPage. Je l'ai nomme CMyPropertyPage.
Ensuite j'ai cree une autre boite de dialogue. Je voulais lui affecter une nouvelle classe qui aurait derive de CMyPropertyPage mais le pb c'est que cette derniere n'apparait pas dans la liste!!
J'ai essaye comme tu me disais. J'ai fais Insert/New Class, j'ai choisi generic class et puis j'ai selectionne CMyPropertyPage.
Donc la classe est bien creer mais elle n'est pas rattache a une boite de dialogue.


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 13-09-2002 à 14:35:59    

:bounce:


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 13-09-2002 à 17:25:59    

try58 a écrit a écrit :

 :bounce:  




 
Créé la nouvelle classe de ta boite de dialogue en la faisant dérivé de CPropertyPage; ensuite edite les .h et .cpp créés en remplacant toutes les instances de "CPropertyPage" par "CMyPropertyPage"; fait gaffe aussi aux macros IMPLEMENT_DYNCREATE si tu les utilisent...
 
c'est ok?
 
 :bounce:  :bounce:  :bounce:

Reply

Marsh Posté le 13-09-2002 à 17:33:29    

yung3001 a écrit a écrit :

 
 
Créé la nouvelle classe de ta boite de dialogue en la faisant dérivé de CPropertyPage; ensuite edite les .h et .cpp créés en remplacant toutes les instances de "CPropertyPage" par "CMyPropertyPage"; fait gaffe aussi aux macros IMPLEMENT_DYNCREATE si tu les utilisent...
 
c'est ok?
 
 :bounce:  :bounce:  :bounce:  



Je vais essayer mais j'espere que ca va pas tout me ruiner. Je te remercie!


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 13-09-2002 à 17:39:58    

try58 a écrit a écrit :

Je vais essayer mais j'espere que ca va pas tout me ruiner. Je te remercie!




 
Normalement, c'est tout con à faire...
Si tu fais une erreur, et que tu veux retirer correctement ta classe de Visual Studio et du classe Wizard: Efface les fichier .cpp et .h, et rappelle le class wizard: la il va te dire qu'il ne trouve plus les fichier de la classe correspondante, et tu as un bouton pour l'effacer de la liste de classes du project; si ça marche pas, efface le fichier .clw du project et rappelle le Class Wizard; la il va te demander de regenerer un fichier .clw tout neuf et à jour!
 
 :bounce:  :bounce:  :bounce:

Reply

Marsh Posté le 13-09-2002 à 17:39:58   

Reply

Marsh Posté le 13-09-2002 à 17:44:10    

Bon pour l'instant, je peux pas trop dire si ca marche mais ca compile


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 20-09-2002 à 10:30:43    

Mon programme plante. J'ai toujours ma classe CMyPropertyPage derivee de CPropertyPage. J'ai creer une autre classe CTest, derivee de CMyPropertyPage en faisant la methode decrite precedement :
Je cree CTest avec le wizard derivee de CPropertyPage, j'obtiens le code suivant :

Code :
  1. IMPLEMENT_DYNAMIC(CTest, CPropertyPage)
  2. CTest::CTest()
  3. : CPropertyPage(CTest::IDD)
  4. {
  5. }
  6. CTest::~CTest()
  7. {
  8. }
  9. void CTest::DoDataExchange(CDataExchange* pDX)
  10. {
  11. CPropertyPage::DoDataExchange(pDX);
  12. }
  13. BEGIN_MESSAGE_MAP(CTest, CPropertyPage)
  14. END_MESSAGE_MAP()


Je remplace CPropertyPage par CMyPropertyPage et j'enleve CTest::IDD :

Code :
  1. IMPLEMENT_DYNAMIC(CTest, CMyPropertyPage)
  2. CTest::CTest()
  3. : CMyPropertyPage()
  4. {
  5. }
  6. CTest::~CTest()
  7. {
  8. }
  9. void CTest::DoDataExchange(CDataExchange* pDX)
  10. {
  11. CMyPropertyPage::DoDataExchange(pDX);
  12. }
  13. BEGIN_MESSAGE_MAP(CTest, CMyPropertyPage)
  14. END_MESSAGE_MAP()


Je rajoute ensuite une CListCtrl dans ma dialogue associee a ma CTest. Le programme se met a planter des que je rajoute une variable de controle pour ma CListCtrl et je ne vois vraiment pas pourquoi!!


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 20-09-2002 à 14:30:11    

:bounce:


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 20-09-2002 à 15:34:00    

Salut,
 
Bon déjà, tu dois remaplacer toutes les instances de CPropertyPage par CMyPropertyPage dans la classe CTest; sinon tu va avoir des problèmes avec la msg map et la creation dynamique.
 
Ensuite lance ton programme en debug (F5) et reagrde exactement ou ça plante (affiche une call stack pour t'aider)
 
:bounce: :bounce: :bounce:

Reply

Marsh Posté le 20-09-2002 à 15:37:05    

yung3001 a écrit a écrit :

Bon déjà, tu dois remplacer toutes les instances de CPropertyPage par CMyPropertyPage dans la classe CTest; sinon tu va avoir des problèmes avec la msg map et la creation dynamique.



Bah c'est ce que j'ai fais, regarde le code que j'ai ecris!
Sinon, ca plante quand j'appelle la fonction Create de ma CMyPropertySheet derivee de CPropertySheet et uniquement quand j'ai affecte une variable de control a un composant, quel qu'il soit!


Message édité par try58 le 20-09-2002 à 15:39:36

---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 20-09-2002 à 15:44:08    

try58 a écrit a écrit :

Bah c'est ce que j'ai fais, regarde le code que j'ai ecris!
Sinon, ca plante quand j'appelle la fonction Create de ma CMyPropertySheet derivee de CPropertySheet et uniquement quand j'ai affecte une variable de control a un composant, quel qu'il soit!




 
Ah okkk!!! Si tu as deja affecte une variable de control , comme tu dis, c'est normal que la fonction create plante! Quand tu fais le liens entre une variable et un control (avec la Wizard), le mecanisme de DDE (Dynamic Data Exchange) s'occupe de créé le control pour toi! Donc si tu essayes de le recréer toi même, il n'aime pas!  Pour cela, va en debug, et juste avant de faire ton create, regarde la valeur du membre m_hWnd de ton list control; tu verras qu'il n'est pas NULL et qu'il a une valeur valide (pas un truc du style 0xcccccccc). Cela veut donc dire que l'object list control en lui même existe et qu'il est rattaché à ta classe CListCtrl.  
 
Is it clear? :D

Reply

Marsh Posté le 20-09-2002 à 15:45:33    

try58 a écrit a écrit :

Bah c'est ce que j'ai fais, regarde le code que j'ai ecris!
Sinon, ca plante quand j'appelle la fonction Create de ma CMyPropertySheet derivee de CPropertySheet et uniquement quand j'ai affecte une variable de control a un composant, quel qu'il soit!




 
Donc tu peux virer ton create... Les DDE et tous les mecanismes des MFC sont la pour eviter justement d'ecrire du code répétitif, donc si tu utilises un template de boite de dialog, tu n'as en général, rien à créé toi même.

Reply

Marsh Posté le 20-09-2002 à 16:07:54    

Je vais m'expliquer mieux! En fait, le create ne porte pas sur un control mais sur un objet de type CMyPropertySheet qui derive de CPropertySheet. Quand je dis que le programme plante lorsque je rajoute une variable de control a un composant (j'ai essaye avec une CListCtrl et une CEdit), c'est avec le wizard que je l'ai cree.
En ce qui concerne ma CMyPropertySheet, je suis oblige d'appeler la fonction Create parce que je ne veux pas que celle-ci soit modale, sinon j'aurai utilise DoModal().
Voici mon code contenant la ligne ou ca plante :

Code :
  1. void CMonitoringBoxDlg::AffSwitchSheet(HTREEITEM hitem)
  2. {
  3. HTREEITEM hchild;
  4. CString  string;
  5. COid  *TabOid;
  6. CTest  Page1;
  7. hchild = m_RightTree.GetChildItem(hitem);
  8. while (hchild)
  9. {
  10.  string = m_RightTree.GetItemText(hchild);
  11.  if (string == "IP" )
  12.  {
  13.   TabOid = TabSwitchIp;
  14.   m_SwitchSheet->AddPage(&Page1);
  15.  }
  16.  hchild = m_RightTree.GetNextItem(hchild, TVGN_NEXT);
  17. }
  18. m_SwitchSheet->Create(this); // ca plante ici
  19. }

m_SwitchSheet est de type CMyPropertySheet


Message édité par try58 le 20-09-2002 à 16:09:25

---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 20-09-2002 à 16:14:07    

try58 a écrit a écrit :

Je vais m'expliquer mieux! En fait, le create ne porte pas sur un control mais sur un objet de type CMyPropertySheet qui derive de CPropertySheet. Quand je dis que le programme plante lorsque je rajoute une variable de control a un composant (j'ai essaye avec une CListCtrl et une CEdit), c'est avec le wizard que je l'ai cree.
En ce qui concerne ma CMyPropertySheet, je suis oblige d'appeler la fonction Create parce que je ne veux pas que celle-ci soit modale, sinon j'aurai utilise DoModal().
Voici mon code contenant la ligne ou ca plante :

Code :
  1. void CMonitoringBoxDlg::AffSwitchSheet(HTREEITEM hitem)
  2. {
  3. HTREEITEM hchild;
  4. CString  string;
  5. COid  *TabOid;
  6. CTest  Page1;
  7. hchild = m_RightTree.GetChildItem(hitem);
  8. while (hchild)
  9. {
  10.  string = m_RightTree.GetItemText(hchild);
  11.  if (string == "IP" )
  12.  {
  13.   TabOid = TabSwitchIp;
  14.   m_SwitchSheet->AddPage(&Page1);
  15.  }
  16.  hchild = m_RightTree.GetNextItem(hchild, TVGN_NEXT);
  17. }
  18. m_SwitchSheet->Create(this); // ca plante ici
  19. }

m_SwitchSheet est de type CMyPropertySheet




 
Difficile à dire comme ça; comme je te l'ai dit avant, il faudrait afficher la "call stack", et voir ou ça plante dans la fonction Create (donc dans le code des MFCs). Conseil: Toujours regarder en détails le code des MFCs, c'est le seulmoyen d'apprendre réèlement à s'en servir.

Reply

Marsh Posté le 20-09-2002 à 16:20:35    

Code :
  1. BOOL CPropertySheet::Create(CWnd* pParentWnd, DWORD dwStyle, DWORD dwExStyle)
  2. {
  3. _AFX_THREAD_STATE* pState = AfxGetThreadState();
  4. // Calculate the default window style.
  5. if (dwStyle == (DWORD)-1)
  6. {
  7.  pState->m_dwPropStyle = DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP |
  8.        DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION;
  9.  // Wizards don't have WS_SYSMENU.
  10.  if (!IsWizard())
  11.   pState->m_dwPropStyle |= WS_SYSMENU;
  12. }
  13. else
  14. {
  15.  pState->m_dwPropStyle = dwStyle;
  16. }
  17. pState->m_dwPropExStyle = dwExStyle;
  18. ASSERT_VALID(this);
  19. ASSERT(m_hWnd == NULL);
  20. VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
  21. AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
  22. // finish building PROPSHEETHEADER structure
  23. BuildPropPageArray();
  24. m_bModeless = TRUE;
  25. m_psh.dwFlags |= (PSH_MODELESS|PSH_USECALLBACK);
  26. m_psh.pfnCallback = AfxPropSheetCallback;
  27. m_psh.hwndParent = pParentWnd->GetSafeHwnd();
  28. // hook the window creation process
  29. AfxHookWindowCreate(this);
  30. HWND hWnd = (HWND)PropertySheet(&m_psh); //ca plante ici   
  31. #ifdef _DEBUG
  32. DWORD dwError = ::GetLastError();
  33. #endif
  34. // cleanup on failure, otherwise return TRUE
  35. if (!AfxUnhookWindowCreate())
  36.  PostNcDestroy();    // cleanup if Create fails
  37. if (hWnd == NULL || hWnd == (HWND)-1)
  38. {
  39. #ifdef _DEBUG
  40.  TRACE(traceAppMsg, 0, "PropertySheet() failed: GetLastError returned %d\n", dwError);
  41. #endif
  42.  return FALSE;
  43. }
  44. ASSERT(hWnd == m_hWnd);
  45. return TRUE;
  46. }


Message édité par try58 le 20-09-2002 à 16:21:03

---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 23-09-2002 à 09:09:42    

try58 a écrit a écrit :

Code :
  1. BOOL CPropertySheet::Create(CWnd* pParentWnd, DWORD dwStyle, DWORD dwExStyle)
  2. {
  3. _AFX_THREAD_STATE* pState = AfxGetThreadState();
  4. // Calculate the default window style.
  5. if (dwStyle == (DWORD)-1)
  6. {
  7.  pState->m_dwPropStyle = DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP |
  8.        DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION;
  9.  // Wizards don't have WS_SYSMENU.
  10.  if (!IsWizard())
  11.   pState->m_dwPropStyle |= WS_SYSMENU;
  12. }
  13. else
  14. {
  15.  pState->m_dwPropStyle = dwStyle;
  16. }
  17. pState->m_dwPropExStyle = dwExStyle;
  18. ASSERT_VALID(this);
  19. ASSERT(m_hWnd == NULL);
  20. VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
  21. AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
  22. // finish building PROPSHEETHEADER structure
  23. BuildPropPageArray();
  24. m_bModeless = TRUE;
  25. m_psh.dwFlags |= (PSH_MODELESS|PSH_USECALLBACK);
  26. m_psh.pfnCallback = AfxPropSheetCallback;
  27. m_psh.hwndParent = pParentWnd->GetSafeHwnd();
  28. // hook the window creation process
  29. AfxHookWindowCreate(this);
  30. HWND hWnd = (HWND)PropertySheet(&m_psh); //ca plante ici   
  31. #ifdef _DEBUG
  32. DWORD dwError = ::GetLastError();
  33. #endif
  34. // cleanup on failure, otherwise return TRUE
  35. if (!AfxUnhookWindowCreate())
  36.  PostNcDestroy();    // cleanup if Create fails
  37. if (hWnd == NULL || hWnd == (HWND)-1)
  38. {
  39. #ifdef _DEBUG
  40.  TRACE(traceAppMsg, 0, "PropertySheet() failed: GetLastError returned %d\n", dwError);
  41. #endif
  42.  return FALSE;
  43. }
  44. ASSERT(hWnd == m_hWnd);
  45. return TRUE;
  46. }






 
Humm... bon, donc le membre PROPSHEETHEADER (m_psh) est forcemment mal initialisé. Le pointeur to le CWnd* parent est forcemment bon, puisque c'est un List Control qui est bien créé (ajout d'items ok).
Comme ça, j'suis désolé, mais je vois pas du premier coup d'oeil... en debug regarde toutes les valeurs de la structure m_psh, tu vas peu être voir ce qui coince...
 
Bon courage
 
 :bounce:  :bounce:  :bounce:

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed