2017-08-08 14 views
0

Je vois un problème où je ne peux pas sélectionner à nouveau le bitmap d'origine sur un contrôleur de domaine, provoquant une fuite de mémoire. Le pointeur sur le bitmap d'origine est resté le même tout au long du programme, mais les données (de CBitmap :: GetBitmap) passent de monochrome à autre chose. Je ne sais pas quand le bitmap change réellement, mais quelque chose dans le système le cause.GDI: les modifications de bitmap DC d'origine ne peuvent pas être restaurées

CBitmap* cMyClass::mpOldBitmap; 
CDC cMyClass::mCanvasDc; 
CBitmap cMyClass::mCanvasBmp; 

void cMyClass::Init() 
{ 
    // One-time initialization 
    CDC* pDc = GetDC(); 
    mCanvasDc.CreateCompatibleDC(pDc); 
    mCanvasBmp.CreateCompatibleBitmap(pDc, 10, 10); 
    mpOldBitmap = mCanvasDc.SelectObject(&mCanvasBmp); 
    ReleaseDC(pDc); 

    BITMAP bitmap; 
    mpOldBitmap->GetBitmap(&bitmap); // A monochrome bitmap, as expected. 
} 

void cMyClass::Recreate(int newW, int newH) 
{ 
    // 1. Delete existing bitmap: 
    if (mpOldBitmap) 
    { 
     BITMAP bitmap; 
     mpOldBitmap->GetBitmap(&bitmap); // This is no longer the monochrome bitmap. It is 8bpp, with random size. 

     CBitmap* pCurrBmp = mCanvasDc.SelectObject(mpOldBitmap); // This fails (NULL). I can't de-select my bitmap. 
     mCanvasBmp.DeleteObject(); // This fails too, causing memory leak. Actually, it fails in CE6, but not in Win32. Regardless, both platforms will have a memory leak. 
    } 

    // 2. Recreate the bitmap with new size: 
    { 
     CDC* pDc = GetDC(); 
     mCanvasBmp.CreateCompatibleBitmap(pDc, newW, newH); 
     ReleaseDC(pDc); 
    } 

    // 3. Finalize 
    mpOldBitmap = mCanvasDc.SelectObject(&mCanvasBmp); 
} 
  1. Tous les scénarios connus où cela peut se produire?
  2. Des conseils de débogage à interrompre lorsque les données bitmap changent?

Remarque: Dans le code, j'ai mentionné "cela échoue". Je supprime le assert sur les valeurs retournées pour rendre le code lisible.


Edit: La solution que j'utilise pour le fixer est d'utiliser CDC: SaveDC et CDC :: RestoreDC au lieu de stashing le pointeur. La fuite de mémoire a disparu, et chaque appel GDI est passé. Mais je suis toujours curieux de savoir pourquoi le code original a fui. Le pointeur vers le bitmap par défaut, autant que je sache, devrait être un bitmap monochrome par défaut qui est probablement global dans le monde GDI

+1

[mcve] requis. – IInspectable

+0

Je pense que votre problème est que vous ne pouvez pas manipuler (recréer) une variable d'instance comme celle-ci. Vous avez besoin d'un pointeur vers CBitmap, c'est-à-dire CBitmap * mCanvasBmp et le "supprimer" et le recréer comme mCanvasBmp = new CBitmap à chaque fois. – VuVirt

Répondre

-1

Voyons le code de OP.

mpOldBitmap = mCanvasDc.SelectObject(mCanvasBmp); 

Parce que mCanvasBmp est un objet CBitmap (pas un pointeur vers CBitmap), est d'abord appelé l'opérateur HGDIOBJ, puis CDC :: SelectObject (HGDIOBJ) qui retourne HGDIOBJ et non CBitmap *. Cela devrait donner une erreur de compilateur de conversion. Si vous convertissez la valeur retournée en CBitmap *, c'est également faux.

La meilleure façon de se débarrasser d'un problème consiste à passer un pointeur.

mpOldBitmap = mCanvasDc.SelectObject(& mCanvasBmp); 

Cette affaire sera appelée CDC :: SelectObject (CBitmap * pBitmap) qui retourne un CBitmap *.

// J'espère que c'est assez clair. :)

+0

Désolé, c'était une faute de frappe de ma part en essayant de simplifier le code pour SO. J'ai corrigé la description. J'ai également ajouté la solution que j'ai trouvée, mais je suis toujours curieux de savoir pourquoi l'original n'a pas fonctionné. – Ryuu