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.
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…! :wave:
[Edit...] Incidentally, the parameters xStart and yStart will both be 0 in most cases.
Re: MFC : Make a bitmap with a transparant color
As an alternative, take a look at CDC::TransparentBlt().
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 ?
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.
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) ?
Re: MFC : Make a bitmap with a transparant color
Quote:
Originally Posted by FireJocker
Must I declare transparent color I want ?
Yes....
Quote:
Originally Posted by FireJocker
Isn't it possible getting the transparent of a pixel given ? (by it's X, Y position) ?
Not as far as I know - though someone might correct me about that.
Re: MFC : Make a bitmap with a transparant color
lol !
I'm really bad ! :) I don't see how using your code
Code:
void CTransparentBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CBitmapButton::DrawItem(lpDIS);
DrawTransparentBitmap(
}
what are these parameters :
HDC hdc, HBITMAP hBitmap, short xStart, short yStart, bool bAssume100Green ?
Sorry being so bad !
Re: MFC : Make a bitmap with a transparant color
Okay, sorry - here's how to call the function....
Code:
// From 'OnPaint()
void CTransparentBitmapButton::OnPaint()
{
if ((GetParent()) && (GetParent()->IsIconic()))
{
CBitmapButton::OnPaint();
}
else
{
CPaintDC dc(this); // device context for painting
// At least onw bitmap must be loaded before calling 'Paint()'
ASSERT(m_bitmap.m_hObject != NULL);
// and we'll assume until we find otherwise, that
// the button is being drawn in its normal state.
CBitmap* pBitmap = &m_bitmap;
if ((!(IsWindowEnabled())) && (NULL != m_bitmapDisabled.m_hObject))
pBitmap = &m_bitmapDisabled;
DrawTransparentBitmap(dc.m_hDC, *pBitmap, 0, 0, m_kTransparentColour, true);
}
}
// From 'DrawItem()'
void CTransparentBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct != NULL);
// At least onw bitmap must be loaded before calling 'DrawItem()'
ASSERT(m_bitmap.m_hObject != NULL);
CBitmap* pBitmap = &m_bitmap;
UINT state = lpDrawItemStruct->itemState;
if ((state & ODS_SELECTED) && (NULL != m_bitmapSel.m_hObject))
pBitmap = &m_bitmapSel;
else if ((state & ODS_FOCUS) && (NULL != m_bitmapFocus.m_hObject))
pBitmap = &m_bitmapFocus;
else if ((state & ODS_DISABLED) && (NULL != m_bitmapDisabled.m_hObject))
pBitmap = &m_bitmapDisabled;
DrawTransparentBitmap(lpDrawItemStruct->hDC, *pBitmap, 0, 0, m_kTransparentColour, true);
}
I'll be out for the next couple of hours - but leave a message saying how you got on.
Re: MFC : Make a bitmap with a transparant color
ok, thanks :)
I was near your code ! :)
Looking the code of CBitmapButton in afxext.h then in winbtn.cpp, my code was .....
Code:
void CTransparentBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CBitmapButton::DrawItem(lpDIS);
HBITMAP pBitmap = m_bitmap;
UINT state = lpDIS->itemState;
if ((state & ODS_SELECTED) && m_bitmapSel.m_hObject != NULL)
pBitmap = &m_bitmapSel;
else if ((state & ODS_FOCUS) && m_bitmapFocus.m_hObject != NULL)
pBitmap = &m_bitmapFocus; // third image for focused
else if ((state & ODS_DISABLED) && m_bitmapDisabled.m_hObject != NULL)
pBitmap = &m_bitmapDisabled; // last image for disabled
DrawTransparentBitmap(lpDIS->hDC, pBitmap,
}
I'll use yours then I'll answers you.
thanks a lot for your help !
Re: MFC : Make a bitmap with a transparant color
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.:thumb:
Re: MFC : Make a bitmap with a transparant color
Quote:
Originally Posted by humptydumpty
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.:thumb:
I don't see how your code help me making a CBitmapButton transparent
Could you explain ... ?
thx
Re: MFC : Make a bitmap with a transparant color
Just Tryied That Once and let me know.Don't Forget to use CBitmapClass
Re: MFC : Make a bitmap with a transparant color
@ John E
------------
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;
}
How merge the tranparency with this background ?
Re: MFC : Make a bitmap with a transparant color
There is already a TransparentBlt function.