heres my image 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;
    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;

    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()
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        btBitmap=CreateCompatibleBitmap(hdcimage,1,1);
        obj = SelectObject(hdcimage, btBitmap);
        imageheight=1;
        imageweight=1;
    }

    image(HDC hdcWindow)
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        hdcwindow=hdcWindow;
    }

    image(const int width, const int height)
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        hdcimage = CreateCompatibleDC(NULL);
        btBitmap = CreateBitmap(width,height,1,32,NULL);
        obj = SelectObject(hdcimage, btBitmap);
        framecount=1;
        imageheight=height;
        imageweight=width;
    }

    image( const string & filename)
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        strfilename=filename;
        if(toupper(filename[filename.size()-3])=='C' && toupper(filename[filename.size()-2])=='U' && toupper(filename[filename.size()-1])=='R')
        {
            //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());
            btBitmap=CreateBitmap(img2.GetWidth(),img2.GetHeight(),1,32,NULL);
            obj = SelectObject(hdcimage, btBitmap);
            Gdiplus::Graphics graphics(hdcimage);
            graphics.DrawImage(&img2, 0, 0, img2.GetWidth(), img2.GetHeight());
            imageweight=img2.GetWidth();
            imageheight=img2.GetHeight();
            UINT count = 0;
            count = img2.GetFrameDimensionsCount();
            GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);
            img2.GetFrameDimensionsList(pDimensionIDs, count);
            framecount=img2.GetFrameCount(&pDimensionIDs[0]);
            if (framecount>1)
                framedelay =img2.GetPropertyItemSize(PropertyTagFrameDelay);
            else
                framedelay =0;
            img=new Image(towstring(filename).c_str());
            free(pDimensionIDs);
        }
    }

    image (const image &cSource)
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        framecount=cSource.framecount;
        clrBackColor=cSource.clrBackColor;
        img=cSource.img->Clone();
        framedelay =img->GetPropertyItemSize(PropertyTagFrameDelay);
        imageweight=cSource.imageweight;
        imageheight=cSource.imageheight;
        strfilename=cSource.strfilename;
        btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);
        obj = SelectObject(hdcimage, btBitmap);
        BitBlt(hdcimage,0,0,imageweight,imageheight,cSource.hdcimage,0,0,SRCCOPY);
    }

    image& operator= (const image &cSource)
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        framecount=cSource.framecount;
        clrBackColor=cSource.clrBackColor;
        FileName=cSource.FileName;
        img=cSource.img->Clone();
        framedelay =img->GetPropertyItemSize(PropertyTagFrameDelay);
        imageweight=cSource.imageweight;
        imageheight=cSource.imageheight;
        strfilename=cSource.strfilename;
        btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);
        obj = SelectObject(hdcimage, btBitmap);
        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;
            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, img->GetWidth(), img->GetHeight());
            free(pDimensionIDs);
        }
    };

    void RePaint(bool blackandwhite)
    {
        //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(); Y++)
        {
            for (X = 0; X< img->GetWidth(); X++)
            {
                if(blackandwhite==true)
                {
                    ave_color = (pixels[0] [X] [Y] + pixels[1] [X] [Y] + pixels[2] [X] [Y]) / 3;
                    pixels[0] [X] [Y] = pixels[0] [X] [Y]+2;
                    pixels[1] [X] [Y] = pixels[1] [X] [Y]+2;
                    pixels[1] [X] [Y] = pixels[1] [X] [Y]+2;
                }
            }
        }
        //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)
        {
            if(isimgused==true)
                delete img;

            DeleteObject(btBitmap);
            DeleteObject(obj);
            strfilename=filename;
            if(toupper(filename[filename.size()-3])=='C' && toupper(filename[filename.size()-2])=='U' && toupper(filename[filename.size()-1])=='R')
            {
                //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
            {
                Gdiplus::Image img2(towstring(filename).c_str());
                btBitmap=CreateBitmap(img2.GetWidth(),img2.GetHeight(),1,32,NULL);
                obj = SelectObject(hdcimage, btBitmap);
                Gdiplus::Graphics graphics(hdcimage);
                graphics.DrawImage(&img2, 0,0,img2.GetWidth(),img2.GetHeight());
                imageweight=img2.GetWidth();
                imageheight=img2.GetHeight();
                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);
            }
        }
    };

    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()
    {
        Gdiplus::GdiplusShutdown(m_gdiplusToken);
        SelectObject(hdcimage, obj);
        DeleteObject(btBitmap);
        DeleteDC(hdcimage);
    }
};

