c1727130
asked on
Problem drawing transparent bitmap using DrawTransparentBitmap exisitng ONLY in Win98 16bit color
Hello,
I'm using following function :
-------------------------- ---------- ---------- ---------- ---------- -----
void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, int xStart,
int yStart, COLORREF cTransparentColor)
{
BITMAP bm;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
POINT ptSize;
hdcTemp = CreateCompatibleDC(hdc);
SelectObject(hdcTemp, hBitmap); // Select the bitmap
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(hdcB ack, bmAndBack);
bmObjectOld = (HBITMAP)SelectObject(hdcO bject, bmAndObject);
bmMemOld = (HBITMAP)SelectObject(hdcM em, bmAndMem);
bmSaveOld = (HBITMAP)SelectObject(hdcS ave, 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);
// Set the background color of the source DC to the color.
// contained in the parts of the bitmap that should be transparent
cColor = SetBkColor(hdcTemp, cTransparentColor);
// 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);
// Set the background color of the source DC back to the original
// color.
SetBkColor(hdcTemp, cColor);
// 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 colored 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);
}
-------------------------- ---------- ---------- ---------- ---------- -----
I use function a lot and it works perfect. Recently , by chance i finded out
there's a problem in win98 ( second edition ) when using 16 BIT COLOR.
Here's example of how i use this function :
DrawTransparentBitmap(
m_hMemDC ,
HBITMAP(pictBubble),
nBubblePosX,
nBubblePosY,
CLR_TRANSPARENT);
Here's my define of transparent color ( "clean" CYAN )
#define CLR_TRANSPARENT RGB(0,255,255)
As i said , it works everywhere except win98 ( second edition ) when using 16 BIT COLOR.
As far as i know , each loaded image produces it's own palette. In some cases , it can
cause color to be changed to nearest color and obviously , transparency won't work in this
case since above function needs transparent color to be exact down to pixel.
So , i tried to use following to work it out :
cTransparentColor = GetNearestColor( hdc , CLR_TRANSPARENT );
But , it didn't work.
Need your help ( it's pretty urgent ) , thanks !
P.S. I just prefer solution that won't force me to change everything , but a small patch ;)
I'm using following function :
--------------------------
void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, int xStart,
int yStart, COLORREF cTransparentColor)
{
BITMAP bm;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
POINT ptSize;
hdcTemp = CreateCompatibleDC(hdc);
SelectObject(hdcTemp, hBitmap); // Select the bitmap
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
bmSave = CreateCompatibleBitmap(hdc
// Each DC must select a bitmap object to store pixel data.
bmBackOld = (HBITMAP)SelectObject(hdcB
bmObjectOld = (HBITMAP)SelectObject(hdcO
bmMemOld = (HBITMAP)SelectObject(hdcM
bmSaveOld = (HBITMAP)SelectObject(hdcS
// 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);
// Set the background color of the source DC to the color.
// contained in the parts of the bitmap that should be transparent
cColor = SetBkColor(hdcTemp, cTransparentColor);
// 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);
// Set the background color of the source DC back to the original
// color.
SetBkColor(hdcTemp, cColor);
// 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 colored 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(
DeleteObject(SelectObject(
DeleteObject(SelectObject(
DeleteObject(SelectObject(
// Delete the memory DCs.
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
}
--------------------------
I use function a lot and it works perfect. Recently , by chance i finded out
there's a problem in win98 ( second edition ) when using 16 BIT COLOR.
Here's example of how i use this function :
DrawTransparentBitmap(
m_hMemDC ,
HBITMAP(pictBubble),
nBubblePosX,
nBubblePosY,
CLR_TRANSPARENT);
Here's my define of transparent color ( "clean" CYAN )
#define CLR_TRANSPARENT RGB(0,255,255)
As i said , it works everywhere except win98 ( second edition ) when using 16 BIT COLOR.
As far as i know , each loaded image produces it's own palette. In some cases , it can
cause color to be changed to nearest color and obviously , transparency won't work in this
case since above function needs transparent color to be exact down to pixel.
So , i tried to use following to work it out :
cTransparentColor = GetNearestColor( hdc , CLR_TRANSPARENT );
But , it didn't work.
Need your help ( it's pretty urgent ) , thanks !
P.S. I just prefer solution that won't force me to change everything , but a small patch ;)
ASKER
So how can i deal with these RGB 5/6/6 ?
Any ideas ?
Any ideas ?
ASKER
Please refund points, thank you.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
One other thing, it is unrelated, are you certain you don't need to store the previous bitmap for SelectObject(hdcTemp, hBitmap);? I normally do as a precaution. I guess if you don't run out of GDI resources after a few hundred calls you don't need it.