can i change the HBITMAP structure for be transparent?
because the gif's files are show me a black background color.
cambalinho 142 Practically a Posting Shark
SalmiSoft 102 Junior Poster
So you want to draw the "foreground" of the bitmap but let the background be transparent, so the image appears to be drawn on your window rather than within a black square? If so, you need to mask the bitmap. Take a look at http://www.codeguru.com/cpp/g-m/bitmap/article.php/c1753/Transparent-Bitmap--True-Mask-Method.htm
cambalinho 142 Practically a Posting Shark
sorry, in these case i don't have HDC
triumphost 120 Posting Whiz
The first thing you need to do is select the HBITMAP
into a MemoryDC
. Then you cna use the AlphaBlend
function to draw it to the WindowDC
.
If the MemoryDC
is NOT compatible with the WindowDC
, this will fail! In that case, you can use CreateCompatibleBitmap(WindowDC, width, height)
, copy the existing bitmap to the new bitmap, draw it and free the new bitmap.
However, that is left as an exercise for you..
void DrawAlphaGDI(HDC DC, Gdiplus::Rect rect)
{
HGDIOBJ obj = SelectObject(memDC, hBmp);
AlphaBlend(DC, rect.X, rect.Y, rect.Width, rect.Height, memDC, 0, 0, Width, Height, BlendFunc); //You need to create a blend-function..
SelectObject(memDC, obj);
}
If the source has no alpha channel, it will NOT be transparent unless you specify what colour to make transparent. For that, you can use TransparentBlt
.
Image <-- Transparent image (png)
Results <-- Transparent Drawing..
Edited by triumphost
cambalinho 142 Practically a Posting Shark
i did i nice way for my label control and works:
void DrawHBITMAPtoHDC(HBITMAP hBitmap, HDC hdc)
{
BITMAP bm;
HDC MemDCExercising = CreateCompatibleDC(hdc);
HBITMAP oldbitmap =(HBITMAP) SelectObject(MemDCExercising, hBitmap);
GetObject(hBitmap,sizeof(bm),&bm);
TransparentBlt(hdc, 0, 0, bm.bmWidth , bm.bmHeight, MemDCExercising, 0, 0,bm.bmWidth , bm.bmHeight,GetPixel(MemDCExercising,0,0) );
SelectObject(MemDCExercising,oldbitmap);
DeleteDC(MemDCExercising);
}
//on label paint message:
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(inst->hwnd, &ps);
if(inst->Paint==NULL)
{
RECT f;
HDC hdc=GetDC(inst->hwnd);//getting the control HDC
GetClientRect(inst->hwnd,&f);//getting the
HBRUSH s=CreateSolidBrush(inst->clrBackColor);
HBRUSH oldBrush=(HBRUSH)SelectObject(hdc,(HBRUSH)s);
if (inst->clrBackColor==-1)
{
//hide, copy the parent control and show the control again
ShowWindow(inst->hwnd,SW_HIDE);
BitBlt(hdc,0,0,f.right-f.left,f.bottom-f.top,GetDC(GetParent(inst->hwnd)),inst->intLeft,inst->intTop,SRCCOPY);
ShowWindow(inst->hwnd,SW_SHOW);
}
else
FillRect(hdc,&f,s);
DrawHBITMAPtoHDC(inst->hBitmap,hdc);
SetBkMode(hdc,TRANSPARENT);
char *text=(char*)inst->strCaption.c_str();
SetTextColor(hdc,inst->clrTextColor );
DrawTextEx(hdc,text,-1,&f,DT_CENTER,NULL);
SelectObject(hdc,(HBRUSH)oldBrush);
DeleteObject(s);
}
EndPaint(inst->hwnd, &ps);
i'm trying the same tecnic with menus, but, for now, without sucess.
void bitmap(image imgImage)
{
BITMAP bm;
HDC MemDCExercising = CreateCompatibleDC(NULL);
GetObject((HBITMAP)imgImage,sizeof(bm),&bm);
HBITMAP outbitmap=CreateBitmap(bm.bmWidth,bm.bmHeight,1,32,NULL);
HBITMAP oldbitmap =(HBITMAP) SelectObject(MemDCExercising, outbitmap);
DrawHBITMAPtoHDC(imgImage,MemDCExercising);
SelectObject(MemDCExercising,oldbitmap);
DeleteDC(MemDCExercising);
HMENU hMenu = NULL;
if(primeiromenu)
hMenu = mnuBar;
else
hMenu = MenuHandle;
SetMenuItemBitmaps(hMenu,ID,MF_BYCOMMAND,(HBITMAP)outbitmap ,(HBITMAP)outbitmap);
}
triumphost 120 Posting Whiz
Everytime you do GetDC
, you are leaking a DC. You NEED to ReleaseDC
.
Even if you do DC = GetDC(NULL)
you need to do ReleaseDC(NULL, DC);
. If you do DC = GetDC(hwnd)
you need to do ReleaseDC(hwnd, DC);
.
In the above code, you don't need GetDC.. Use the DC that is inside the PaintStruct.
Secondly, for usage with menu, it must be COMPATIBLE.. You can't just use CreateBitmap
and hope that the DC's compatible..
HBITMAP bitmap(image imgImage) //creates a copy of imgImage or whatever is passed to this function! Beware!
{
BITMAP bm;
GetObject((HBITMAP)imgImage, sizeof(bm), &bm);
HDC DC = GetDC(NULL);
HDC MemDCExercising = CreateCompatibleDC(DC); //Create a DC compatible with our Display/Monitor.. 32-bit.
HBITMAP outbitmap = CreateCompatibleBitmap(DC, bm.bmWidth, bm.bmHeight); //create a bitmap that is compatible with our DC.
HBITMAP oldbitmap = (HBITMAP) SelectObject(MemDCExercising, outbitmap);
DrawHBITMAPtoHDC(imgImage, MemDCExercising); //good.
SelectObject(MemDCExercising, oldbitmap);
DeleteDC(MemDCExercising);
ReleaseDC(NULL, DC); //good.
HMENU hMenu = NULL;
if(primeiromenu)
hMenu = mnuBar;
else
hMenu = MenuHandle;
SetMenuItemBitmaps(hMenu,ID,MF_BYCOMMAND,(HBITMAP)outbitmap ,(HBITMAP)outbitmap);
return outbitmap; //we return it so that later we can call DeleteObject to free its memory.
}
The only thing I'm not sure about is if the DrawHBITMAPToHDC
call will work. But try it and let me know.
Edited by triumphost
cambalinho 142 Practically a Posting Shark
the image is showed, but not transparent :(
void bitmap(image imgImage)
{
DeleteObject(outbitmap);
BITMAP bm;
GetObject((HBITMAP)imgImage,sizeof(bm),&bm);
HDC DC = GetDC(NULL);
HDC MemDCExercising = CreateCompatibleDC(DC);
outbitmap=CreateCompatibleBitmap(DC, bm.bmWidth, bm.bmHeight);
HBITMAP oldbitmap =(HBITMAP) SelectObject(MemDCExercising, outbitmap);
DrawHBITMAPtoHDC(imgImage,MemDCExercising);
SelectObject(MemDCExercising,oldbitmap);
DeleteDC(MemDCExercising);
ReleaseDC(NULL, DC);
HMENU hMenu = NULL;
if(primeiromenu)
hMenu = mnuBar;
else
hMenu = MenuHandle;
SetMenuItemBitmaps(hMenu,ID,MF_BYCOMMAND,(HBITMAP)imgImage ,(HBITMAP)imgImage);
}
the outbitmap is a global variable and deleted, too, on destructor.
cambalinho 142 Practically a Posting Shark
sorry i have several mistakes on last code
cambalinho 142 Practically a Posting Shark
i continue with problems. the HBITMAP isn't copyed to HDC:
void bitmap(image imgImage)
{
DeleteObject(outbitmap);
BITMAP bm;
RECT f={0,0,100,100};
GetObject((HBITMAP)imgImage, sizeof(bm), &bm);
HDC DC = GetDC(NULL);
HDC MemDCExercising = CreateCompatibleDC(DC); //Create a DC compatible with our Display/Monitor.. 32-bit.
outbitmap = CreateCompatibleBitmap(MemDCExercising, bm.bmWidth, bm.bmHeight); //create a bitmap that is compatible with our DC.
HBITMAP oldbitmap = (HBITMAP) SelectObject(MemDCExercising, (HBITMAP)outbitmap);
HDC MemDCExercising2 = CreateCompatibleDC(DC);
HBITMAP oldbitmap2 = (HBITMAP) SelectObject(MemDCExercising2, (HBITMAP)imgImage);
TransparentBlt(MemDCExercising, 0, 0, bm.bmWidth , bm.bmHeight, MemDCExercising2, 0, 0,bm.bmWidth , bm.bmHeight,GetPixel(MemDCExercising2,0,0) );
DrawHBITMAPtoHDC((HBITMAP)imgImage, MemDCExercising); //not showed in these situation
//maybe the memory DC or the HBITMAP selection is wrong
DrawTextEx(MemDCExercising,"hello world",-1,&f,DT_CENTER,NULL);//is showed
SelectObject(MemDCExercising, oldbitmap);
DeleteDC(MemDCExercising);
ReleaseDC(NULL, DC); //good.
HMENU hMenu = NULL;
if(primeiromenu)
hMenu = mnuBar;
else
hMenu = MenuHandle;
SetMenuItemBitmaps(hMenu,ID,MF_BYCOMMAND,(HBITMAP)outbitmap ,(HBITMAP)outbitmap);
}
triumphost 120 Posting Whiz
void Draw(HBITMAP hBitmap, HDC hdc)
{
BITMAP bm;
GetObject(hBitmap, sizeof(bm), &bm);
HDC MemDCExercising = CreateCompatibleDC(hdc);
HGDIOBJ obj = SelectObject(MemDCExercising, hBitmap);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, MemDCExercising, 0, 0, SRCCOPY);
SelectObject(MemDCExercising, obj);
DeleteDC(MemDCExercising);
}
void DrawTransparent(HBITMAP hBitmap, HDC hdc, COLORREF Colour)
{
BITMAP bm;
GetObject(hBitmap, sizeof(bm), &bm);
HDC MemDCExercising = CreateCompatibleDC(hdc);
HGDIOBJ obj = SelectObject(MemDCExercising, hBitmap);
TransparentBlt(hdc, 0, 0, bm.bmWidth , bm.bmHeight, MemDCExercising, 0, 0, bm.bmWidth , bm.bmHeight, Colour);
SelectObject(MemDCExercising, obj);
DeleteDC(MemDCExercising);
}
HBITMAP Copy(HBITMAP hBmp)
{
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
HDC DC = GetDC(NULL);
HDC MemDC = CreateCompatibleDC(DC);
HBITMAP result = CreateCompatibleBitmap(DC, bm.bmWidth, bm.bmHeight);
HGDIOBJ obj = SelectObject(MemDC, result);
Draw(hBmp, MemDC);
SelectObject(MemDC, obj);
DeleteDC(MemDC);
return result;
}
HBITMAP TransparentCopy(HBITMAP hBmp, COLORREF Colour)
{
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
HDC DC = GetDC(NULL);
HDC MemDC = CreateCompatibleDC(DC);
HBITMAP result = CreateCompatibleBitmap(DC, bm.bmWidth, bm.bmHeight);
HGDIOBJ obj = SelectObject(MemDC, result);
DrawTransparent(hBmp, MemDC, Colour);
SelectObject(MemDC, obj);
DeleteDC(MemDC);
return result;
}
Example (same as you were trying to do):
Image imgImage = Image("blah.bmp");
HBITMAP global = TransparentCopy((HBITMAP)imgImage, RGB(255, 0, 0));
SetMenuItemBitmaps(......., global, global);
Then set the menu bitmap to whatever you want.. NOTE: I could not get the above to draw black as transparent. I have no idea why.. All other colours work except black :S. Also note that I did not try any of the above on menus..
Edited by triumphost
cambalinho 142 Practically a Posting Shark
please try with menus. and with gif files(where i see the problem)
Edited by cambalinho
triumphost 120 Posting Whiz
Try this:
For bitmaps, png's, gif's that DO NOT have an alpha channel:
bool isSimilar(COLORREF A, COLORREF B, unsigned int t)
{
unsigned char AR = GetRValue(A);
unsigned char AG = GetGValue(A);
unsigned char AB = GetBValue(A);
unsigned char BR = GetRValue(B);
unsigned char BG = GetGValue(B);
unsigned char BB = GetBValue(B);
return static_cast<unsigned int>((AR - BR) * (AR - BR) + (AG - BG) * (AG - BG) + (AB - BB) * (AB - BB)) <= (t * t);
}
void setAlphas(HBITMAP hBmp, int w, int h, COLORREF TransparentColour, COLORREF BackgroundColour, unsigned int Tolerance)
{
BITMAPINFOHEADER bminfoheader;
ZeroMemory(&bminfoheader, sizeof(BITMAPINFOHEADER));
bminfoheader.biSize = sizeof(BITMAPINFOHEADER);
bminfoheader.biWidth = w;
bminfoheader.biHeight = h;
bminfoheader.biPlanes = 1;
bminfoheader.biBitCount = 32;
bminfoheader.biCompression = BI_RGB;
HDC DC = CreateCompatibleDC(0);
unsigned char* pPixels = new unsigned char[w * h * 4];
memset(pPixels, 0, w * h * 4);
GetDIBits(DC, hBmp, 0, h, pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS);
unsigned char* p = pPixels;
for (int i = 0; i < h; ++i)
{
for (int j = 0; j < w; ++j)
{
unsigned char* B = p++;
unsigned char* G = p++;
unsigned char* R = p++;
unsigned char* A = p++;
if (isSimilar(RGB(*R, *G, *B), TransparentColour, Tolerance))
{
*R = GetRValue(BackgroundColour);
*G = GetGValue(BackgroundColour);
*B = GetBValue(BackgroundColour);
*A = 0;
}
}
}
SetDIBits(DC, hBmp, 0, h, pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS);
DeleteDC(DC);
delete[] pPixels;
}
case WM_PAINT:
{
static AutoGDI* gdi = new AutoGDI(L"C:/Users/Brandon/Desktop/small.png");
setAlphas(gdi->getHBITMAP(), 50, 63, RGB(0, 0, 0), RGB(240, 240, 240), 10); //although it's not costly, you should try to only call this once..
SetBitmapMenu(gdi->getHBITMAP());
}
break;
In the above code:
(0, 0, 0) is the colour that will be considered TRANSPARENT!
(240, 240, 240) is the background colour of the menu.
10 is the threshold/tolerance to determine whether or not two colours match. 0 is the lowest threshold.
Play around with the threshold as much as you want and decide what's best for you.
---------------------------------------------------------------------
For bitmaps, png's, or gifs that ALREADY HAVE an alpha channel:
void setAlphasWithChannel(HBITMAP hBmp, int w, int h, COLORREF BackgroundColour)
{
BITMAPINFOHEADER bminfoheader;
ZeroMemory(&bminfoheader, sizeof(BITMAPINFOHEADER));
bminfoheader.biSize = sizeof(BITMAPINFOHEADER);
bminfoheader.biWidth = w;
bminfoheader.biHeight = h;
bminfoheader.biPlanes = 1;
bminfoheader.biBitCount = 32;
bminfoheader.biCompression = BI_RGB;
HDC DC = CreateCompatibleDC(0);
unsigned char* pPixels = new unsigned char[w * h * 4];
memset(pPixels, 0, w * h * 4);
GetDIBits(DC, hBmp, 0, h, pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS);
unsigned char* p = pPixels;
for (int i = 0; i < h; ++i)
{
for (int j = 0; j < w; ++j)
{
unsigned char* B = p++;
unsigned char* G = p++;
unsigned char* R = p++;
unsigned char* A = p++;
if (*A == 0)
{
*R = GetRValue(BackgroundColour);
*G = GetGValue(BackgroundColour);
*B = GetBValue(BackgroundColour);
}
}
}
SetDIBits(DC, hBmp, 0, h, pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS);
DeleteDC(DC);
delete[] pPixels;
}
case WM_PAINT:
{
static AutoGDI* gdi = new AutoGDI(L"C:/Users/Brandon/Desktop/small.png");
setAlphas(gdi->getHBITMAP(), 50, 63, RGB(240, 240, 240)); //although it's not costly, you should try to only call this once..
SetBitmapMenu(gdi->getHBITMAP());
}
break;
DO NOT forget to delete your AutoGDI
or image
instance when the application closes!
Edited by triumphost
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.