heres how use it:

void Picture(image imgIcon)
    {
       imgtest=imgIcon;
       if(imgtest.FramesCount>1)//it's allawys zero
       {
           animation.Interval=imgtest.FrameDelay;
           animation.timerprocedure=[this]()
           {
                static int a;
                a=a+1;

                if(a==imgtest.FramesCount)
                    a=0;
                imgtest.SelectFrame=a;
                RECT d;
                GetClientRect(hwnd,&d);
                RedrawWindow(hwnd,&d,nullptr,RDW_UPDATENOW);

           };
           animation.Start();
       }
       else
       {
            animation.Stop();
       }
       if(blnAutoSize==true)
            setAutoSize(true);
        else if(imgtest.FramesCount==0)
            InvalidateRect(hwnd,NULL,FALSE);
    }

imgtest.FramesCount is give me, allways, zero :(
why?
but if i do these:

image test("C:\\Nova pasta\\10888212_1605526859675480_781339964_n.jpg"), test2(test);
//on main
test.FileName="C:\\Nova pasta\\007.gif";
test2=test;

works fine. but why these problem?

First of all I don't think I can tell you what is wrong to fix your current bug.. but here are a few thoughts, and I think we need to see the calling code for Picture. However, the following might help [hopefully!].

The key elements here are that your default constructor image() sets framecount to zero. Only the constructor called with a string
e.g. image test("xx.jnp"); actually sets framecount.

The call to void Picture(image imgIcon) worries me.

First, it seems you forgot to make it a const reference, e.g.
void Picture(const image& imgIcon) . That way you would avoid the double copy constructor call [I think the compiler MIGHT be able to optimise that out but not sure] as you do imgTest=imgIcon.

Next you also have no guard in the operator=. Almost ALL operator= methods should have the form:

image&
image::operator=(const image& A)
{
   if (this!=&A)
     {
       // stuff
     }
   return *this;
}

Yes that are exceptions -- BUT start with the standard form and if need be change and add a comment as to why it needed to be changed.

So in short, we need to see the call to Picture and the contruction of the object that was passed into the function Picture, if these couple of thoughts don't help.

p.s. Check the typo on line 218. you didn't mean

 pxxels[1] [X] [Y] = pixels[1] [X] [Y]+2;
 pixels[1] [X] [Y] = pixels[1] [X] [Y]+2;

it probabily should be [2] on the second line.

Comments
thanks
  • so, using my new class's, must add 'const' and adress operator?
  • thanks for that error(pixels). but i get memory errors(when i execute the program) :(

No you don't HAVE to add const, but either you should because that is what you intended [and the compiler can make you faster machine code] or it is not what you intended hence it is a bug.

However, you don't have to add const and references [note: const image& is not an address operator].

You are highly likely to get memory errors. You mix C++ style constructors with C style malloc. You have a line like this:
e.g.

img=new Image(towstring(filename).c_str());
free(pDimensionIDs);

Now when is img deleted??

There is another problem, img is not initialized in the default constructor, so you are going to call img->Clone() without the object. That is certainly going to cause problems. Initialize img to zero and then if you do make the call, you get a seg-fault at the location you messed up.

Also in the operator=(const image& cSource), you have the same line...

  img=cSource.img->Clone();

Now three things (a) img might have a value already, so you have memory leak. (b) cSource.img may be nullptr so what happens (c) if you have the equivilent to A=A, then you have undefined behaviour

Also I noticed this:

if(intSelectFrame<0)
  intSelectFrame=0;
else if (intSelectFrame>=framecount)
   intSelectFrame=framecount-1;
intSelectFrame=selectframe;

Obviously that is the same as just

 intSelectFrame=selectframe;

Your problem as posted still needs the code that actually called Picture for us to figure out.

You're invoking the copy assignment operator on a half initialised class. You've never initialised some of the variables in the other constructors that you have. By default they would be 0 or undefined.

If you call "Picture" using any one of the constructors that do NOT load a "gif", you will always have a framecount of 0.

Comments
thanks

triumphost: if so.. why i get the HDC result correct?
StuXYZ: thanks for all. it's fixed now, but i want avoid the 'const' and the '&' on Picture() function header. and yes i have several mistakes. i don't use the 'delete', because i get a memory leak too

finally i fix it, now i use the new keyword and i can delete:

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;
    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;

    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;
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        btBitmap=CreateCompatibleBitmap(hdcimage,1,1);
        obj = SelectObject(hdcimage, btBitmap);
        imageheight=1;
        imageweight=1;
    }

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

    image(const int width, const int height)
    {
        if (isimgused==true)
            delete img;
        isimgused=false;
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        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 (isimgused==true)
            delete img;
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        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());
            btBitmap=CreateBitmap(img2.GetWidth(),img2.GetHeight(),1,32,NULL);
            obj = SelectObject(hdcimage, btBitmap);
            Gdiplus::Graphics graphics(hdcimage);
            graphics.DrawImage(&img2, 0, 0, img2.GetWidth(), img2.GetHeight());
            imageweight=img2.GetWidth();
            imageheight=img2.GetHeight();
            UINT count = 0;
            count = img2.GetFrameDimensionsCount();
            GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);
            img2.GetFrameDimensionsList(pDimensionIDs, count);
            framecount=img2.GetFrameCount(&pDimensionIDs[0]);
            if (framecount>1)
                framedelay =img2.GetPropertyItemSize(PropertyTagFrameDelay);
            else
                framedelay =0;
            img=new Image(towstring(filename).c_str());
            free(pDimensionIDs);
        }
    }

    image (const image &cSource)
    {
        if (isimgused==true)
            delete img;
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        framecount=cSource.framecount;
        clrBackColor=cSource.clrBackColor;
        strfilename=cSource.strfilename;
        framedelay =cSource.framedelay;
        imageweight=cSource.imageweight;
        imageheight=cSource.imageheight;
        img=new Image(towstring(strfilename).c_str());
        btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);
        obj = SelectObject(hdcimage, btBitmap);
        BitBlt(hdcimage,0,0,imageweight,imageheight,cSource.hdcimage,0,0,SRCCOPY);
        isimgused=true;
    }

    image& operator= (const image &cSource)
    {
        if (isimgused==true)
            delete img;
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        framecount=cSource.framecount;
        clrBackColor=cSource.clrBackColor;
        strfilename=cSource.strfilename;
        framedelay =cSource.framedelay;
        imageweight=cSource.imageweight;
        imageheight=cSource.imageheight;
        img=new Image(towstring(strfilename).c_str());
        btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);
        obj = SelectObject(hdcimage, btBitmap);
        BitBlt(hdcimage,0,0,imageweight,imageheight,cSource.hdcimage,0,0,SRCCOPY);
        isimgused=true;
        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);
            //RePaint();
            free(pDimensionIDs);
        }
    };

    void getImageFromResource()
    {
        HGLOBAL hGlobal;
        LPSTREAM pStream;

        HRSRC hRsrc = FindResource(NULL, "IDR_0_1", 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);
    }

    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)
        {
            if (isimgused==true)
                delete img;
            DeleteObject(btBitmap);
            DeleteObject(obj);
            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);
            }
        }
    };

    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;
        Gdiplus::GdiplusShutdown(m_gdiplusToken);
        SelectObject(hdcimage, obj);
        DeleteObject(btBitmap);
        DeleteDC(hdcimage);
    }
};

