А вообще функция есть в 2000 - TransparentBlt - можно с ее помощью можно создать битмап с прозрачным фоном быстро и без шума.
Есть еще один не совсем простой способ, но зато удобный иногда. Надо считать битмап как бинарный ресурс, формат DIB-а - известен, поменять в таблице цветов соответствующий цвет. А потом из этих, измененных в нашу пользу, данных создать пригодный для использования битмап.
Код примерно такой:
Сначала загружаем ресурс как бинарный:
Code:
HGLOBAL handle = ::LoadResource(AfxGetInstanceHandle(), FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_LOGO), RT_BITMAP));
Потом получаем указатель на эти бинарные данные.
Code:
BITMAPINFO* bitmapInfo = (BITMAPINFO*)(::LockResource(handle));
BITMAPINFOHEADER* bitmapHeader = &bitmapInfo->bmiHeader;
Считаем количество используемых цветов в битмапе согласно его формату:
Code:
int colorCount = 1 << bitmapHeader->biBitCount;
int size = sizeof(BITMAPINFOHEADER) + colorCount * sizeof(RGBQUAD);
Копируeм заголовок битмапа в укромное место:
Code:
BITMAPINFO* bitmapInfoCopy = (BITMAPINFO*)(new BYTE [size]);
memcpy(bitmapInfoCopy, bitmapInfo, size);
Извлекаем таблицу цветов из заголовка:
Code:
DWORD* colorTable = (DWORD*)(bitmapInfoCopy->bmiColors);
Заменяем белый цвет (255, 255, 255) предполагаемого фона из битмапа на серый BTN_FACE - цвет формы, в частности у меня там в диалоге лого рисовалось.
Code:
#define RGB_TO_RGBQUAD(r,g,b) (RGB(b,g,r))
#define CLR_TO_RGBQUAD(clr) (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)))
DWORD bkColor = CLR_TO_RGBQUAD(GetSysColor(COLOR_BTNFACE));
for (int i = 0; i < colorCount; i++)
if (colorTable[i] == RGB_TO_RGBQUAD(255, 255, 255))
colorTable[i] = bkColor;
Извлекаем указатель на пиксельные данные битмапа - находящиеся прямо за заголовком.
Code:
BYTE* bitmapData = (BYTE*)(bitmapHeader + 1);
bitmapData += colorCount * sizeof(RGBQUAD);
Создаем реальный битмап, подставив ему новый заголовок с "правильными" цветами в таблице.
Code:
CClientDC screenDC(NULL);
СBitmap logo;
logo.Attach(CreateDIBitmap(screenDC.m_hDC, bitmapHeader, CBM_INIT, bitmapData, bitmapInfoCopy, DIB_RGB_COLORS));
Ну и наконец удаляем копию заголовка:
Code:
delete [] (BYTE*)bitmapInfoCopy;
Копия заголовка нужна, потому что данные полученные по указателю на ресурс нельзя изменить - они readonly - по крайней мере в NT и 2000.
Ну и напоследок, 100% гарантии не даю, но для простеньких битмапов у меня работало. Может не работать на нестандартных битмапах использующих различные расширения - предусмотренные форматом. Умышленных багов в коде, как это положено традицией - нет, это все таки не журнал
По-крайней мере это проще, чем вручную создавать маску и конструровать битмап, если нужно чтобы работало под 95/98/NT.