Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Using BitBlt to change bacground of a bitmap

Posted on 1998-11-24
5
730 Views
Last Modified: 2012-05-04
[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
Comment
Question by:McKean
  • 3
  • 2
5 Comments
 
LVL 8

Accepted Solution

by:
Answers2000 earned 300 total points
ID: 1254626
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
 
LVL 8

Expert Comment

by:Answers2000
ID: 1254627
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
 

Author Comment

by:McKean
ID: 1254628
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
 

Author Comment

by:McKean
ID: 1254629
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
 

Author Comment

by:McKean
ID: 1254630
Got it working now - thanks for advice which pointed me in right direction!
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.

861 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question