win32 - GDI: why the HDC\HBITMAP aren't destroyed?

i'm doing an image class. but seems the HBITMAP and HDC's aren't deleted and i don't understand why :(
see these part of my class:
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
class image
{
private:
    ULONG_PTR m_gdiplusToken;
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    HDC hdcimage=CreateCompatibleDC(NULL);
    HGDIOBJ PreviousBitmap=NULL;
    HBITMAP CurrentBitmap=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);
            }
            CurrentBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
            PreviousBitmap = SelectObject(hdcimage, CurrentBitmap);//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();
            CurrentBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);
            PreviousBitmap = SelectObject(hdcimage, CurrentBitmap);
            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);
        }
    }

public:

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

        CurrentBitmap=CreateCompatibleBitmap(hdcimage,1,1);
        PreviousBitmap = SelectObject(hdcimage, CurrentBitmap);
        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;
        }
        CurrentBitmap = CreateBitmap(width,height,1,32,NULL);
        PreviousBitmap = SelectObject(hdcimage, CurrentBitmap);
        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> 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 <int> SelectFrame
    {
//get function
        Get(int)
        {
            return intSelectFrame;
        },
//set function
        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);
        }
    };

~image()
    {
        if(isimgused==true)
            delete img;
        if(isGDIPLUSIniciated==true)
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
        if(SelectObject(hdcimage, PreviousBitmap)==NULL)
            MessageBox(NULL, "error", "SelectObject", MB_OK);
        if(DeleteObject(CurrentBitmap)==FALSE)
            MessageBox(NULL, "error", "DeleteObject", MB_OK);
        if(DeleteDC(hdcimage)==FALSE)
            MessageBox(NULL, "error", "DeleteDC", MB_OK);
    }
};

why the HDC\HBITMAP aren'd deleted?
(using task manager i see my class eating more and more memory and see the GDI count objects growing)
Last edited on
Are you sure all your objects are being destroyed?

Do you invoke readimagefile() multiple times on an object? It doesn't seem to free resources before (re)creating them.
doing a new HBITMAP and HDC class's, i resolve 99% of problems:
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
class MemoryDC
{
private:
    HDC memoryDC;

public:
    MemoryDC ()
    {
        memoryDC=CreateCompatibleDC(NULL);
    }

    operator HDC() const
    {
        return memoryDC;
    }

    ~MemoryDC ()
    {
       DeleteDC(memoryDC);
    }
};

class BitmapDC
{
private:
    MemoryDC hdcbitmap;
    HGDIOBJ bitmapold;
    HBITMAP bitmapcurrent;
    int intwidth;
    int intheight;

    void init(int width, int height)
    {
        bitmapcurrent = CreateBitmap(width, height, 1, 32, NULL);
        bitmapold = SelectObject(hdcbitmap, bitmapcurrent);
        intwidth=width;
        intheight=height;
    }

    void destroy()
    {
        SelectObject(hdcbitmap, bitmapold);
        DeleteObject(bitmapcurrent);
    }

public:

    BitmapDC(int width, int height)
    {
        init(width, height);
    }

    BitmapDC()
    {
        init(1, 1);
    }

    void size(int width, int height)
    {
        destroy();
        init(width, height);
    }

    int Width()
    {
        return intwidth;
    }

    int Height()
    {
        return intheight;
    }

    BitmapDC& operator= (const BitmapDC &bitmapsource)
    {
        if (this == &bitmapsource)      // Same object?
            return *this;
        destroy();
        init(bitmapsource.intwidth, bitmapsource.intheight);
        BitBlt(bitmapsource, 0, 0, intwidth, intheight, bitmapsource, 0, 0, SRCCOPY);
        return *this;
    }

    BitmapDC& operator= (const HBITMAP &bitmapsource)
    {
        destroy();
        BITMAP bm;
        GetObject(bitmapsource,sizeof(bm),&bm);
        init(bm.bmWidth, bm.bmHeight);
        DrawHBITMAPtoHDC(bitmapsource,hdcbitmap);
        return *this;
    }

    //testing the bitmao value if is nullptr
    bool operator != ( nullptr_t ) const
    {
        return bitmapcurrent != nullptr;
    }

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

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

    operator HBITMAP() const
    {
        return bitmapcurrent;
    }

    operator HDC() const
    {
        return hdcbitmap;
    }

    ~BitmapDC()
    {
       destroy();
    }
};

but slowly, the memory used is increasing :(
and i don't know why :(
please some advice?
the problem is about the joysticks functions. but i will do a new thread
Topic archived. No new replies allowed.