Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Windows API
  4. What is it with HBITMAPs?

What is it with HBITMAPs?

Scheduled Pinned Locked Moved Windows API
performancequestiongraphicsannouncement
3 Posts 3 Posters 7 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    Craig Longman
    wrote on last edited by
    #1

    I've been working a lot with bitmaps for GUI uses lately, and frequently have been frustrated. Normally, I just fall back to using a CImage class when I have any actual work to do on the image, but now I'm trying to understand what is going on, and I'm confused. I have a button that I want to use coloured bitmap on instead of text (in Win7). So, here is what I tried first:

    HBITMAP hBmp = ::CreateBitmap( 21, 21, 1, 24, NULL );
    HDC hDC = ::CreateCompatibleDC( NULL );
    ::SelectObject( hDC, hBmp );
    ::SelectObject( hDC, hBrush ); // made from ::CreateBrushIndirect()
    ::Rectangle( hDC, 0, 0, 20, 20 );
    ::DeleteDC( hDC );
    ::SendMessage( hWnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp );

    But I just get a black square. Sized correctly, but black and the brush was created as white. MSDN et al. say that ::CreateCompatibleDC() when provided with NULL creates a memory DC compatible with the screen. To me, this means something that is (in my case) a 24 bit colour DC. Reading more of MSDN, they indicate that for performance reasons, it is suggested to use ::CreateCompatibleBitmap() to create colour bitmaps. So, I tried this instead:

    HDC hDC = ::CreateCompatibleDC( NULL );
    HBITMAP hBmp = ::CreateCompatibleBitmap( hDC, 21, 21 );
    ::SelectObject( hDC, hBmp );
    ::SelectObject( hDC, hBrush ); // made from ::CreateBrushIndirect()
    ::Rectangle( hDC, 0, 0, 20, 20 );
    ::DeleteDC( hDC );
    ::SendMessage( hWnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp );

    This gives me a white image on the button, great, I have a bitmap that works. However, changing the colour produces some silly, apparently monochrome, dithered bitmap on the button. Which leads me to believe that the DC being created is, in fact, not compatible with my screen. So I tried this:

    HDC hDC = ::CreateCompatibleDC( ::GetDC( m_hWnd ) );

    But get exactly the same result, a silly monochrome dithered version. What exactly does 'compatible' mean then? Short of going through the whole rigmarole of creating a DIBSection, how does one actually create a usable colour bitmap to draw on and send to a button? I must be missing something, I can't imagine that regular bitmaps are this useless, are they? Thanks, CraigL

    P 1 Reply Last reply
    0
    • C Craig Longman

      I've been working a lot with bitmaps for GUI uses lately, and frequently have been frustrated. Normally, I just fall back to using a CImage class when I have any actual work to do on the image, but now I'm trying to understand what is going on, and I'm confused. I have a button that I want to use coloured bitmap on instead of text (in Win7). So, here is what I tried first:

      HBITMAP hBmp = ::CreateBitmap( 21, 21, 1, 24, NULL );
      HDC hDC = ::CreateCompatibleDC( NULL );
      ::SelectObject( hDC, hBmp );
      ::SelectObject( hDC, hBrush ); // made from ::CreateBrushIndirect()
      ::Rectangle( hDC, 0, 0, 20, 20 );
      ::DeleteDC( hDC );
      ::SendMessage( hWnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp );

      But I just get a black square. Sized correctly, but black and the brush was created as white. MSDN et al. say that ::CreateCompatibleDC() when provided with NULL creates a memory DC compatible with the screen. To me, this means something that is (in my case) a 24 bit colour DC. Reading more of MSDN, they indicate that for performance reasons, it is suggested to use ::CreateCompatibleBitmap() to create colour bitmaps. So, I tried this instead:

      HDC hDC = ::CreateCompatibleDC( NULL );
      HBITMAP hBmp = ::CreateCompatibleBitmap( hDC, 21, 21 );
      ::SelectObject( hDC, hBmp );
      ::SelectObject( hDC, hBrush ); // made from ::CreateBrushIndirect()
      ::Rectangle( hDC, 0, 0, 20, 20 );
      ::DeleteDC( hDC );
      ::SendMessage( hWnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp );

      This gives me a white image on the button, great, I have a bitmap that works. However, changing the colour produces some silly, apparently monochrome, dithered bitmap on the button. Which leads me to believe that the DC being created is, in fact, not compatible with my screen. So I tried this:

      HDC hDC = ::CreateCompatibleDC( ::GetDC( m_hWnd ) );

      But get exactly the same result, a silly monochrome dithered version. What exactly does 'compatible' mean then? Short of going through the whole rigmarole of creating a DIBSection, how does one actually create a usable colour bitmap to draw on and send to a button? I must be missing something, I can't imagine that regular bitmaps are this useless, are they? Thanks, CraigL

      P Offline
      P Offline
      pasztorpisti
      wrote on last edited by
      #2

      Instead of CreateBitmap() try using CreateCompatibleBitmap(). Another mistake that I myself often made is that before destryoing/releasing a DC you should set its object back to the original ones (bitmap, brush, etc...). So store the returning values from ::SelectObject() calls, and after performing the draw operations call ::SelectObject() again with the stored objects. After this its YOU who is responsible for releasing your own resources (bitmap, brush).

      E 1 Reply Last reply
      0
      • P pasztorpisti

        Instead of CreateBitmap() try using CreateCompatibleBitmap(). Another mistake that I myself often made is that before destryoing/releasing a DC you should set its object back to the original ones (bitmap, brush, etc...). So store the returning values from ::SelectObject() calls, and after performing the draw operations call ::SelectObject() again with the stored objects. After this its YOU who is responsible for releasing your own resources (bitmap, brush).

        E Offline
        E Offline
        Espen Harlinn
        wrote on last edited by
        #3

        I might be simpler to Restore the state of the DC using SaveDC/RestoreDC Just a thought Espen Harlinn

        1 Reply Last reply
        0
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • World
        • Users
        • Groups