Thread: Unknown GDI Object Leak in Paint Routine

  1. #1
    Self-Taught Programmer CodeHacker's Avatar
    Join Date
    Jul 2004
    Posts
    12

    Question Unknown GDI Object Leak in Paint Routine

    Hi. I don't know why, but unless I delete a HBitmap twice my paint routines leak GDI Objects. Can anyone tell me what's going on? Here's the code -
    Code:
    case WM_PAINT:
                /*Called when the window needs to be painted (redrawn). */
                
                
                /* Starts painting. */  
                hdc = BeginPaint (hwnd, &ps);
                
                     //Sets up the off-screen drawing variables.
                     hdcMem = CreateCompatibleDC(hdc);
                     hdc_hbm = CreateCompatibleBitmap(hdc,640,480);
                     DeleteObject(SelectObject(hdcMem,hdc_hbm));
                     
                     //Fill in the background.
                     FillRect(hdcMem,&Background_Area,wincl.hbrBackground);
                    
                     // Sets the colour of the text
                     switch(Position_Type){case -2: SetTextColor(hdcMem,RGB(atoi(separators[266]+1),atoi(separators[267]+1),atoi(separators[268]+1))); break;
                               case -1: SetTextColor(hdcMem,RGB(atoi(separators[274]+1),atoi(separators[275]+1),atoi(separators[276]+1))); break;
                               case 0: SetTextColor(hdcMem,RGB(atoi(separators[282]+1),atoi(separators[283]+1),atoi(separators[284]+1))); break;
                               case 1: SetTextColor(hdcMem,RGB(atoi(separators[290]+1),atoi(separators[291]+1),atoi(separators[292]+1))); break;
                               case 2: SetTextColor(hdcMem,RGB(atoi(separators[298]+1),atoi(separators[299]+1),atoi(separators[300]+1))); break;
                               case 3: SetTextColor(hdcMem,RGB(atoi(separators[306]+1),atoi(separators[307]+1),atoi(separators[308]+1))); break;
                               case 4: SetTextColor(hdcMem,RGB(atoi(separators[314]+1),atoi(separators[315]+1),atoi(separators[316]+1))); break;} 
                    
                     // Sets the Font.
                     DeleteObject(SelectObject(hdcMem,Font));
                     SetBkMode(hdcMem,TRANSPARENT);
                    
                     // Draws the text.
                     TB_Title->TB_Draw(hdcMem);
                     TB_Status->TB_Draw(hdcMem);
                     TB_Level->TB_Draw(hdcMem);
                     TB_Position->TB_Draw(hdcMem);
                     TB_Commands->TB_Draw(hdcMem);
                     TB_Message->TB_Draw(hdcMem);
                     TB_Battle1->TB_Draw(hdcMem);
                     TB_Battle2->TB_Draw(hdcMem);
                    
                     // Draws the sword and shield.
                     hdcMem2 = CreateCompatibleDC(hdcMem);
                     DeleteObject(SelectObject(hdcMem2,Image1));
                     BitBlt(hdcMem,10,360,bm.bmWidth,bm.bmHeight,hdcMem2,0,0,SRCCOPY);
                     DeleteObject(SelectObject(hdcMem2,Image2));
                     BitBlt(hdcMem,490,360,bm.bmWidth,bm.bmHeight,hdcMem2,0,0,SRCCOPY);
                     DeleteDC(hdcMem2);
                     
                     //Copies the bitmap drawn off-screen to the screen
                     BitBlt(ps.hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,hdcMem,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
                     
                     //Deletes the hdc made for drawing in memory.
                     DeleteDC(hdcMem);
                     DeleteObject(hdc_hbm);
                    
                /* Stops painting. */
                EndPaint (hwnd, &ps);
                
                return 1;
            break;
            
            case WM_ERASEBKGND: return 1; // Say we handled it.

  2. #2
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    When you select a new object into a DC, you must save the old object and select it back in later.

    Code:
    // Set up a DC and select a new DC into it.
    HBITMAP hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hdc_hbm = CreateCompatibleBitmap(hdc,640,480);
    HBITMAP hbmOld = SelectObject(hdcMem,hdc_hbm);
    
    // Use here.
    
    // Select old bmp back into DC.
    SelectObject(hdcMem, hbmOld);
    // Now you can delete the bmp and the DC.
    DeleteObject(hdc_hbm);
    DeleteDC(hdcMem);
    That same pattern applies for the font and the image you select into hdcMem2.

  3. #3
    Self-Taught Programmer CodeHacker's Avatar
    Join Date
    Jul 2004
    Posts
    12
    Thanks a lot, anonytmouse! I'll get my program to do that.
    --- I think I think, therefore I might be ---

    Why call myself the Code Hacker when I'm only a beginner? Because every day I log onto my PC and hack 'n' slash my way through line after line of my mixed up code, trying to make it work. And failing miserably.

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    You seem to be doing some complex drawing on paint messages. You may get flickering or shearing under windows (especially if using GDI not GDI+) Paint messages are low priority in the OS message que (but the OS message que can be bypassed with UpdateWindow() so the application sends the message internally rather than posting to the OS)

    I would suggest you use some form of buffer. That is create a copy of the image when the program starts and just copy it back to the screen when needed. (As opposed to creating the HDC, drawing to it, ect)


    That is create a HDC (with a bitmap, as you do in the paint) when the program inits. Create them as a global or static in the dialogs callback. WM_INITDIALOG, WM_CREATE, OnInit() in MFC

    Create a function that you can send in the HDC and do all the drawing. Just a bit of cut and paste then change to handle the HDC pointer.

    When you need to paint use your last single BitBlt() to copy the image to the paint HDC.

    Clean them up, as you do, when the dialog/app closes WM_CLOSE (OnClose() in MFC)

    Run a search here for 'double buffering' for plenty of code.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  5. #5
    Self-Taught Programmer CodeHacker's Avatar
    Join Date
    Jul 2004
    Posts
    12
    Thanks for the advice, novacain - I do some double buffering, as you can see with my calls to CreateCompatibleDC in my code, and bypass the message queue when my program updates itself by writing a smaller paint routine in code there (only one place) using GetDC - I have no need to update the pictures myself, just the textboxes, so I can make it a bit faster.

    It doesn't flicker but can be a bit slow. If you can think of a way to speed it up, thanks a lot!

    Is there any way to get round calling CreateCompatibleDC() and CreateCompatibleBitmap() each time I redraw my program? If you can think of a way, please help.

    In the Major Problems with GetSaveFileName() and GetLoadFileName thread I started I attached my full program to my last post, if anyone wants to see it.
    --- I think I think, therefore I might be ---

    Why call myself the Code Hacker when I'm only a beginner? Because every day I log onto my PC and hack 'n' slash my way through line after line of my mixed up code, trying to make it work. And failing miserably.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Question on l-values.
    By Hulag in forum C++ Programming
    Replies: 6
    Last Post: 10-13-2005, 04:33 PM
  2. A question about constructors...
    By Wolve in forum C++ Programming
    Replies: 9
    Last Post: 05-04-2005, 04:24 PM
  3. Linked List Templates and Object Types
    By ventolin in forum C++ Programming
    Replies: 10
    Last Post: 06-16-2004, 12:05 PM
  4. How would you do this (object interlinking)
    By darksaidin in forum C++ Programming
    Replies: 7
    Last Post: 08-30-2003, 12:08 AM
  5. GDI: Creating a pen VS taking it as a stock object.
    By limacat in forum Windows Programming
    Replies: 5
    Last Post: 03-31-2003, 10:14 AM