GDI根据位图和透明度创建蒙版

#include <windows.h>

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, 1, 1, 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, 0, 0, bitmap.bmWidth, bitmap.bmHeight, bitmapGraphicsDeviceContext, 0, 0, SRCCOPY);
    BitBlt(bitmapGraphicsDeviceContext, 0, 0, bitmap.bmWidth, bitmap.bmHeight, bitmapMaskGraphicsDeviceContext, 0, 0, SRCINVERT);

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

    // Voila!
    return bitmapMaskHandle;
}

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

    MSG msg = { 0 };
    WNDCLASS wc = { 0 };
    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, 0, 0, LR_LOADFROMFILE);
    g_bmpMask = createImageMask(g_bmp, RGB(255, 0, 0));

    if (!RegisterClass(&wc))
        return 1;

    if (!CreateWindow(wc.lpszClassName,
        L"Minimal Windows Application",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        0, 0, 640, 480, 0, 0, hInstance, NULL))
        return 2;

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

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, 0, 0, 184, 184, hdcMask, 0, 0, SRCCOPY);
    BitBlt(hdc, 184, 0, 184, 184, hdcBmp, 0, 0, SRCCOPY);
    EndPaint(hWnd, &ps);

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

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

    return 0;
}

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

    switch (message)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        break;

    case WM_PAINT:
        return HandleWmPaint(hWnd, wParam, lParam);

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

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

猜你喜欢

转载自www.cnblogs.com/strive-sun/p/12085165.html