Link to home
Start Free TrialLog in
Avatar of mahno
mahno

asked on

Problem with buttons containing bitmaps

Hi all!

Please help me. My problem is following:
I want to create Button containing bitmap. (MS Visual C++ 6.0) I place button control to a form. Add propierties: Bitmap, Transparent. Associate variable m_bmp with this button (Control, class CButton)

Add source code:

  CBitmap bmp;
  bmp.LoadBitmap(TEST_BMP);
  m_bmp.SetBitmap((HBITMAP)bmp);

(TEST_BMP is a 16 color bitmap)

But the image does not showing.

And Q2: How can I set this image transparent (e.g. Set transparent color, for example color of top-left pixel)?

Thanks

Regards,
  Ruslan (mahno@mail.lv)

ASKER CERTIFIED SOLUTION
Avatar of krisp
krisp

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Zoppo
Hi mahno,

try add a

bmp.Detach();

after the line with the SetBitmap() function to avoid deletion of the bitmap's GDI object with dtor of CBitmap.

Since the drawing of CButton does not support transparency you can only create a new bitmap with all pixels you want to be transparent set to the color of the buttons background.

ZOPPO
Hey, krisp, you should even say something about Q2 when locking the question as answered ...
Avatar of krisp
krisp

sorry zoppo
Not my problem, but manho's             :)
Avatar of mahno

ASKER

Thanks krisp and Zoppo, Q1 is clearified to me (both methods are working) Just one more question (Q2): I'm trying to get transparent bitmap by this way:

  CBitmap bmp;
  const int nBmpSize = 16*16; //Bitmap size
  unsigned short *lpBits;
  DWORD dwCount = nBmpSize<<1;
  DWORD dwSysColor;

  lpBits = new unsigned short[nBmpSize];
  bmp.LoadBitmap(IDB_BITMAP2);
  dwCount = bmp.GetBitmapBits(dwCount, (LPVOID)lpBits);
  dwSysColor = GetSysColor(COLOR_BTNFACE);

  if (dwCount == nBmpSize<<1) {
    for (int nIndex = 1; nIndex < nBmpSize; nIndex++) {
      //Top-Left with StdWinBtnFace color
      if (lpBits[nIndex] == lpBits[0]) {
        lpBits[nIndex] = (unsigned short)dwSysColor; //Error
      }
    }
    lpBits[0] = (unsigned short)dwSysColor; //Error
    bmp.SetBitmapBits(dwCount, (LPVOID)lpBits);
  }
  m_bmp.SetBitmap((HBITMAP)bmp.Detach());

One problem: When I get bitmap bits using "GetBitmapBits" - for each pixel I get 16bit color value, but using "GetSysColor" - 32bit (24bit are used). How can I convert 24 -> 16? I can't find this in help.

Thanks,
  Ruslan
Hi mahno,

Use ::GetDIBits() instead ...

ZOPPO
Avatar of mahno

ASKER

Zoppo, something like this?

  DWORD dwCount;
  BITMAPINFO bi;

  HBITMAP hbitmap = LoadBitmap(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP2));
  dwCount = ::GetDIBits(this->GetDC()->GetSafeHdc(), hbitmap, 0, 16, (LPVOID)lpBits, &bi, DIB_RGB_COLORS);

?

Thanks,
  Ruslan

I do not know exactly how to use it (because I did not use it until now), but here are some MSDN articles which may help you with this:

ID: Q81498
ID: Q230492
ID: Q80080

ZOPPO
Avatar of mahno

ASKER

Thanks,
  mahno
:(
Avatar of mahno

ASKER

Hi Zoppo,

I'm sorry but, unfortunately, I'm not experienced in Experts-Exchange (This is my first time :-) Therefore I've made mistake when add PTS ONLY to krisp. Would You mind explaining me how could I correct my mistake and add PTS both of you?

ps: You answers was fine and now I have almoust transparent bitmap :-).
I've got this by the following:

  CBitmap bmp;
  const int nBmpSize = 16*16; //Bitmap size
  unsigned short *lpBits;
  DWORD dwCount = nBmpSize<<1;
  DWORD dwSysColor;
  WORD wSysColor;

  lpBits = new unsigned short[nBmpSize];
  bmp.LoadBitmap(IDB_BITMAP2);
  dwCount = bmp.GetBitmapBits(dwCount, (LPVOID)lpBits);
  dwSysColor = GetSysColor(COLOR_BTNFACE);
  //Converting 24bpp -> 15bpp
  wSysColor = (((WORD)((dwSysColor&0xff)>>3) << 10)&0x7c00) |        //Red
              (((WORD)(((dwSysColor&0xff00)>>8)>>3) << 5)&0x03e0) |  //Green
              (((WORD)(((dwSysColor&0xff0000)>>16)>>3))&0x001f);     //Blue


  if (dwCount == nBmpSize<<1) {
    for (int nIndex = 1; nIndex < nBmpSize; nIndex++) {
      //Replace Top-Left with StdWinBtnFace color
      if (lpBits[nIndex] == lpBits[0]) {
        lpBits[nIndex] = wSysColor;
      }
    }
    lpBits[0] = wSysColor;
    bmp.SetBitmapBits(dwCount, (LPVOID)lpBits);
  }
  m_bmp.SetBitmap((HBITMAP)bmp.Detach());

Later I change code (use ::GetDIBits()), because in current implementation I loose some color information (converting 8bit-per-color -> 5bit-per-color)

Regards,
  mahno
It's not possible to correct given points, but never mind, krisp will be very happy abouot his/her first points ...

enjoy learning with EE           :)