now i must otimizate the code and use 1 function for read the images, instead repeat the code ;)
theres just 1 thing: i continue with flickers, sometimes, can anyone advice me?

Edited 1 Year Ago by cambalinho

Images are read by the constructor as each instance is instantiated, and you handle the images by pointer assignment, destroying them when done.

heress the class otimizated:

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;
        DeleteObject(btBitmap);
        DeleteObject(obj);
        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;
        }
        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);
            //RePaint();
            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);
    }

    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);
    }
};

Dang.. that is a lot of code with a lot of design flaws.

Here's what's wrong after a very quick glance:

//You have the following constructor:
image()
{
    if (isimgused==true) //NOT needed. This is a constructor! Statement is never true.
        delete img;      //NOT needed. This is a constructor! Statement is never true.

    //It's not true because you initialised it to false.    


    //----------------------------------------------------


    isimgused=false;
    if(isGDIPLUSIniciated==false) //not needed. Statement is already true.
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        isGDIPLUSIniciated=true;
    }


    //Why did you CreateCompatibleDC in the class itself, instead of the constructor?
    //that makes the class super hard to read.

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


//Your next constructor is:
image(const int width, const int height)
{
    if (isimgused==true)
        delete img;  //again, these two statements aren't needed.

    isimgused=false;
    if(isGDIPLUSIniciated==false) //not needed.
    {
        Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        isGDIPLUSIniciated=true;
    }

    hdcimage = CreateCompatibleDC(NULL); //MEMORY LEAK. You've already initialised hdcimage in the class itself.
    btBitmap = CreateBitmap(width,height,1,32,NULL);
    obj = SelectObject(hdcimage, btBitmap);

    framecount=1;
    imageheight=height;
    imageweight=width;
}


