IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MFC Discussion :

modèle View/Document : acces violation a la fermeture


Sujet :

MFC

  1. #1
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Points : 144
    Points
    144
    Par défaut modèle View/Document : acces violation a la fermeture
    Bonjour,

    J'ai créé une appli sur le modèle View, Document... pour gérer plus proprement l'application mais j'ai des erreurs "Access Violation" qui apparaissent des fois quand je ferme le programme...

    J'aurais aimé vos conseils, méthodes pour bien créer une appli sur ce modèle.

    Ma question est déjà, dans quelles méthodes de View, Document, CDialog, placer les initialisations, destructions ?
    Parce que il y a les constructeurs/Destructeurs mais il y a aussi les méthodes comme OnInitialUpdate(), Destroy, etc...

    Dans quel ordre sont créées mes classes ? D'abord le Document et ensuite la View je suppose ?

    Mon projet se présente ainsi :
    - CMainFrame hérite de CFrameWnd
    - CXApp hérite de CWinApp
    - CXDoc hérite de CDocument
    - CXView hérite de CFormView

    et

    - CXDlg hérite de CDialog, => type de fenetres que j'ouvre lors d'un clic sur un élément d'une listebox.


    C'est dans la View, que je crée les CXDlg et que je stocke les pointeurs.

    Dans CXDlg, du coup, j'utilise la méthode PostNCDestroy comme préconisé dans la FAQ...
    Lors de la fermeture du programme avec des fenetres CXDlg ouvertes, on passe bien dans PostNCDestroy, mais c'est après être passées dans cette fonction pour chaque petite fenêtre ouverte que j'ai un Access Violation et le debugueur me mets sur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CXDoc* CXView::GetDocument()
    {
    ASSERT(m_pDocument->isKindOf(RUNTIME_CLASS(CXDoc))); // ICI la petite flèche jaune dans Visual...
    return (CXDoc*) m_pDocument;
    }
    Le problème, c'est que je n'arrive pas à voir d'ou est appelé ce GetDocument...

    Bref, si quelqu'un a une idée et des conseils...

    Merci
    Bonne journée

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par italiasky Voir le message
    Bonjour,

    J'ai créé une appli sur le modèle View, Document... pour gérer plus proprement l'application mais j'ai des erreurs "Access Violation" qui apparaissent des fois quand je ferme le programme...
    Tu as raison. Probablement des destructions croisées ou redondantes...

    Citation Envoyé par italiasky Voir le message
    J'aurais aimé vos conseils, méthodes pour bien créer une appli sur ce modèle.

    Ma question est déjà, dans quelles méthodes de View, Document, CDialog, placer les initialisations, destructions ?
    Parce que il y a les constructeurs/Destructeurs mais il y a aussi les méthodes comme OnInitialUpdate(), Destroy, etc...
    D'abord, il faut que tu ais bien séparé les données propres au document de celles propres à l'affichage. Ensuite, quelques pistes:
    -> Dans les constructeurs sont construits et initialisées les variables membres de comportement de l'instance indépendamment du contenu du document/vue
    -> Dans OnInitialUpdate, OnNewDoc, ... seront construits les variables membres directement liées au contenu du/de la document/vue.
    Citation Envoyé par italiasky Voir le message
    Dans quel ordre sont créées mes classes ? D'abord le Document et ensuite la View je suppose ?
    Tu trouveras des informations précieuses dans le MSDN: ici (+++) et ici.
    En gros, le DocTemplate, crée un document puis la frame. La frame se charge de créer la vue.

    Citation Envoyé par italiasky Voir le message
    Mon projet se présente ainsi :
    - CMainFrame hérite de CFrameWnd
    - CXApp hérite de CWinApp
    - CXDoc hérite de CDocument
    - CXView hérite de CFormView

    et

    - CXDlg hérite de CDialog, => type de fenetres que j'ouvre lors d'un clic sur un élément d'une listebox.


    C'est dans la View, que je crée les CXDlg et que je stocke les pointeurs.
    En as-tu vraiment besoin? Il est souvent redondant de stocker les pointeurs des boites de dialogue non modal dans la fenêtre qui les a créé. Es-tu sur de ta conception?

    Citation Envoyé par italiasky Voir le message
    Dans CXDlg, du coup, j'utilise la méthode PostNCDestroy comme préconisé dans la FAQ...
    Effectivement, pour les boîtes de dialogue non modale, c'est une partique courante.

    Citation Envoyé par italiasky Voir le message
    Lors de la fermeture du programme avec des fenetres CXDlg ouvertes, on passe bien dans PostNCDestroy, mais c'est après être passées dans cette fonction pour chaque petite fenêtre ouverte que j'ai un Access Violation et le debugueur me mets sur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CXDoc* CXView::GetDocument()
    {
    ASSERT(m_pDocument->isKindOf(RUNTIME_CLASS(CXDoc))); // ICI la petite flèche jaune dans Visual...
    return (CXDoc*) m_pDocument;
    }
    Le problème, c'est que je n'arrive pas à voir d'ou est appelé ce GetDocument...
    Le debugger te donne aussi la pile d'appel. Ne peux-tu la voir?

    Une piste: n'aurais-tu pas dans le destructeur de tes boîtes de dialogue un appel vers la vue? Ou un envoi de message vers cette vue?

  3. #3
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Points : 144
    Points
    144
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    En as-tu vraiment besoin? Il est souvent redondant de stocker les pointeurs des boites de dialogue non modal dans la fenêtre qui les a créé. Es-tu sur de ta conception?
    Et bien en fait, je vais expliquer le contexte...
    J'ai une listebox, et à chaque clic sur un item, j'ouvre une boite de dialogue qui m'affiche des détails, etc...
    Mais par exemple, si j'en ai ouvert une dizaine, au lieu de les fermer une à une, j'ai fait un bouton qui permet de fermer toutes les fenêtres ouvertes...
    Donc je n'ai pas vu d'autres solutions que de stocker les pointeurs dans un vector et d'après de les parcourir un par un pour supprimer les fenêtres avec la méthode DestroyWindow() appelée sur chaque fenêtre...
    Et donc du coup aussi, je regarde lorsqu'on ferme une fenêtre seule normalement, de supprimer le pointeur correspondant dans le vector en ayant mis des ID comme attribut pour identifier les fenêtres.

    Après, ce n'est peut être pas la meilleure façon..
    Si quelqu'un peut me dire son conseil sur la façon la plus "sure" de faire ceci... en permettant d'avoir toujours un bouton pour fermer toutes les fenêtres ouvertes d'un coup si besoin...

    Citation Envoyé par 3DArchi Voir le message
    Le debugger te donne aussi la pile d'appel. Ne peux-tu la voir?
    Je n'ai pas réussi à sortir quelque chose de bon en regardant la pile lol

    Citation Envoyé par 3DArchi Voir le message
    Une piste: n'aurais-tu pas dans le destructeur de tes boîtes de dialogue un appel vers la vue? Ou un envoi de message vers cette vue?
    Et bien en fait dans PostNCDestroy(), j'ai un appel vers la vue oui...
    En fait, je récupère le pointeur de ma vue avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CXView* pView = CXView::GetView()
    pView->removeDlgByID(this->ID);
    Donc en fait, j'ai fait une méthode static GetView pour avoir le pointeur de ma vue parce que j'en avais besoin à des endroits... mais bon ca aussi c'est peut être pas recommander lol
    Et après, donc j'appelle une méthode de ma vue ou je donne l'ID de la fenetre ouverte qui est entrain de se détruire pour qu'elle la supprime du vector...

    Bref, je crois que c'est pas très clair tout ca... lol

    Merci

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par italiasky Voir le message
    Et bien en fait, je vais expliquer le contexte...
    J'ai une listebox, et à chaque clic sur un item, j'ouvre une boite de dialogue qui m'affiche des détails, etc...
    Mais par exemple, si j'en ai ouvert une dizaine, au lieu de les fermer une à une, j'ai fait un bouton qui permet de fermer toutes les fenêtres ouvertes...
    Donc je n'ai pas vu d'autres solutions que de stocker les pointeurs dans un vector et d'après de les parcourir un par un pour supprimer les fenêtres avec la méthode DestroyWindow() appelée sur chaque fenêtre...
    Et donc du coup aussi, je regarde lorsqu'on ferme une fenêtre seule normalement, de supprimer le pointeur correspondant dans le vector en ayant mis des ID comme attribut pour identifier les fenêtres.
    Tu ne peux pas t'en sortir avec FindWindow?

    Citation Envoyé par italiasky Voir le message
    Et bien en fait dans PostNCDestroy(), j'ai un appel vers la vue oui...
    En fait, je récupère le pointeur de ma vue avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CXView* pView = CXView::GetView()
    pView->removeDlgByID(this->ID);
    Donc en fait, j'ai fait une méthode static GetView pour avoir le pointeur de ma vue parce que j'en avais besoin à des endroits... mais bon ca aussi c'est peut être pas recommander lol
    Et après, donc j'appelle une méthode de ma vue ou je donne l'ID de la fenetre ouverte qui est entrain de se détruire pour qu'elle la supprime du vector...

    Bref, je crois que c'est pas très clair tout ca... lol
    Si,si: lorsque tu quittes tu ne maîtrise pas l'ordre des fermetures. Donc ta view doit être fermée avant les boîtes de dialogues -> CXView::GetView

    Soit tu arrives à te débarrasser de ton vecteur avec FindWindow, soit tu dois blinder tes fermetures:
    -> synchroniser la fermeture de la fenêtre view avec celle des dialogues,
    -> gérer l'invalidité de la vue courante (CXView::GetView peut retourner NULL et donc à tester).

  5. #5
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Points : 144
    Points
    144
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Tu ne peux pas t'en sortir avec FindWindow?
    Et bien je ne sais pas trop... FindWindowEx permet d'avoir un lien sur une fenêtre en fonction du titre de la fenêtre c'est bien ca ?

    Il faudrait que je stocke les noms des titres quand même alors du coup ?

    Citation Envoyé par 3DArchi Voir le message
    Si,si: lorsque tu quittes tu ne maîtrise pas l'ordre des fermetures. Donc ta view doit être fermée avant les boîtes de dialogues -> CXView::GetView

    Soit tu arrives à te débarrasser de ton vecteur avec FindWindow, soit tu dois blinder tes fermetures:
    -> synchroniser la fermeture de la fenêtre view avec celle des dialogues,
    -> gérer l'invalidité de la vue courante (CXView::GetView peut retourner NULL et donc à tester).
    Je ne sais pas si mon problème avec la fermeture des fenêtres CDialog ou pas est réglé mais en faisant des modifs, je ne l'ai plus... enfin j'ai toujours un problème à la fermeture de ma fenêtre, mais ce n'est plus au même endroit lol

    En fait, dans ma classe MainFrm, j'ai rajouté la fonction OnClose qui est appelé au clic sur la croix rouge, et j'ai donc remis dedans l'appel à la fonction de base :
    Et c'est dans cette fonction que ca bug, très exactement à la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // close all documents first
    pApp->CloseAllDocuments(FALSE)
    Encore une histoire de fermeture de vue, document apparemment non ?

    Merci
    Bonne journée

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    1/Une façon de ne plus planter mais sans vraiment résoudre ton problème à la base est de stocker des HWND au lieu des pointeurs. Ensuite, tu peux utiliser IsWindow et DestroyWindow.
    2/FindWindow peut être utilisée uniquement avec le nom de la classe (tu dois pouvoir retrouver le nom pour une boîte de dialogue).
    3/D'ailleurs, à la réflexion, tu peux aussi passer par EnumChildWindows si toutes tes boîtes de dialogues sont fille de ta classe vue ou frame.

    Enfin, tu as clairement un problème d'ordre dans la destruction des tes éléments qui aboutit à ton problème. J'ai toujours trouvé un peu confus ces choses entre la fermeture par la petite croix rouge, par Alt+F4, par un menu etc... Ce sont souvent des aspects mal maîtrisés. As-tu regardé si la doc de farscape sur les MFC aborde ce sujet? Peut-être la solution est dedans.

  7. #7
    Membre éclairé
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Points : 709
    Points
    709
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    1/Une façon de ne plus planter mais sans vraiment résoudre ton problème à la base est de stocker des HWND au lieu des pointeurs. Ensuite, tu peux utiliser IsWindow et DestroyWindow.
    2/FindWindow peut être utilisée uniquement avec le nom de la classe (tu dois pouvoir retrouver le nom pour une boîte de dialogue).
    3/D'ailleurs, à la réflexion, tu peux aussi passer par EnumChildWindows si toutes tes boîtes de dialogues sont fille de ta classe vue ou frame.

    Enfin, tu as clairement un problème d'ordre dans la destruction des tes éléments qui aboutit à ton problème. J'ai toujours trouvé un peu confus ces choses entre la fermeture par la petite croix rouge, par Alt+F4, par un menu etc... Ce sont souvent des aspects mal maîtrisés. As-tu regardé si la doc de farscape sur les MFC aborde ce sujet? Peut-être la solution est dedans.
    D'ac
    On peut aussi le faire avec SendMessage( hWnd, WM_DESTROY, 0,0) (Ou la version MFC avec 3 params);
    J'epère que je me suis pas trompé

  8. #8
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Points : 144
    Points
    144
    Par défaut
    Oui c'est vrai que c'est confus la façon dont c'est créé et détruit avec les MFC quand on a une vue et un document...
    Il y a les constructeurs/destructeurs, et j'ai l'impression que plusieurs méthodes pour initialiser ou détruire se ressemblent plus ou moins lol ! et on a du mal à savoir laquelle choisir, laquelle est appelée avant qui, et ce qui se passe exactement lors du clic sur la croix rouge ou quand on ferme avec un bouton rajouté...

    Bref, c'est un peu le fouilli tout ca j'ai l'impression.
    Et si je revois la façon dont est fait mon appli et que je reste qu'avec une seule classe qui hérite de CDialog pour la fenêtre principale...
    Du coup, je n'ai pas a gérer la fermeture, de la vue, du document, ce sera peut être moins prise de tête ?

    Par contre, pour CDialog, on initialise avec onInitDialog() c'est bien ca ?
    Et pour la destruction, il faut surcharger quelle méthode ? OnDestroy() ?

    Mais oui enfin d'un coté, j'aurais toujours le problème de quitter l'appli avec la croix rouge et avec un bouton "close" que j'aurais rajouté... je sens bien que ca ne va pas suivre le même chemin encore... lol

    C'est pas simple ces MFC c'est la première fois que je les utilise et la ca me séduit pas trop faut dire, au vu des cafouillages lol

    Enfin aller merci
    Bonne journée

Discussions similaires

  1. [WD-2010] Word - Acces - Modèle de document
    Par AidezMoiSvp dans le forum VBA Word
    Réponses: 6
    Dernier message: 20/11/2012, 12h38
  2. [POI]Utiliser des modèles de document, c'est possible ?
    Par hugo123 dans le forum Documents
    Réponses: 5
    Dernier message: 04/09/2006, 13h52
  3. Réponses: 3
    Dernier message: 13/09/2005, 13h21
  4. [Eclipse 2.1.2] Créer un modèle de document/fichier
    Par iubito dans le forum Eclipse Platform
    Réponses: 1
    Dernier message: 26/01/2005, 12h47
  5. Comment réaliser des modèles de documentations avec XML ?
    Par Dams76 dans le forum XML/XSL et SOAP
    Réponses: 6
    Dernier message: 29/08/2003, 03h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo