I've just been working on this myself. You need to nominate a particular colour in the bitmap to be the "transparency colour". In my case, I chose 100% green and I used this code which I modified from some code I found on MSDN....
In your class - or header file...
Code:
const COLORREF RGB_BLACK = 0x00000000L;
const COLORREF RGB_WHITE = 0x00FFFFFFL;
const COLORREF RGB_RED = 0x000000FFL;
const COLORREF RGB_GREEN = 0x0000FF00L;
const COLORREF RGB_BLUE = 0x00FF0000L;
const COLORREF RGB_LIGHTGRAY = 0x00C0C0C0L;
// Define any others you need.
// The colour inside this button's bitmap(s) that should be regarded as transparent
COLORREF m_kTransparentColour;
// The thresholds for red, green & blue
short m_RedThreshold, m_GreenThreshold , m_BlueThreshold;
In your CPP file...
Code:
// Initialise the transparency colour
// and thresholds for this button.
m_kTransparentColour = RGB_GREEN;
m_RedThreshold = 100; // Adjust to your own requirements
m_GreenThreshold = 132; // Adjust to your own requirements
m_BlueThreshold = 80; // Adjust to your own requirements
The actual code....
Code:
void YourClass::DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart, short yStart, COLORREF kTransparentColour, bool bAssume100Green)
{
BITMAP bm;
COLORREF cColour;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
POINT ptSize;
int x, y;
hdcTemp = CreateCompatibleDC(hdc);
if (HGDIOBJ hOldObj = SelectObject(hdcTemp, hBitmap)) // Select the bitmap
DeleteObject(hOldObj);
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
ptSize.x = bm.bmWidth; // Get width of bitmap
ptSize.y = bm.bmHeight; // Get height of bitmap
DPtoLP(hdcTemp, &ptSize, 1); // Convert from device
// to logical points
// Create some DCs to hold temporary data.
hdcBack = CreateCompatibleDC(hdc);
hdcObject = CreateCompatibleDC(hdc);
hdcMem = CreateCompatibleDC(hdc);
hdcSave = CreateCompatibleDC(hdc);
// Create a bitmap for each DC. DCs are required for a number of GDI functions.
// Monochrome DC
bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
// Monochrome DC
bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
// Each DC must select a bitmap object to store pixel data.
bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);
bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);
bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);
// Set proper mapping mode.
SetMapMode(hdcTemp, GetMapMode(hdc));
// Save the bitmap sent here, because it will be overwritten.
BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
// If we're assuming a 100% green background (the normal case) set all
// pixels that are green or "very nearly green" to be exactly 100% green.
if (bAssume100Green)
{
for (x = 0; x < ptSize.x; x++)
for (y = 0; y < ptSize.y; y++)
{
COLORREF pixel = GetPixel(hdcTemp, x, y);
if (pixel)
{
DWORD dwRedContent, dwGreenContent, dwBlueContent;
dwRedContent = ((pixel & 0x000000FF) % 0xFFFFFF);
dwGreenContent = (((pixel & 0x0000FF00) >> 8) % 0xFFFFFF);
dwBlueContent = (((pixel & 0x00FF0000) >> 16) % 0xFFFFFF);
// Does the pixel have a high content of green?
if ((short)dwGreenContent > m_GreenThreshold)
{
// If so, and it has a low content of both
// red and blue, set it to be 100% green.
if (((short)dwRedContent < m_RedThreshold) &&
((short)dwBlueContent < m_BlueThreshold))
SetPixel(hdcTemp, x, y, RGB_GREEN);
}
}
}
}
else
cColour = SetBkColor(hdcTemp, kTransparentColour);
// Create the object mask for the bitmap by performing a BitBlt
// from the source bitmap to a monochrome bitmap.
BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
// Now, if we're assuming a 100% green background, make
// absolutely sure that any 100% green pixels are converted
// to white in the mask - and all other pixels are black.
if (bAssume100Green)
{
for (x = 0; x < ptSize.x; x++)
for (y = 0; y < ptSize.y; y++)
{
COLORREF pixel = GetPixel(hdcTemp, x, y);
if (pixel == RGB_GREEN)
SetPixel(hdcObject, x, y, RGB_WHITE);
else
SetPixel(hdcObject, x, y, RGB_BLACK);
}
// Now change the green background colour for the supplied
// bitmap to be the colour that we want for transparency.
for (x = 0; x < ptSize.x; x++)
for (y = 0; y < ptSize.y; y++)
{
COLORREF pixel = GetPixel(hdcTemp, x, y);
if (pixel)
if (pixel == RGB_GREEN)
SetPixel(hdcTemp, x, y, kTransparentColour);
}
}
else
SetBkColor(hdcTemp, cColour);
// Create the inverse of the object mask.
BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);
// Copy the background of the main DC to the destination.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, SRCCOPY);
// Mask out the places where the bitmap will be placed.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
// Mask out the transparent coloured pixels on the bitmap.
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
// XOR the bitmap with the background on the destination DC.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
// Copy the destination to the screen.
BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);
// Place the original bitmap back into the bitmap sent here.
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
// Delete the memory bitmaps.
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
// Delete the memory DCs.
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
}
The main bit I added was support for "assume 100% green". All this does is to look at colours that are "almost 100% green" and turn them into precisely 100% green. If you use a different colour, you'll need to adjust m_kTransparentColour (and the RGB thresholds) to suit your own requirements. It takes quite a long time to get this right BTW – so be prepared to experiment…!
[Edit...] Incidentally, the parameters xStart and yStart will both be 0 in most cases.
Last edited by John E; February 6th, 2006 at 11:50 AM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
Yes - use the code that I gave you above. That's exactly what I was doing... You need to call it in DrawItem() and OnPaint() - selecting the appropriate bitmap to pass to the DrawTransparentBitmap() function.
The main problem is that you have to nominate a particular colour as the transparency colour. This sounds very easy in theory - but in practice, most graphics packages (DrawPlus / Paint / PhotoShop etc) don't export the exact colours that you define. In my case, 100% green would come out as "not quite" 100% green - so I needed to correct this in the source bitmap. However, it is possible. I managed to make it work extremely well.
"A problem well stated is a problem half solved.” - Charles F. Kettering
First Set your Button Style OwnerDraw.Then use CBitMapButton Class and Create Object of your CBitmap Class Associate them with your Dialog Control and now do what ever u want
some few lines will helps you
Code:
CBitmapButton m_btnAdd;
DDX_Control(pDX, IDC_BUTTON_UPDATE, m_btnAdd);
//now load the state of your button
m_btnAdd.LoadBitmaps(IDB_ADD_NORMAL, IDB_ADD_PRESSED, IDB_ADD_FOCUSED, IDB_ADD_DISABLED);
m_btnAdd.SizeToContent();
that is enough for your code.
Thanx.
Last edited by humptydumpty; February 7th, 2006 at 03:41 AM.
First Set your Button Style OwnerDraw.Then use CBitMapButton Class and Create Object of your CBitmap Class Associate them with your Dialog Control and now do what ever u want
some few lines will helps you
Code:
CBitmapButton m_btnAdd;
DDX_Control(pDX, IDC_BUTTON_UPDATE, m_btnAdd);
//now load the state of your button
m_btnAdd.LoadBitmaps(IDB_ADD_NORMAL, IDB_ADD_PRESSED, IDB_ADD_FOCUSED, IDB_ADD_DISABLED);
m_btnAdd.SizeToContent();
that is enough for your code.
Thanx.
I don't see how your code help me making a CBitmapButton transparent
Could you explain ... ?
Ok, If I understand a little, your code allow some threshold to make the transparency, I'm simply using one colour to make transparency, I think I'll remove this possibility,
but, when I modify by calling your function with the parameter bAssume100Green to "false" transparency seems working
I successfully get the Dialog Background, the originally but not the one I put with this code :
Code:
BOOL CMyDialog::OnEraseBkgnd(CDC* pDC)
{
CBitmap Bitmap;
CDC MemDC;
Bitmap.LoadBitmap(p_iIDD_Background); // lecture bitmap dans les ressources
BITMAP InfosBmp; // structure d'informations.
Bitmap.GetBitmap(&InfosBmp);
MemDC.CreateCompatibleDC(pDC); // creation d'un DC en memoire
MemDC.SelectObject(&Bitmap); // selection du bitmap dans le DC en memoire
// transfert final du bitmap dans le dc de la view.
pDC->BitBlt( 0,0,InfosBmp.bmWidth, InfosBmp.bmHeight,
&MemDC,
0,0,
SRCCOPY);
return TRUE;
}
Bookmarks