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 :

[VC++6]Créations de fenêtres et objets GDI


Sujet :

MFC

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut [VC++6]Créations de fenêtres et objets GDI
    Salut,

    Je faisais quelques petits tests.

    Pour celà, j'ai créé un classe dérivée de CWnd. Et dans ma view principale, je déclare une instance de cette classe.

    Sous un bouton de tests, je lance le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (!m_wndTest.m_hWnd)
    		m_wndTest.CreateEx(WS_EX_OVERLAPPEDWINDOW, AfxRegisterWndClass(NULL,NULL, NULL, NULL), "MyWnd", WS_VISIBLE, CRect(0,0,200,200), this, NULL);
    Alors, je lance mon appli, et je regarde le nombre d'objets GDI. Je crée une première fois ma fenêtre en appuyant sur le bouton. Le nombre d'objets GDI augmente de 2. Je ferme la fenêtere créée. Le nombre d'objets GDI ne diminue pas de 2. (au contraire, il reste stable)
    Je rappuie sur le bouton pour crééer ma fenêtre et cette fois ci, le nombre d'objets GDI augmente de 5. En fermant la fenêtre, pas de diminution. Puis à chaque création, ce nombre augmente de 5... ad vitam eternam.

    Bref, il y aune fuite de mémoire GDI dans mon programme.

    Est ce normal? D'où vient elle? Puis je l'éliminer?

  2. #2
    Membre du Club
    Inscrit en
    Octobre 2002
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Octobre 2002
    Messages : 39
    Points : 40
    Points
    40
    Par défaut
    faudra peut etre detruire la fenetre que t'as cree via
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_wndTest.DestroyWindow()
    avant de creer la nouvelle

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    JE le mets ou ce DestroyWindow?

    Bref, j'ai essayé de le mettre dans ma procdure de test, juste avant le test if, mais ça ne change rien.

    Cad que je fais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    m_wndTest.DestroyWindow();
    if (!m_wndTest.m_hWnd) 
          m_wndTest.CreateEx(WS_EX_OVERLAPPEDWINDOW, AfxRegisterWndClass(NULL,NULL, NULL, NULL), "MyWnd", WS_VISIBLE, CRect(0,0,200,200), this, NULL);

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Alors, pour info, lorsque je crée une fenêtre de la sorte:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_wndTest.Create(AfxRegisterWndClass(0,NULL, NULL, NULL), "MyWnd", WS_VISIBLE, CRect(0,0,200,200), this, 2000);
    cad une fenêtre ayant ma view principale comme parent, je n'ai plus ces pertes mémoire GDI.

    Vraiment étonnant...

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Punaise, je n'arrive vraiment pas à comprendre pourquoi cette fuite de mémoire GDI.

    En fait, même avec le code suivant il y a une fuite de mémoire GDI:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_wndTest.CreateEx(0, AfxRegisterWndClass(0,NULL, NULL, NULL), "MyWnd", WS_VISIBLE, CRect(0,0,200,200), NULL, NULL);
    Je ne pense pas que l'on puisse faire plus simple comme fenêtre.

    En fait, la mémoire fuit du moment que la fenêtre est rendue visible. Sinon, si je ne la rends pas visible, et la détruis par la suite, aucune fuite mémoire.

    Vraiment bizarre...

  6. #6
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    Citation Envoyé par Yoyo@
    Alors, pour info, lorsque je crée une fenêtre de la sorte:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_wndTest.Create(AfxRegisterWndClass(0,NULL, NULL, NULL), "MyWnd", WS_VISIBLE, CRect(0,0,200,200), this, 2000);
    cad une fenêtre ayant ma view principale comme parent, je n'ai plus ces pertes mémoire GDI.

    Vraiment étonnant...
    c'est comme ça que je procede ...
    avec le type WS_CHILD en plus .

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par farscape
    c'est comme ça que je procede ...
    avec le type WS_CHILD en plus .
    Bah tu devrais toi aussi avoir des fuites mémoire je viens d'essayer de rajouter le style WS_CHILD, qui fait que la fenêtre est limitée dans son mouvement à la fenêtre parent. (mais on peut la déplacer grace au WS_CAPTION)

    Est ce que tu pourrais essayer d'en créer et d'en détruire plusieurs de la sorte, histoire de voir si tu as des fuites mémoire?

    Je suis maintenant quasiment convaincu que les fuites mémoire proviennet du WS_CAPTION, car quand je l'enlève, alors je n'en ai plus (mais je ne peux plus déplacer ma fenêtre)

  8. #8
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    hum ,
    pourquoi tu parles de WS_CAPTION ?
    moi je fais ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_pWnd->Create(NULL,NULL,WS_CHILD|WS_VISIBLE,rect,pParent,id);
    moi en fait je crée ce genre de fenetre pour une zone de travail interne .
    que veux tu faire exactement ?


  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Bah mon but est de créer une fenêtre quelconque extern, que je puisse déplacer à ma guise avec ma souris.

    Je tiens vraiment à ce que ce soit une fenêtre issue de ma propre classe, et non pas un Dialog ou autre.

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Bon, visiblement, mon post ne suscite pas beaucoup de solution, mais quand même, pour ma part, j'en ai trouvé une, et j'ai aussi trouvé le début du pourquoi. A force d'étudier ce qu'il se passe sous mes fenêtres, la gestion des classes par MFC, etc, j'ai fini par avoir une idée:

    Redéfinir mon propre AfxRegisterWndClass comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    LPCTSTR AFXAPI AfxMyRegisterWndClass(UINT nClassStyle,
    	HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)
    {
    	// Returns a temporary string name for the class
    	//  Save in a CString if you want to use it for a long time
    	LPTSTR lpszName = AfxGetThreadState()->m_szTempClassName;
     
    	// generate a synthetic name for this class
    	HINSTANCE hInst = AfxGetInstanceHandle();
    	if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
    		wsprintf(lpszName, _T("Afx:%x:%x"), (UINT)hInst, nClassStyle);
    	else
    		wsprintf(lpszName, _T("Afx:%x:%x:%x:%x:%x"), (UINT)hInst, nClassStyle,
    			(UINT)hCursor, (UINT)hbrBackground, (UINT)hIcon);
     
    	// see if the class already exists
    	WNDCLASS wndcls;
    	if (::GetClassInfo(hInst, lpszName, &wndcls))
    	{
    		// already registered, assert everything is good
    		ASSERT(wndcls.style == nClassStyle);
     
    		// NOTE: We have to trust that the hIcon, hbrBackground, and the
    		//  hCursor are semantically the same, because sometimes Windows does
    		//  some internal translation or copying of those handles before
    		//  storing them in the internal WNDCLASS retrieved by GetClassInfo.
    		return lpszName;
    	}
     
    	// otherwise we need to register a new class
    	wndcls.style = nClassStyle;
    	wndcls.lpfnWndProc = AfxWndProc;
    	wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
    	wndcls.hInstance = hInst;
    	wndcls.hIcon = hIcon;
    	wndcls.hCursor = hCursor;
    	wndcls.hbrBackground = hbrBackground;
    	wndcls.lpszMenuName = NULL;
    	wndcls.lpszClassName = lpszName;
    	if (!AfxRegisterClass(&wndcls))
    		AfxThrowResourceException();
     
    	// return thread-local pointer
    	return lpszName;
    }
    La sule déifférence vient de cette ligne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wndcls.lpfnWndProc = AfxWndProc;
    au lieu de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wndcls.lpfnWndProc = DefWndProc;
    Je ne comprends pas exactement pourquoi ça marche, mais au moins, ça marche...

  11. #11
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut,
    tu as essayé comme dans mon exemple en mettant null ?

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Nan, je n'avais pas essayé, donc, j'ai essayé...

    Mais ça me fait un Debg Assertion Failure.

    En y regardant de plus près, voici le code de PreCreateWindow:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs)
    {
    	if (cs.lpszClass == NULL)
    	{
    		// make sure the default window class is registered
    		VERIFY(AfxDeferRegisterClass(AFX_WND_REG));
     
    		// no WNDCLASS provided - use child window default
    		ASSERT(cs.style & WS_CHILD);
    		cs.lpszClass = _afxWnd;
    	}
    	return TRUE;
    }
    Bref, on voit bien que si l'on ne fournit pas de nom de classe, alors ça ne marche que si la fenêtre que l'on veut créer a le style WS_CHILD, ce qui n'est pas mon cas...

  13. #13
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    re,
    apres une petite recherche dans les codes que je j'utilise ,
    dans le cas d'une fenetre de style popup pour simuler un tooltip voila comment j'ai declaré ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    CString szClassName = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS, 
                                                  LoadCursor(NULL, IDC_ARROW));
     
        if (!CWnd::CreateEx(WS_EX_TOPMOST, szClassName, _T(""), 
                            WS_POPUP, 
                            0, 0, 10, 10, 
                            pParentWnd->GetSafeHwnd(), 0, NULL))
        {
            return FALSE;
        }
    CS_SAVEBITS peut etre enlevé il permet ici de disposer d'un mecanisme de sauvegarde ecran geré par le systeme,donc utile pour un popup comme un tooltipctrl.

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    D'accord!

    Mais mon but est d'avoir une fenêtre que je puisse déplacer à la souris. Donc, il me faut un WS_CAPTION.

    Donc, j'ai utilisé le même code que toi, mais avec WS_CAPTION en plus, et là, bien sûr: fuites mémoire GDI. (comme je le disais plus haut: c'est le WS_CAPTION qui semble causer ces fuites)

    Ca me parait vraiment inextricable (et inexplicable!) comme problème... Pourtant, les données du problème sont simples !

  15. #15
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    hum j'ai jamais eu besoin besoin de creer une fenetre de ce style,

    le cas echeant je creerais une dialog non modale sans ressources.
    a tout hasard ,dans le post it faq j'ai mis un code pour dialog modale sans ressources.
    il suffit de modifier la fonction d'initialisation pour passer en non modale.
    http://www.developpez.net/forums/vie...810922#1810922

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Bah oui, je sais bien que je peux passer par un Dialog.

    Mais bon, je trouve ça quand même assez fou que je ne puisse pas créer une fenêtre indépendante "à la main", de manière simple, que je puisse ensuite déplacer à la souris.

    Enfin, si, je peux le faire, mais en voyant mon compteur GDI augmenter à chaque création/destruction de fenêtre...

  17. #17
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    une dialogue oui ,mais sans ressources en dynamique ...

  18. #18
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Bon, ca marche très bien avec un Dialog. J'ai pas essayé la version non modae, mais bon, je vois très bien comment parvenir à mes fins. J'iame bien cette "construction" à la main, on voit bien ce qu'on fait!

    Mais quand même, n'empêche, je n'arrive pas à croire qu'on ne puissse créer nous mêmes notre fenêtre "extérieure" à la main. Ca ne vous interpelle pas plus que ça? Qu'il y ait ces fuites d'objets GDI? (sauf à utiliser la solution alambiquée que j'ai trouvée...

    Et pourquoi le probleme ne vient que l'orsqu'il y a une Caption?

    Qu'est ce qui constitue les objets GDI d'une fenêtre?

  19. #19
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    Citation Envoyé par Yoyo@
    Bon, ca marche très bien avec un Dialog. J'ai pas essayé la version non modae, mais bon, je vois très bien comment parvenir à mes fins. J'iame bien cette "construction" à la main, on voit bien ce qu'on fait!

    Mais quand même, n'empêche, je n'arrive pas à croire qu'on ne puissse créer nous mêmes notre fenêtre "extérieure" à la main. Ca ne vous interpelle pas plus que ça? Qu'il y ait ces fuites d'objets GDI? (sauf à utiliser la solution alambiquée que j'ai trouvée...

    Et pourquoi le probleme ne vient que l'orsqu'il y a une Caption?

    Qu'est ce qui constitue les objets GDI d'une fenêtre?
    si si il faudrait creuser la chose (et avoir un peu de temps) ,et voir comment en win32 on crée une fenetre de ce style.
    jusqu'à present je n'ai eu besoin de creer que des fenetres child ,pour le reste je passe par la dialog template modale ou non modale.


  20. #20
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 79
    Points : 17
    Points
    17
    Par défaut
    Tiens, c'est vrai, ce n'est pas une mauvaise idée: je pourrais dans un premier temps tester avec des fenêtres Win32.

    Tu vois, on a trouvé une solution intemédiaire (avec les Dialog) mais néanmoins, je n'iame pas ne pas aller au fond des choses. Et c'est justement en se battant sur des petits détails qu'on avance.

    Bref, je vais partir 1 semaine en vacances, mais quoiqu'il advienne, je vais continuer à creuser la chose.

    Est ce que tu as une idée des objets GDI qui sont créés avec la fenêtre? D'ailleurs, pour info, ces objets n'apparaissent que quand la fenêtre est rendue visible!

Discussions similaires

  1. Problème avec création de fenêtre dynamique
    Par FredericB dans le forum C++Builder
    Réponses: 3
    Dernier message: 29/09/2005, 17h21
  2. [MFC + Win32] Création de fenêtre
    Par nmarf dans le forum MFC
    Réponses: 2
    Dernier message: 05/07/2005, 10h25
  3. Création de fenêtres sans icone dans la barre des taches
    Par bruce_will dans le forum Windows
    Réponses: 2
    Dernier message: 06/12/2004, 04h29
  4. [MFC] libération des objets GDI's
    Par Kevgeii dans le forum MFC
    Réponses: 5
    Dernier message: 01/02/2004, 10h37
  5. Problème de création de fenêtre
    Par tomateauketchup dans le forum DirectX
    Réponses: 1
    Dernier message: 08/06/2003, 19h42

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