see my MemoryDc and BitmapDC class's:

class MemoryDC
{
private:
    HDC memoryDC;

public:
    MemoryDC ()
    {
        HDC hdc=GetDC(GetDesktopWindow());
        memoryDC=CreateCompatibleDC(hdc);
        ReleaseDC(GetDesktopWindow(),hdc);
    }

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

now see my image class:

class image
{
private:
    ULONG_PTR m_gdiplusToken;
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    BitmapDC HBitmap;
    Image *img=NULL;
    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::Blue;
    bool blnTransparent=true;
    HPEN imgPen;
    HBRUSH imgBrush;
    CHOOSEFONT chFont;

    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);
            }
            HBitmap.size(imageweight,imageheight);
            DrawIconEx(HBitmap,0,0,hicon,imageweight,imageheight,0,0,DI_NORMAL);
            framecount=1;
            DestroyCursor(hicon);
        }
        else
        {
            isimgused=true;
            Gdiplus::Image img2(towstring(filename).c_str());
            imageweight=img2.GetWidth();
            imageheight=img2.GetHeight();
            HBitmap.size(imageweight,imageheight);
            Gdiplus::Graphics graphics(HBitmap);
            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(HBitmap, bmp.bmWidth, bmp.bmHeight);

        ICONINFO ii = {0};
        ii.fIcon    = TRUE;
        ii.hbmColor = bitmap;
        ii.hbmMask  = hbmMask;
        HICON hIcon = CreateIconIndirect(&ii);
        DeleteObject(ii.hbmColor);
        DeleteObject(ii.hbmMask);
        return hIcon;
    }

public:

    void resize(const int width, const int height)
    {
        imageheight=height;
        imageweight=width;
        HBitmap.size(imageweight,imageheight);
    }

    image()
    {
        if (isimgused==true)
            delete img;
        isimgused=false;
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        imageheight=1;
        imageweight=1;
        HBitmap.size(imageweight,imageheight);
    }

    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;
        }
        framecount=1;
        imageheight=height;
        imageweight=width;
        HBitmap.size(imageweight,imageheight);
    }

    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(HBitmap,0,0,imageweight,imageheight,cSource.HBitmap,0,0,SRCCOPY);
    }

    image& operator= (const image &cSource)
    {
        if (this == &cSource)      // Same object?
            return *this;
        if(isGDIPLUSIniciated==false)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            isGDIPLUSIniciated=true;
        }
        readimagefile(cSource.strfilename);
        BitBlt(HBitmap,0,0,imageweight,imageheight,cSource.HBitmap,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(HBitmap);
            graphics.Clear(clrBackColor);
            graphics.DrawImage(img, 0, 0, imageweight, imageheight);
            free(pDimensionIDs);
        }
    };

    void draw(HDC control, long posX=0, long posY=0)
    {
        if (blnTransparent==true)
        {
            TransparentBlt(control, posX, posY,width(),height(),HBitmap, 0, 0,width(), height(), clrBackColor.ToCOLORREF());
        }
        else
        {
            BitBlt(control,posX,posY,width(),height(),HBitmap,0,0,SRCCOPY);
        }
    }
    operator HICON() //works
    {
        return HICONFromHBITMAP(HBitmap);
    }

    operator HBITMAP() const //don't works
    {
        return HBitmap;
    }

seen these: why i can't return the HBITMAP value?

seems that i have 1 problem on my BitmapDC(line):

BitBlt(bitmapsource, 0, 0, intwidth, intheight, bitmapsource, 0, 0, SRCCOPY);

it's:

BitBlt(bitmapsource, 0, 0, intwidth, intheight, HBitmap, 0, 0, SRCCOPY);

besides the variable life. what you can tell me about returning HBITMAP?
seems that everytime that i need it, i must recreate it with HDC.

Your copy constructor is missing.
Your bitmap is destroyed when assigned. Why? Because you're making a shallow copy by doing Bitmap& operator = (const Bitmap& bmp); and when bmp dies, all its resources dies. Thus your bitmap that was passed in is now destroyed or has invalid resources.

Secondly, HICONFromHBITMAP creates a compatible bitmap from the existing DC or Bitmap.

Finally, your BitmapDC is returning an HBITMAP that is currently selected into a DC already. You cannot do that.

Edited 1 Year Ago by triumphost

https://msdn.microsoft.com/en-us/library/windows/desktop/dd162957(v=vs.85).aspx

Remarks

