GDI根据位图和透明度创建蒙版
阅读原文时间:2023年07月10日阅读:1

#include

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

HBITMAP g_bmp;
HBITMAP g_bmpMask;

HBITMAP createImageMask(HBITMAP bitmapHandle, const COLORREF transparencyColor) {
// For getting information about the bitmap's height and width in this context
BITMAP bitmap;

// Create the device contexts for the bitmap and its mask  
HDC bitmapGraphicsDeviceContext = CreateCompatibleDC(NULL);  
HDC bitmapMaskGraphicsDeviceContext = CreateCompatibleDC(NULL);

// The actual mask  
HBITMAP bitmapMaskHandle;

// 1. Generate the mask.  
GetObject(bitmapHandle, sizeof(BITMAP), &bitmap);  
bitmapMaskHandle = CreateBitmap(bitmap.bmWidth, bitmap.bmHeight, , , NULL);

// 2. Setup the device context for the mask (and the bitmap).  
SelectObject(bitmapGraphicsDeviceContext, bitmapHandle);  
SelectObject(bitmapMaskGraphicsDeviceContext, bitmapMaskHandle);

// 3. Set the background color of the mask.  
SetBkColor(bitmapGraphicsDeviceContext, transparencyColor);

// 4. Copy the bitmap to the mask and invert it so it blends with the background color.  
BitBlt(bitmapMaskGraphicsDeviceContext, , , bitmap.bmWidth, bitmap.bmHeight, bitmapGraphicsDeviceContext, , , SRCCOPY);  
BitBlt(bitmapGraphicsDeviceContext, , , bitmap.bmWidth, bitmap.bmHeight, bitmapMaskGraphicsDeviceContext, , , SRCINVERT);

// Clean-up  
DeleteDC(bitmapGraphicsDeviceContext);  
DeleteDC(bitmapMaskGraphicsDeviceContext);

// Voila!  
return bitmapMaskHandle;  

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

MSG msg = {  };  
WNDCLASS wc = {  };  
wc.lpfnWndProc = WndProc;  
wc.hInstance = hInstance;  
wc.hbrBackground = (HBRUSH)(COLOR\_BACKGROUND);  
wc.lpszClassName = L"minwindowsapp";

g\_bmp = (HBITMAP)LoadImage(hInstance, L"C:\\\\Users\\\\h2fM6d9.bmp", IMAGE\_BITMAP, , , LR\_LOADFROMFILE);  
g\_bmpMask = createImageMask(g\_bmp, RGB(, , ));

if (!RegisterClass(&wc))  
    return ;

if (!CreateWindow(wc.lpszClassName,  
    L"Minimal Windows Application",  
    WS\_OVERLAPPEDWINDOW | WS\_VISIBLE,  
    , , , , , , hInstance, NULL))  
    return ;

while (GetMessage(&msg, NULL, , ) > ) {  
    TranslateMessage(&msg);  
    DispatchMessage(&msg);  
}  
return ;  

}

LRESULT HandleWmPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;

HDC hdcScr = GetDC(NULL);  
HDC hdcBmp = CreateCompatibleDC(hdcScr);  
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcBmp, g\_bmp);

HDC hdcMask = CreateCompatibleDC(hdcScr);  
HBITMAP hbmOldMask = (HBITMAP)SelectObject(hdcMask, g\_bmpMask);

HDC hdc = BeginPaint(hWnd, &ps);  
BitBlt(hdc, , , , , hdcMask, , , SRCCOPY);  
BitBlt(hdc, , , , , hdcBmp, , , SRCCOPY);  
EndPaint(hWnd, &ps);

SelectObject(hdcMask, hbmOldMask);  
DeleteDC(hdcMask);

SelectObject(hdcBmp, hbmOld);  
DeleteDC(hdcBmp);  
ReleaseDC(NULL, hdcScr);

return ;  

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

switch (message)  
{  
case WM\_CLOSE:  
    PostQuitMessage();  
    break;

case WM\_PAINT:  
    return HandleWmPaint(hWnd, wParam, lParam);

default:  
    return DefWindowProc(hWnd, message, wParam, lParam);  
}  
return ;  

}

顺便说一句,这项技术是一种非常古老的实现方法,在GDI中引入的MaskBlt 可以取代它,它可以在一个调用中完成您想要的操作。但更进一步,MaskBlt在这一点上已经过时了。如果是想为游戏或类似游戏的游戏绘制精灵。实际上可能想要的是使用每个像素的Alpha加载PNG,并使用Alpha合成对其进行绘制。也可以使用GDI +或诸如FreeImage之类的开源图形库来实现。