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

Windows Forms Discussion :

Problème de mémoire avec Bitmap (c++/cli)


Sujet :

Windows Forms

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Janvier 2005
    Messages : 93
    Points : 64
    Points
    64
    Par défaut Problème de mémoire avec Bitmap (c++/cli)
    Bonjour à tous ,
    Voilà, je suis débutant et je travaille sur un projet avec les winforms en c++/cli ,
    Je cherche à afficher une capture d'écran dans un(e) pictureBox, pour cela , j'utilise le code trouvé sur la faq de developpez.com :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
    pictureBox1->Image = safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
    Le hic , c'est que lorsque je souhaite par exemple mettre ce code dans une boucle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    public : Bitmap^ screen;
    .....
     for(int i=0;i<100;i++){
    System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
    screen=safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
    pictureBox1->Image=screen;
    			 }
    Là je vois la mémoire qu'utilise le programme augmente de manière très inquiétante, ca ne le fait pas planter mais bon c'est génant ,

    Ma question est la suivante: comment cela se fait que ayant déclarer une seule fois le Bitmap qui va "recevoir" la capture d'écran (ici screen) la mémoire utilisé continue à augmenter ?
    Sinon, ne dois je pas faire une libération de ressource quelque part ?

    Merci à tous ,

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    A chaque passage dans la boucle, tu fais une nouvelle copie d'écran, et tu la récupères dans un Bitmap... donc c'est un peu normal que la mémoire utilisée augmente. Le fait de ne déclarer qu'une fois le Bitmap ne change rien à l'affaire : la variable screen n'est qu'une référence vers une instance de Bitmap, et à chaque passage dans la boucle c'est une nouvelle instance qui est utilisée.

    Vu que tu ne conserves pas de référence vers chaque instance créée, le garbage collector passera au bout d'un moment pour "nettoyer" en récupérant la mémoire des instances inutilisées. Si tu veux forcer le passage du GC, appelle la méthode GC::Collect(). Ou mieux, tu peux appeler Dispose sur le Bitmap (dans ce cas, mets d'abord pictureBox1->Image à null)

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Janvier 2005
    Messages : 93
    Points : 64
    Points
    64
    Par défaut
    ok, donc dans le premier cas , je peux mettre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    public : Bitmap^ screen;
    .....
     for(int i=0;i<100;i++){
    System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
    screen=safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
    pictureBox1->Image=screen;
    GC::Collect();
    			 }
    en effet, ca fonctionne bien ,
    mais avec le Dispose sur le Bitmap et le null sur l'image du pictureBox, la je bloque parce que le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    pictureBox1->Image=NULL
     
    for(...){
    ...
    }
    Il aime pas du tout
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    error C2664: 'System::Windows::Forms::PictureBox::Image::set' : cannot convert parameter 1 from 'int' to 'System::Drawing::Image ^'
    donc je ne vois pas trop avec ton second conseil , tu peux m'aider ?
    Merci

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    NULL (=0) est un entier, tu ne peux pas le convertir implicitement en Bitmap^, il faut faire un cast

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    public : Bitmap^ screen;
    ...
     
    for(int i=0;i<100;i++)
    {
        System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
        if (screen != null)
        {
            pictureBox1->Image = (Bitmap^) NULL;
            screen->Dispose();
        }
        screen=safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
        pictureBox1->Image=screen;
    }

    Il vaut mieux faire un Dispose sur l'image que faire un GC::Collect (qui est assez lourd)

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Janvier 2005
    Messages : 93
    Points : 64
    Points
    64
    Par défaut
    Alors , voilà j'ai fait comme tu m'a dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for(int i=0;i<100;i++){
        System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
        if (screen != NULL){
            pictureBox1->Image = (Bitmap^) NULL;
            screen->Dispose();
        }
        screen=safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
        pictureBox1->Image=screen;
    }
    J'ai quelques erreurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    if (screen != NULL){....
    >>>> error C2446: '!=' : no conversion from 'int' to 'System::Drawing::Bitmap ^'
     
    pictureBox_Image->Image = (Bitmap^) NULL;
    >>>> error C2440: 'type cast' : cannot convert from 'int' to 'System::Drawing::Bitmap ^'
     
    screen->Dispose();
    >>>> error C2039: 'Dispose' : is not a member of 'System::Drawing::Bitmap'
    Et là je ne sais vraiment pas quoi faire , avec GC::collect(), ca fonctionne nickel mais si tu dis que c'est lourd , c'est pas la peine ,
    que dois- je faire ?

    Merci bien ,

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Ah oui, je me rappelais plus comment on spécifiait une référence nulle en C++/CLI... en fait c'est nullptr. Donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for(int i=0;i<100;i++){
        System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
        if (screen != nullptr){
            pictureBox1->Image = nullptr;
            screen->Dispose();
        }
        screen=safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
        pictureBox1->Image=screen;
    }
    Par contre, pour cette erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    'Dispose' : is not a member of 'System::Drawing::Bitmap'
    Il a fumé quoi ton compilateur ??! Je suis sûr à 200% que cette méthode existe... en fait elle n'est pas définie dans Bitmap mais dans la classe de base, Image.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Janvier 2005
    Messages : 93
    Points : 64
    Points
    64
    Par défaut
    Bon , pour le nullptr, c'est parfait , par contre j'aimerai bien qu'il fume un peu moins mon compilateur , voilà ce que j'ai avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    for(int i=0;i<10;i++){
        System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
        if (screen != nullptr){
            pictureBox1->Image = nullptr;		 
        }
        screen=safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
        pictureBox1->Image=screen;
        screen->Dispose();
    }
     
    1> error C2039: 'Dispose' : is not a member of 'System::Drawing::Bitmap'
    1> c:\windows\microsoft.net\framework\v2.0.50727\system.drawing.dll : see declaration of 'System::Drawing::Bitmap'
    1> You should invoke the destructor, '~Bitmap' instead
    que faire ?

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    ok, je crois que j'ai l'explication...
    http://msdn.microsoft.com/en-us/library/ms177197.aspx

    Citation Envoyé par MSDN
    Because the Visual C++ compiler provides support for deterministic release of resources, Visual C++ programmers should not attempt to implement the Dispose or Finalize methods.
    Je crois que la solution passe par un bon vieux delete :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for(int i=0;i<100;i++){
        System::Windows::Forms::SendKeys::SendWait("+{PRTSC}");
        if (screen != nullptr){
            pictureBox1->Image = nullptr;
            delete screen;
        }
        screen=safe_cast<Bitmap^>(Clipboard::GetDataObject()->GetData("Bitmap"));
        pictureBox1->Image=screen;
    }

    Sinon je sais pas trop...

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Janvier 2005
    Messages : 93
    Points : 64
    Points
    64
    Par défaut
    Impec', ca fonctionne nickel , merci de ton aide et de ta patience

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    ben j'ai aussi appris 2 ou 3 trucs au passage... j'utilise rarement C++/CLI donc j'ai quelques lacunes

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de mémoire avec des Bitmap
    Par Ryu2000 dans le forum Android
    Réponses: 11
    Dernier message: 06/04/2012, 11h34
  2. Problème de mémoire avec CvCreateImage
    Par kvarme63 dans le forum OpenCV
    Réponses: 3
    Dernier message: 03/07/2007, 16h44
  3. [GD] Problème de mémoire avec les grandes images en PHP
    Par bodysplash007 dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 12/04/2007, 17h02
  4. [Crystal Report]Problème de mémoire avec le moteur RDC
    Par sur_uix dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 26/05/2005, 09h09
  5. Problème de mémoire avec BDE
    Par Machuet dans le forum Bases de données
    Réponses: 3
    Dernier message: 13/07/2004, 10h11

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