//Next, you have the following:

void readimagefile(string filename)
{
   //..
   //..
   //..

   else
   {
       isimgused=true;

       //reading the image once.
       Gdiplus::Image img2(towstring(filename).c_str());

       //..
       //..
       //..

        //reading the image again!
        img=new Image(towstring(filename).c_str());

        //Why don't you just read the image ONCE? Allocate the first image on the heap, and use that instead of creating another image and reading all over again.
    }
}


//Next, you copy constructor does NOT COPY anything.. It doesn't copy the image that was passed in.
//Instead, it reads the image from the disk again!

Edited 1 Year Ago by triumphost

Comments
thanks for all

triumphost: why i did:

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;
    }

?
1 - the GDIPLUS::Image don't read some files(like *.cur);
2 - i only can use the Clone() when the img is initializate.

Some sort of cache of recent images would allow images not immediately used to be reused without reload/new. It could include images in use so they can be used many places, too.

i have another error that i don't understand:
1 - the timers works perfetly and show the animations;
2 - after sometime, or the timers stop or o lose the original HDC.
see the my image class, what you can tell me?

Frankly, I haven't had the chance to look the class over in detail, but my impression is that there is too much being 'baked in' to this one class, and that much of it could be separated out into subclasses. Were I designing this, I would make image an abstract class and use subclasses for most of the actual implementation; an icon subclass would in particular make sense, and move a lot of extraneous code out of the parent class.

David_50's suggestion of caching the images is a sensible one as well. I would use a priority queue (heap) and a Least Recently Used algorithm to track the cache; as new images get added, it would check to see if any images have a priority below some minimum level, and remove those from the heap, while each reference to an image already in the heap would brevet it back up to the top of the heap.

And oh yes, you have too many of you methods - as in all of them - in the class declaration. This is C++, not Java; you will want to move the majority of the implementation code into a separate source file.

Edited 1 Year Ago by Schol-R-LEA

To follow up on the last comment:

image.h

#ifndef IMAGE_H
#define IMAGE_H 1

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);

    HICON HICONFromHBITMAP(HBITMAP bitmap);

public:

    image();

    image(HDC hdcWindow);

    image(const int width, const int height);

    image( const string & filename);

    image (const image &cSource);

    image& operator= (const image &cSource);

    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);
            //RePaint();
            free(pDimensionIDs);
        }
    };

    void getImageFromResource(string strResourceName);

    void RePaint(bool blackandwhite=true);

    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);

    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;

    bool operator==(const image &other) const;

    bool operator!=(const image &other) const;

    bool haveimage();

    ~image();
};

#endif

image.cpp

void image::readimagefile(string filename)
{
    if (isimgused==true)
    delete img;
    DeleteObject(btBitmap);
    DeleteObject(obj);
    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 image::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;
}

image::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::image(HDC hdcWindow)
{
    if (isimgused==true)
    delete img;
    isimgused=false;
    if(isGDIPLUSIniciated==false)
    {
    Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
    isGDIPLUSIniciated=true;
    }
    hdcwindow=hdcWindow;
}

image:: 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;
    }
    hdcimage = CreateCompatibleDC(NULL);
    btBitmap = CreateBitmap(width,height,1,32,NULL);
    obj = SelectObject(hdcimage, btBitmap);
    framecount=1;
    imageheight=height;
    imageweight=width;
}

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

image::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& 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;
}


void image::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);
}

void image::RePaint(bool blackandwhite)
{
    //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);
}


void image::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);
}


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

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

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

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

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

Now, this still doesn't address many of the problems with the code, but at least it gets it into the right format. I left the properties in the class header mainly because I don't know how they would behave outside of them.

Edited 1 Year Ago by Schol-R-LEA

This article has been dead for over six months. Start a new discussion instead.