An application cannot select a single bitmap into more than one DC at a time.

class BitmapDC
{
private:
    MemoryDC hdcbitmap;
    HGDIOBJ bitmapold;
    HBITMAP bitmapcurrent;
    int width;
    int height;

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

    void destroy()
    {
        if (bitmapold)
        {
            SelectObject(hdcbitmap, bitmapold);
            bitmapold = nullptr;
        }

        if (bitmapcurrent)
        {
            DeleteObject(bitmapcurrent);
            bitmapcurrent = nullptr;
        }
    }

public:
    BitmapDC(int width = 1, int height = 1) : hdcbitmap(), bitmapold(nullptr), bitmapcurrent(nullptr), width(width), height(height)
    {
        init(width, height);
    }

    BitmapDC(const BitmapDC &other) : BitmapDC(other.width, other.height)
    {
        BitBlt(hdcbitmap, 0, 0, width, height, other, 0, 0, SRCCOPY);
    }

    ~BitmapDC()
    {
        destroy();
    }

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

    int Width() const
    {
        return width;
    }

    int Height() const
    {
        return height;
    }

    BitmapDC& operator = (const BitmapDC &other)
    {
        if(this == &other)
            return *this;

        destroy();
        init(other.width, other.height);
        BitBlt(hdcbitmap, 0, 0, width, height, other, 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;
    }

    bool operator != (std::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
    {
        if (bitmapold)
        {
            SelectObject(hdcbitmap, bitmapold);
            bitmapold = nullptr;
        }
        return bitmapcurrent;
    }

    operator HDC() const
    {
        if (!bitmapold)
        {
            bitmapold = SelectObject(hdcbitmap, bitmapcurrent);
        }
        return hdcbitmap;
    }
};

Edited 1 Year Ago by triumphost

i'm sorry, but i get errors here:

operator HBITMAP() const
    {
        if (bitmapold)
        {
            SelectObject(hdcbitmap, bitmapold);
            bitmapold = nullptr;//error
        }
        return bitmapcurrent;
    }

"assignment of member 'BitmapDC::bitmapold' in read-only object"
i get these same error on other places that we assign

Ooops. Remove the const from the function signature. operator HBITMAP() NOT operator HBITMAP() const.

operator HDC() NOT operator HDC() const

Edited 1 Year Ago by triumphost

sorry continues with some problems. but i fix it:

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

    MemoryDC hdcbitmap2;
    HGDIOBJ bitmapold2;
    HBITMAP bitmapcurrent2;

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

    void destroyreturn()
    {
        SelectObject(hdcbitmap2, bitmapold2);
        DeleteObject(bitmapcurrent2);
    }


public:

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

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

    void resize(int width, int height)
    {
        destroy();
        init(width, height);
        destroyreturn();
        bitmapcurrent2 = CreateBitmap(intwidth, intheight, 1, 32, NULL);
        bitmapold2 = SelectObject(hdcbitmap2, bitmapcurrent2);
        BitBlt(hdcbitmap2, 0, 0, intwidth, intheight, hdcbitmap, 0, 0, SRCCOPY);
        SelectObject(hdcbitmap2, bitmapold2);

    }

    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(hdcbitmap, 0, 0, intwidth, intheight, bitmapsource.hdcbitmap, 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()
    {
        destroyreturn();
        bitmapcurrent2 = CreateBitmap(intwidth, intheight, 1, 32, NULL);
        bitmapold2 = SelectObject(hdcbitmap2, bitmapcurrent2);
        BitBlt(hdcbitmap2, 0, 0, intwidth, intheight, hdcbitmap, 0, 0, SRCCOPY);
        SelectObject(hdcbitmap2, bitmapold2);
        return bitmapcurrent2;
    }

    operator HDC() const
    {
        return hdcbitmap;
    }

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

now the HBITMAP is showed.
but see these sample on Menu class:

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


        return *this;
    }



void bitmap(const image imgImage)
    {
        //assignment imgImage to imgMenu
        imgMenu=imgImage;
        //change the image backcolor for menu backcolor
        imgMenu.Backcolor=GetSysColor(COLOR_MENU);

here the HBITMAP is losed.. why?

The question is confusing. The first problem is that your bitmaps are already selected into a DC. The second problem is that your bitmap class is going out of scope and the destructor is being called which destroys it. The third problem is that you have no copy constructor or move constructor so you should not be copying temporary objects (shallow copy)..

Edited 1 Year Ago by triumphost

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