Thread: Creating and delete DeivceContext and bitmaps

  1. #1
    Registered User
    Join Date
    Jul 2011
    Posts
    27

    Creating and delete DeivceContext and bitmaps

    Code:
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
    
     hfFontDefault = CreateFont(lfHeight, 0, 0, 0, 0, TRUE, 0, 0, 0, 0, 0, 0, 0, _T("Times New Roman"));
     bmTest= (HBITMAP)LoadBitmap(hInstance, _T("MyBitmap"));
    
    }
    
    
    …
    WM_PAINT:
    
    
    image_dc = CreateCompatibleDC(hdc);
    		SelectObject(image_dc, hfFontDefault);
    		old_hbitmap = (HBITMAP)SelectObject(image_dc, bmTest);
    		BitBlt(hdc ,10 , 10, 1000, 1000, image_dc, 0, 0, SRCCOPY);
    		wsprintf(szSize, _T(""));
    
    SelectObject(image_dc, old_hbitmap);
    		DeleteDC(image_dc);
    Hello,
    In the code above used the function CreateCompatibleDC to create a device context called image_dc for double buffering. I select hfFontDefault and bmTest bitmap into it. At the end of the WM_PAINT message, I select the old_hbitmap back into the image_dc.

    Question 1: I have attached a diagram. Is the diagram an accurate representation of the device context in the code?
    Creating and delete DeivceContext and bitmaps-bitmap2-png
    Question 2: I think it’s safe to skip the last message to select the old_hbitmap back into image_dc before I DeleteDC(image_dc). However I would assume it’s always a good idea to put it back. Is that true?

    Question 3: the bmTest needs to be deleted, and I did so at the WM_DESTORY message. Right?

  2. #2
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by derder View Post
    Question 1: I have attached a diagram. Is the diagram an accurate representation of the device context in the code?
    What makes you think it wouldn't be?

    Question 2: I think it’s safe to skip the last message to select the old_hbitmap back into image_dc before I DeleteDC(image_dc). However I would assume it’s always a good idea to put it back. Is that true?
    No. Everything you SelectObject into it must be taken out before you delete it, like you did with the bitmap. Note that you forgot to do it with hfFontDefault, so that's an error.
    Question 3: the bmTest needs to be deleted, and I did so at the WM_DESTORY message. Right?
    We've no idea if you did or not, you didn't post that part. But yes, it needs to be deleted.

    The usual approach to double buffering is to create the memory dc (that's image_dc in your code) in WM_CREATE and destroy it in WM_DESTROY rather than creating and deleting it for each WM_PAINT message.

    wsprintf(szSize, _T(""));
    This is a heavy handed way of doing szSize[0] = 0;

  3. #3
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by derder View Post
    In the code above used the function CreateCompatibleDC to create a device context called image_dc for double buffering.
    It is not double buffering if you do the actual drawing in the paint handler.

    The objective behind double buffering is to reduce the time taken to process a WM_PAINT msg. This is acheived by doing all teh drawing and then sending a paint msg.

    In the WM_PAINT the only drawing is coping the minimum amount from the back-buffer (memDC) to the screen DC with one BitBlt
    "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

  4. #4
    Registered User
    Join Date
    Jul 2011
    Posts
    27
    No. Everything you SelectObject into it must be taken out before you delete it, like you did with the bitmap. Note that you forgot to do it with hfFontDefault, so that's an error.
    What do you mean take it back out. I thought you meant put it back in. My code puts in bmTest and hfFontDefault into image_dc. Next I use the select object as follows: SelectObject(image_dc, old_hbitmap) to put it back in. How would you take it back out?

  5. #5
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Consider the HDC a struct.

    The HDC holds 'pointers' to each of the GDI objects it can contain; font, pen, brush, bmp etc.

    The HDC is created / get already full of 'default' GDI objects (ie a created compatible DC is created containing a 1x1 monochrome bmp)

    The HDC can only hold one of each type, so when you select a GDI object into the DC you push out the current GDI object of the same type (ie SelectObject a pen and the current pen is pushed out)

    The HDC may not delete / release with non default GDI objects selected into it.

    Non default GDI objects may not delete while selected into a HDC.

    .NET version IDEs are less strict and tend to 'hide' GDI leaks.

    GDI leaks are much worse than memory leaks as GDI memory is very limited and shared across all applications.

    SelectObject(image_dc, hfFontDefault);
    // The previous poster pointed out you do not catch the default font and push this font out of the 1,000s of HDCs you select this font into (1 HDC per paint msg) so you might be leaking 1 GDI object per paint msg. Check in Task Manger to see (add 'GDI Objects' to the 'Processes" TAB of Task Manager).
    Last edited by novacain; 07-25-2011 at 02:41 AM.
    "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

  6. #6
    Registered User
    Join Date
    Dec 2010
    Posts
    71
    I want to see if I understand.

    In WM_DESTROY must added:
    Code:
    SelectObject(image_dc,hfFontOld);
    SelectObject(image_dc, old_hbitmap);
    DeleteObject(hfFontDefault);
    DeleteObject(bmTest);
    DeleteDC(image_dc);
    ?

  7. #7
    Registered User
    Join Date
    Jul 2011
    Posts
    27
    Check in Task Manger to see (add 'GDI Objects' to the 'Processes" TAB of Task Manager).
    Wow! Thanks for the task manaager info. It took me a few seconds to figure out how to add the "GDI Objects" as a column. Once I got it, I think that really helps!

  8. #8
    Registered User
    Join Date
    Jul 2011
    Posts
    27
    \The objective behind double buffering is to reduce the time taken to process a WM_PAINT msg. This is acheived by doing all teh drawing and then sending a paint msg.
    How do you add code to "do all the drawing"? Perhaps I use a timer or registered mouse move to call the draw routine? Is there a synchronized clause to make sure there's no race condition?

  9. #9
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Depends on what triggers the requirement to draw.
    Generally your app receives a msg, which could be time based or a user generated event, network or other event.
    This msg triggers the app to re-draw its screen and then generates a paint msg (which updates the actual screen).

    If you had a button that when clicked an image changes, then in the buttons BN_CLICKED handler would load the new image, draw the image to the memDC and generate a WM_PAINT msg.

    If the user was drawing a line with the mouse then mouse move and button up would re-draw and send paint msgs.

    Animation can be done with timer msgs.

    In WM_PAINT you copy the memDC to the DC from the PAINTSTRUCT DC using the PAINTSTRUCT rect.

    There is no race condition as the OS combines WM_PAINT msgs in the queue (the only msg that is processed by GetMessage or PeekMessage).

    Generally apps that draw in this way use UpdateWindow() to bypass the OS msg queue (and post directly to the windows callback).
    "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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with creating a dynamic array that can add and delete elements
    By cloudstrife910 in forum C++ Programming
    Replies: 6
    Last Post: 11-18-2010, 09:01 PM
  2. Concerning delete/delete[] at program exit
    By laserlight in forum C++ Programming
    Replies: 58
    Last Post: 01-09-2008, 01:40 PM
  3. Bitmaps
    By ldb88 in forum Windows Programming
    Replies: 6
    Last Post: 05-29-2007, 01:45 PM
  4. Replies: 17
    Last Post: 11-16-2006, 09:06 PM
  5. Creating/Editing Bitmaps
    By Speedy5 in forum Windows Programming
    Replies: 2
    Last Post: 01-17-2004, 11:06 AM