-
February 6th, 2006, 09:27 AM
#1
MFC : CBitmapButton with a transparant color
Hi,
I use pictures instead of CButton with this component : http://www.codeguru.com/Cpp/controls...cle.php/c5163/
But I need to add a transparant color, I wanted to use this code : http://www.codeguru.com/forum/showthread.php?p=1025767
But it's not to MFC,
Does someone have a solution to modify the component I gave above ?
Thanks all.
Last edited by FireJocker; February 7th, 2006 at 03:27 AM.
-
February 6th, 2006, 12:47 PM
#2
Re: MFC : Make a bitmap with a transparant color
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 12:50 PM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
February 6th, 2006, 01:13 PM
#3
Re: MFC : Make a bitmap with a transparant color
As an alternative, take a look at CDC::TransparentBlt().
Gort...Klaatu, Barada Nikto!
-
February 7th, 2006, 03:26 AM
#4
Re: MFC : Make a bitmap with a transparant color
And what about CBitmapButton ?
I finally choose using this component, it really easier to use !
Is it possible making it transparent ?
-
February 7th, 2006, 03:44 AM
#5
Re: MFC : Make a bitmap with a transparant color
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
-
February 7th, 2006, 03:46 AM
#6
Re: MFC : Make a bitmap with a transparant color
Must I declare transparent color I want ?
Isn't it possible getting the transparent of a pixel given ? (by it's X, Y position) ?
-
September 26th, 2014, 04:18 AM
#7
Re: MFC : Make a bitmap with a transparant color
sorry if you think my question is improper because I am new to mfc.
It's not that the question is improper - its that this thread is over 8 years old and it would have been more appropriate to start a new thread asking your specific question.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|