how avoid memory leaks?
from here: http://www.winprog.org/tutorial/bitmaps.html
i learned:

GetDC() - ReleaseDC()
BeginPaint() - EndPaint()
CreateCompatibleDC() - DeleteDC() 

i must get the old selected object. select it when isn't needed and then delete it.
so seen these constructor and desctructor:

image(const int width, const int height)
    {
        if (isimgused==true)
            delete img;
        isimgused=false;
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        SelectObject(hdcimage, obj);
        DeleteObject(btBitmap);
        DeleteObject(obj);
        DeleteDC(hdcimage);
        hdcimage = CreateCompatibleDC(NULL);
        btBitmap = CreateBitmap(width,height,1,32,NULL);
        obj = SelectObject(hdcimage, btBitmap);
        framecount=1;
        imageheight=height;
        imageweight=width;
    }

~image()
    {
        if(isimgused==true)
            delete img;
        if(isGDIPLUSIniciated==true)
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
        SelectObject(hdcimage, obj);
        DeleteObject(btBitmap);
        DeleteDC(hdcimage);
    }

and these function:

void DrawHICONtoHDC(HDC hdc, HICON hIcon, int PosX=0, int PosY=0)
{
    BITMAP BMInf;
    ICONINFO    csII;
    GetIconInfo(hIcon, &csII);
    GetObject(csII.hbmColor, sizeof(BMInf), &BMInf);
    HDC MemDCExercising = CreateCompatibleDC(hdc);
    HBITMAP hBitmap=CreateBitmap(BMInf.bmWidth ,BMInf.bmHeight,1,32,0);
    HBITMAP oldbitmap =(HBITMAP) SelectObject(MemDCExercising, hBitmap);
    DrawIcon(MemDCExercising,0,0,hIcon);
    TransparentBlt(hdc, PosX, PosY, BMInf.bmWidth , BMInf.bmHeight, MemDCExercising, 0, 0,BMInf.bmWidth , BMInf.bmHeight,GetPixel(MemDCExercising,BMInf.bmWidth-1,BMInf.bmHeight-1) );
    SelectObject(MemDCExercising,oldbitmap);
    DeleteDC(MemDCExercising);
    DeleteObject(oldbitmap);
    ::DeleteObject(csII.hbmColor);
    ::DeleteObject(csII.hbmMask);
    DestroyIcon(hIcon);
    DeleteObject(hBitmap);
}

what i'm doing wrong?
from a windows tool: the HDC, HBITMAP, HPEN, HBRUSH continue been created, instead delete the old one when isn't needed

Recommended Answers

All 3 Replies

Please show the entire image class definition.

heres the entire class:

class image
{
private:
    ULONG_PTR m_gdiplusToken;
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    HDC hdcimage=CreateCompatibleDC(NULL);
    HGDIOBJ obj=NULL;
    HBITMAP btBitmap=NULL;
    Image *img;
    bool isimgused=false;
    bool isGDIPLUSIniciated=false;
    int imageheight=0;
    int imageweight=0;
    int framecount=0;
    int intSelectFrame=0;
    int framedelay=0;
    string strfilename="";
    Gdiplus::Color clrBackColor=Gdiplus::Color::Transparent;
    HDC hdcwindow;
    bool blnTransparent=true;

