Thread: what's wrong with BitmpDC?

  1. #1
    Registered User
    Join Date
    Aug 2013
    Posts
    451

    what's wrong with BitmpDC?

    i did 2 nice functions for creating an HDC and other HBITMAP:
    Code:
    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();
        }
    };
    the MemoryDC seems ok, because the HDC is returned.
    the BitmapDC seems wrong... why don't return correctly the HBITMAP?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by joaquim
    the MemoryDC seems ok, because the HDC is returned.
    the BitmapDC seems wrong... why don't return correctly the HBITMAP?
    How do you know that it does not "return correctly the HBITMAP"?

    I suggest that you avoid implicit conversion functions. Use named conversion functions, or declare them explicit. This can avoid hard to diagnose situations where an implicit conversion happens when it was not expected.

    A few other things to note:
    • For MemoryDC, you defined the destructor such that it is not empty, so you probably should also define the copy constructor and copy assignment operator, or at least disable them (e.g., by declaring them to be deleted). Consider defining the move constructor and maybe also the move assignment operator.
    • For BitmapDC, you defined the copy assignment operator, but you did not define the copy constructor. If applicable, you should also consider defining the move constructor and perhaps the move assignment operator.
    • For BitmapDC, the Width and Height member functions should be declared const. For consistency, consider renaming them to width and height or getWidth and getHeight, otherwise rename init, destroy and size to Init, Destroy and Size.
    • For BitmapDC, the size member function does not seem well named. I would expect it to return a size, but it seems to do a resize. Consider renaming it to resize.
    • Overloading operator != to compare with nullptr seems strange: I would only expect pointers to be compared to nullptr. I suggest an explicit conversion function for conversion to bool instead, i.e.,
      Code:
      explicit operator bool() const
      {
          return bitmapcurrent != nullptr;
      }
      This way, you can use your BitmapDC object as an expression in an if statement's condition and other boolean contexts it will work as expected.
    • Consider overloading operator!= as a non-member non-friend function in the same namespace as BitmapDC.
    • I am a little concerned that you often call the destroy member function and then go about calling init and other functions. If init or the other functions can throw or propagate an exception, then this approach is not exception safe as it could leave your BitmapDC object in a destroyed state that is presumably an invalid state. One way out is to use the copy-swap idiom, i.e., you define an efficient swap function, after which you can create the resulting BitmapDC object and swap it with your current object, letting the destructor destroy the swapped out object when done.
    Last edited by laserlight; 08-25-2015 at 12:49 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    thanks for all. now see the image class:
    Code:
    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;
        }
    operator HICON()//these is returned
        {
            return HICONFromHBITMAP(HBitmap);
        }
    
        operator HBITMAP()//these isn't returned
        {
            return HBitmap;
        }
    ////..............
    and now my class Menu:
    Code:
    class Menu
    {
    private:
    
        static int intID;
        boolean blncheck=false;
        int ID=0;
        HMENU mnuBar=NULL;
        HMENU MenuHandle=NULL;//i must correct these ;)
        HMENU MenuPopup=NULL;
        HWND Mainwindow=NULL;
        bool ispopup=false;
        bool primeiromenu=false;
        int menuposition=0;
        string strCaption="";
        image imgMenu;
    
    void bitmap(image imgImage)
        {
    imgMenu=imgImage;
            imgMenu.Backcolor=GetSysColor(COLOR_MENU);
    
            HMENU hMenu = NULL;
            if(primeiromenu)
                hMenu = mnuBar;
            else
                hMenu = MenuHandle;
    
            SetMenuItemBitmaps(hMenu,ID,MF_BYCOMMAND,(HBITMAP)imgMenu ,(HBITMAP)imgMenu);
        }
    my problem is that i don't recive the HBITMAP image. only the size

  4. #4
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    i understand that i have several problems on my BitmapDC, laserlight(i must read, again, what you said). but i have seen, before some errors. but i will read it again.
    but can anyone correct me these: 'An application cannot select a single bitmap into more than one DC at a time.'?
    these means that i can't return the HBITMAP?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 11-14-2011, 06:35 PM
  2. wrong wrong with my xor function?
    By Anddos in forum C++ Programming
    Replies: 5
    Last Post: 04-26-2009, 01:38 PM
  3. whats wrong with this? no errors but wrong result
    By InvariantLoop in forum C Programming
    Replies: 6
    Last Post: 01-28-2005, 12:48 AM
  4. Replies: 9
    Last Post: 07-15-2004, 03:30 PM
  5. what's wrong?
    By V1P3R V3N0M in forum Windows Programming
    Replies: 9
    Last Post: 07-02-2003, 10:02 PM