Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 795
  • Last Modified:

Using BitBlt to change bacground of a bitmap

[If anyone can supply sample code which works, I'll happily increase points!]

I'm using MS VC++4.2, but programming in C; writing for Win95/NT4. I want to put a bitmap on a dialog box, but change it so that the bitmap "background" is COLOR_3DFACE - and therefore the same color as the dialog box.

I've got 2 bitmaps ready; one the actual bitmap, the other a black and white mask with the pixels which are to be background color (transparent) white.

So far, my attempts have produced nothing on the dialog box; here's what I have so far...

            hdc=GetDC(hDlg);
            hdc1=CreateCompatibleDC(hdc);
            hdc2=CreateCompatibleDC(hdc);
            hdc3=CreateCompatibleDC(hdc);
            hBit1=LoadBitmap(g_hinst,MAKEINTRESOURCE( IDB_MASK));
            hBit2=LoadBitmap(g_hinst,MAKEINTRESOURCE( IDB_BITMAP));
            hBit=CreateCompatibleBitmap(hdc,12,13);
            cColor = SetBkColor(hdc1, COLOR_3DFACE);
            hOld=SelectObject(hdc1,hBit);
            hOld1=SelectObject(hdc2,hBit1);
            hOld2=SelectObject(hdc3,hBit2);
            BitBlt(hdc1,0,0,12,13,hdc2,0,0,SRCAND);
            BitBlt(hdc1,0,0,12,13,hdc3,0,0,SRCINVERT);
            SendDlgItemMessage(hDlg,IDC_DM,STM_SETIMAGE,(WPARAM) IMAGE_BITMAP,(LPARAM)hBit );
            DeleteObject(SelectObject(hdc1, hOld));
            DeleteObject(SelectObject(hdc2, hOld1));
            DeleteObject(SelectObject(hdc3, hOld2));
            DeleteDC(hdc);
            DeleteDC(hdc1);
            DeleteDC(hdc2);
            DeleteDC(hdc3);

There are probably horrendous mistakes there; can anyone spot them and show how it's really done??

Thanks!
0
McKean
Asked:
McKean
  • 3
  • 2
1 Solution
 
Answers2000Commented:
About your code
1. COLOR_3DFACE is an index to a color, rather than an actual color, use GetSysColor(COLOR_3DFACE)
2. The DeleteObject's look wrong, I think you mean
DeleteObject(hOld) ; // etc


Having said all that, there are a couple of things you should know about drawing bitmaps with transparency

(a) If possible use Image Lists.  These include a transparent drawing feature.  If you need an HBITMAP as the end result do this

i. Create bitmap 1
ii. Create DC 1
iii.  Select bitmap 1 into DC 1
iv. Fill the bitmap 1 with the background color
v. Create Image List, you can specify a transparent color (e.g. Magenta - is RGB(255,0,255).  Except for this, the image list is a normal bitmap resource.
vi. Draw on the imagelist onto DC1
vii. You now have the imagelist


OR

the algorithm to do transparent bitblt is :-

              1. Create memory dc and select bitmap (color) in it
              2. Create a second memory DC with a monochrome bitmap same same as original bitmap.  Create AND mask by setting background color of #1 to
         transparent color
              and BitBlt to this bitmap.
              3. Create a third memory dc and bitmap (color).  Create XOR mask by bitblt #1 into this with SRCCOPY and bitblting #1 into this with raster op code
         0x220326
              4. Create a fourth memory dc and bitmap (color).  BitBlt from output dc into this
              5. BitBlt #2 into #4 with SRCAND raster op code.  Then BitBlt #1 into  #4 with SRCINVERT raster op code
              6. BitBlt #4 into your output dc.   Alternative use the handle to #'4 as your hBitmap


Please read the comment below too
0
 
Answers2000Commented:
Also Make sure you static control has SS_BITMAP style

Here is code for a transparent bitlbt using imagelists

 m_ImgList.Create( MAKEINTRESOURCE(IDB_FOREGRND), 32, 1, RGB(255,255,255) );  //Create the image list with the Foreground image as the first
         image... Transparency white!
           CBitmap cbm;   // Create the bitmap.
           cbm.LoadBitmap(MAKEINTRESOURCE(IDB_BACKGRND)) ;  // Load in the background  resource.
           m_ImgList.Add(&cbm,RGB(255,255,255)); //Add the background to the ImageList, So that we have a copy for future reference... .
           CDC cdc;    // Create the memory DC.
           cdc.CreateCompatibleDC(NULL) ;     // Make sure it's compatable with system DC.
           CBitmap *oldbmp=cdc.SelectObject( &cbm ) ;     // Select the Background Bitmap, and store the previous one (Important).
           m_ImgList.Draw(&cdc, 0, CPoint(0,0), ILD_NORMAL );    //Draw over the background with the foreground Image.
           cdc.SelectObject(oldbmp);   //Release the modified Bitmap (Important).
           m_ImgList.Add( &cbm, RGB(0,0,0));   //Read it into the Image list, note that when we first read in the bitmap too the DC, it made the transparent color BLACK,
         so this is pushing it back to Transparent.
         // Now draw out the images in order...
           m_ImgList.Draw(pDC, 0, CPoint(0,0), ILD_NORMAL );

0
 
McKeanAuthor Commented:
Thanks for all that! I'm not using MFC, but, having been pointed in the right direction by you, have found that the following works (where IDB_BITMAP1 contains 7 12x13 images and IDC_DM is a static SS_BITMAP control):

hImages=ImageList_Create(12,13,ILC_COLOR4 | ILC_MASK,7,0);
hBit1=LoadBitmap(g_hinst,MAKEINTRESOURCE( IDB_BITMAP1));
ImageList_AddMasked(hImages,hBit1, RGB(192,192,192));
DeleteObject(hBit1);
hdc=GetWindowDC(GetDlgItem(hDlg,IDC_DM));
ImageList_DrawEx(hImages,2,hdc,0,0,12,13,CLR_NONE,CLR_NONE, ILD_TRANSPARENT);
ReleaseDC(GetDlgItem(hDlg,IDC_DM),hdc);

The only problem is that it won't work under WM_INITDIALOG, presumably because the dialog hasn't yet been displayed and the DC not valid. Is there a way round that, because I want the image displayed on the dialog on creation, and at the moment nothing appears - though if I include the above code under a clicked event, for example, the bitmap does appear on click.

0
 
McKeanAuthor Commented:
Thanks for all that! I'm not using MFC, but, having been pointed in the right direction by you, have found that the following works (where IDB_BITMAP1 contains 7 12x13 images and IDC_DM is a static SS_BITMAP control):

hImages=ImageList_Create(12,13,ILC_COLOR4 | ILC_MASK,7,0);
hBit1=LoadBitmap(g_hinst,MAKEINTRESOURCE( IDB_BITMAP1));
ImageList_AddMasked(hImages,hBit1, RGB(192,192,192));
DeleteObject(hBit1);
hdc=GetWindowDC(GetDlgItem(hDlg,IDC_DM));
ImageList_DrawEx(hImages,2,hdc,0,0,12,13,CLR_NONE,CLR_NONE, ILD_TRANSPARENT);
ReleaseDC(GetDlgItem(hDlg,IDC_DM),hdc);

The only problem is that it won't work under WM_INITDIALOG, presumably because the dialog hasn't yet been displayed and the DC not valid. Is there a way round that, because I want the image displayed on the dialog on creation, and at the moment nothing appears - though if I include the above code under a clicked event, for example, the bitmap does appear on click.

0
 
McKeanAuthor Commented:
Got it working now - thanks for advice which pointed me in right direction!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now