    void readimagefile(string filename)
    {
        if (isimgused==true)
            delete img;
        strfilename=filename;
        if(toupper(filename[filename.size()-3])=='C' && toupper(filename[filename.size()-2])=='U' && toupper(filename[filename.size()-1])=='R')
        {
            isimgused=false;
            //create the transparent icon handle
            HCURSOR hicon = (HCURSOR)LoadImage(NULL, filename.c_str(), IMAGE_CURSOR, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE|LR_LOADTRANSPARENT);
            ICONINFO ii;
            BOOL fResult = GetIconInfo(hicon, &ii);
            if (fResult)
            {
                BITMAP bm;
                fResult = GetObject(ii.hbmMask, sizeof(bm), &bm) == sizeof(bm);
                if (fResult)
                {
                    imageweight= bm.bmWidth;
                    imageheight= ii.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
                }
                if (ii.hbmMask) DeleteObject(ii.hbmMask);
                if (ii.hbmColor) DeleteObject(ii.hbmColor);
            }
            btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
            obj = SelectObject(hdcimage, btBitmap);//add the bitmap to memory DC
            DrawIconEx(hdcimage,0,0,hicon,imageweight,imageheight,0,0,DI_NORMAL);//draw the icon to DC with right size
            //seems the DrawIcon(), always, draw it with 32X32 size
            framecount=1;
            DestroyCursor(hicon);
        }
        else
        {
            isimgused=true;
            Gdiplus::Image img2(towstring(filename).c_str());
            imageweight=img2.GetWidth();
            imageheight=img2.GetHeight();
            btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);
            obj = SelectObject(hdcimage, btBitmap);
            Gdiplus::Graphics graphics(hdcimage);
            graphics.DrawImage(&img2, 0,0,imageweight,imageheight);

            UINT count = 0;
            count = img2.GetFrameDimensionsCount();
            GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);
            img2.GetFrameDimensionsList(pDimensionIDs, count);
            framecount=img2.GetFrameCount(&pDimensionIDs[0]);
            framedelay =img2.GetPropertyItemSize(PropertyTagFrameDelay);
            img=new Image(towstring(filename).c_str());
            isimgused=true;
            free(pDimensionIDs);
        }
    }

    HICON HICONFromHBITMAP(HBITMAP bitmap)
    {
        BITMAP bmp;
        GetObject(bitmap, sizeof(BITMAP), &bmp);
        HBITMAP hbmMask = CreateCompatibleBitmap(GetDC(NULL), bmp.bmWidth, bmp.bmHeight);

        ICONINFO ii = {0};
        ii.fIcon    = TRUE;
        ii.hbmColor = bitmap;
        ii.hbmMask  = hbmMask;

        HICON hIcon = CreateIconIndirect(&ii);
        DeleteObject(hbmMask);

        return hIcon;
    }

public:

    image()
    {
        if (isimgused==true)
            delete img;
        isimgused=false;
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }

        btBitmap=CreateCompatibleBitmap(hdcimage,1,1);
        obj = SelectObject(hdcimage, btBitmap);
        imageheight=1;
        imageweight=1;
    }

    image(HDC hdcWindow)
    {
        if (isimgused==true)
            delete img;
        isimgused=false;
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        hdcwindow=hdcWindow;
    }

    image(const int width, const int height)
    {
        if (isimgused==true)
            delete img;
        isimgused=false;
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        SelectObject(hdcimage, obj);
        DeleteObject(btBitmap);
        DeleteObject(obj);
        DeleteDC(hdcimage);
        hdcimage = CreateCompatibleDC(NULL);
        btBitmap = CreateBitmap(width,height,1,32,NULL);
        obj = SelectObject(hdcimage, btBitmap);
        framecount=1;
        imageheight=height;
        imageweight=width;
    }

    image( const string & filename)
    {
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        readimagefile(filename);
    }

    image (const image &cSource)
    {
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        readimagefile(cSource.strfilename);
        BitBlt(hdcimage,0,0,imageweight,imageheight,cSource.hdcimage,0,0,SRCCOPY);
    }

    image& operator= (const image &cSource)
    {
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        readimagefile(cSource.strfilename);
        BitBlt(hdcimage,0,0,imageweight,imageheight,cSource.hdcimage,0,0,SRCCOPY);
        return *this;
    }

    property <int> SelectFrame
    {
        Get(int)
        {
            return intSelectFrame;
        },
        Set(int selectframe)
        {
            if(intSelectFrame<0)
                intSelectFrame=0;
            else if (intSelectFrame>=framecount)
                intSelectFrame=framecount-1;
            else
                intSelectFrame=selectframe;

            UINT count = 0;
            count = img->GetFrameDimensionsCount();

            GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);
            img->GetFrameDimensionsList(pDimensionIDs, count);
            img->SelectActiveFrame(&pDimensionIDs[0],intSelectFrame);
            Gdiplus::Graphics graphics(hdcimage);
            graphics.Clear(clrBackColor);
            graphics.DrawImage(img, 0, 0, imageweight, imageheight);
            free(pDimensionIDs);
        }
    };

    void getImageFromResource(string strResourceName)
    {
        HGLOBAL hGlobal;
        LPSTREAM pStream;

        HRSRC hRsrc = FindResource(NULL, strResourceName.c_str(), RT_RCDATA);
        HGLOBAL hGlob1 = LoadResource(NULL, hRsrc);
        int size = SizeofResource(NULL, hRsrc);
        hGlobal = GlobalAlloc(GMEM_FIXED, size);
        LPVOID resPtr = LockResource(hGlob1);
        memcpy(hGlobal, resPtr, size);
        FreeResource(hGlobal);

        CreateStreamOnHGlobal(hGlobal, true,&pStream);
        img = new Image(pStream, false);
    }

    int GetLastImageError()
    {
        return img->GetLastStatus();
    }

    void RePaint(bool blackandwhite=true)
    {
        //clean the hdc
        Gdiplus::Graphics graphics(hdcimage);
        graphics.Clear(clrBackColor);

        //draw image to hdc
        graphics.DrawImage(img, 0, 0, img->GetWidth(), img->GetHeight());

        BITMAPINFO bitmap_info;
        color ave_color;
        int bytes_per_scanLine;
        int pad_per_scanLine;
        int X;
        int Y;

        //add values to bitmap_info
        bitmap_info.bmiHeader.biSize = 40;
        bitmap_info.bmiHeader.biWidth = img->GetWidth();
        bitmap_info.bmiHeader.biHeight = -img->GetHeight();
        bitmap_info.bmiHeader.biPlanes = 1;
        bitmap_info.bmiHeader.biBitCount = 32;
        bitmap_info.bmiHeader.biCompression = BI_RGB;
        bytes_per_scanLine = ((((bitmap_info.bmiHeader.biWidth * bitmap_info.bmiHeader.biBitCount) + 31) / 32) * 4);
        pad_per_scanLine = bytes_per_scanLine - (((bitmap_info.bmiHeader.biWidth * bitmap_info.bmiHeader.biBitCount) + 7) / 8);
        bitmap_info.bmiHeader.biSizeImage = bytes_per_scanLine * abs(bitmap_info.bmiHeader.biHeight);

        //prepared for recive the pixels
        BYTE pixels[3][img->GetWidth()]  [img->GetHeight()];
        GetDIBits (hdcimage,btBitmap , 0, img->GetHeight(), &pixels, &bitmap_info, DIB_RGB_COLORS);

        //grayscale the pixels
        for (Y = 0; Y< img->GetHeight()-1; Y++)
        {
            for (X = 0; X< img->GetWidth()-1; X++)
            {
                if(blackandwhite==true)
                {
                    ave_color = (pixels[0] [X] [Y] + pixels[1] [X] [Y] + pixels[2] [X] [Y]) / 3;
                    pixels[0] [X] [Y] = ave_color;
                    pixels[1] [X] [Y] = ave_color;
                    pixels[2] [X] [Y] = ave_color;
                }
            }
        }
        //save the new pixels on btBitmap
        SetDIBits(hdcimage,btBitmap , 0, img->GetHeight(), &pixels, &bitmap_info, DIB_RGB_COLORS);
    }

    property<int> FramesCount
    {
        Get(int)
        {
            return framecount;
        }
    };

    property<int> FrameDelay
    {
        Get(int)
        {
            return framedelay;
        }
    };

    property<string> FileName
    {
        Get(string)
        {
            return strfilename;
        },
        Set(string filename)
        {
            readimagefile(filename);
        }
    };

    property<Gdiplus::Color> Backcolor
    {
        Get(Gdiplus::Color)
        {
            return clrBackColor;
        },
        Set(Gdiplus::Color bkcolor)
        {
            clrBackColor = bkcolor;
            SetDCBrushColor(hdcimage,clrBackColor.ToCOLORREF());
        }
    };

    void draw(HDC control)
    {
        //if (clrBackColor.GetValue() == Gdiplus::Color::Transparent)
        if (clrBackColor.GetValue()== Gdiplus::Color::Transparent)
        {
            TransparentBlt(control, 0, 0,width(),height(),hdcimage, 0, 0,width(), height(), GetPixel(hdcimage,width()-1,height()-1));
        }
        else
        {
            BitBlt(control,0,0,width(),height(),hdcimage,0,0,SRCCOPY);
        }
        //InvalidateRect(WindowFromDC(control),NULL,false);
    }

    operator string()
    {
        return strfilename;
    }

    operator HICON()
    {
        return HICONFromHBITMAP(btBitmap);
    }

    operator HBITMAP()
    {
        return btBitmap;
    }

    int height()
    {
        return imageheight;
    }

    int width()
    {
        return imageweight;
    }

    operator HDC()
    {
        return hdcimage;
    }

    bool operator != ( nullptr_t ) const
    {
        return btBitmap != nullptr;
    }

    bool operator==(const image &other) const
    {
        return (other.btBitmap == this->btBitmap);
    }

    bool operator!=(const image &other) const
    {
        return !(*this == other);
    }

    bool haveimage()
    {
        if(btBitmap==NULL)
            return false;
        else
            return true;
    }

    ~image()
    {
        if(isimgused==true)
            delete img;
        if(isGDIPLUSIniciated==true)
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
        SelectObject(hdcimage, obj);
        DeleteObject(btBitmap);
        DeleteDC(hdcimage);
    }
};

I'm using Valgrind or Deleaker for such cases. Any GDI leaks profiler will help you. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.