Search code examples
cwindowsapiwinapibmp

Set bitmap background the same pixels as the bitmap behind it - Windows API


I was trying to print a .bmp when I pressed a button, but this image would have to have "transparency".

I thought about changing the color of each pixel. This .bmp would be in front of another one, so what I want to do is: take the color of the pixels from the .bmp behind and paint the background of the front one with them.

The problem:

I imagine this could be done, considering that the background of the .bmp is white, just identifying if a pixel is white and changing its color.

However, I was not successful in trying to do this... I tried several references to base myself, none of them worked.

I tried this one: I tried to edit it to change the background pixels of the .bmp when they are white, to the pixels of the .bmp behind it. I was not successful, the pixels were all scrambled.

I also tried this one: the image was black and white (this has already been explained in the comments below).

I haven't find an example of the TransparentBlt() function usage with bitmaps to base myself on, I already tried to use it, but the image remained the same. here's my whole code:

#define _WIN32_WINNT 0x0500  /* tem ficar na primeira linha do código */
#define WINVER 0x0600
#include <windows.h>
#include <wingdi.h>

#define WM_CREATE 0x0001
#define WM_DESTROY 0x0002

#define ID_IMAGE1 1
#define ID_IMAGE2 2
#define ID_IMAGE3 3

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void LoadMyImage(void);
void LoadMyImage2(void);
void LoadMyImage3(void);

HBITMAP hBitmap;
HBITMAP hBitmap2;
HBITMAP hBitmap3;
POINT posicao;
int x, y;
HWND hWnd = GetConsoleWindow();

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR lpCmdLine, INT nCmdShow) {

    MSG  msg;
    WNDCLASSW wc = {0};
    wc.lpszClassName = L"Static image";
    wc.hInstance     = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc   = WndProc;
    wc.hCursor       = LoadCursor(0,IDC_ARROW);


    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"MLG antivirus",
                  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                  100, 100, 1001, 601, 0, 0, hInstance, 0);

    ShowWindow(hWnd, SW_MINIMIZE);
    //won't hide the window without SW_MINIMIZE
    ShowWindow(hWnd, SW_HIDE);

    while (GetMessage(&msg, NULL, 0, 0)) {

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
    WPARAM wParam, LPARAM lParam) {

    HWND hsti;
    HWND hBitmapButton;
    HWND hitm;

    switch(msg) {

        case WM_CREATE:

            LoadMyImage();
            hsti = CreateWindowW(L"Static", L"",
                WS_CHILD | WS_VISIBLE | SS_BITMAP,
                0, 0, 300, 300, hwnd, (HMENU) ID_IMAGE1, NULL, NULL);

            SendMessage(hsti, STM_SETIMAGE,
                (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap);

            LoadMyImage2();
            hBitmapButton = CreateWindowW(L"BUTTON", L"", WS_CHILD | WS_VISIBLE
                | BS_PUSHBUTTON | BS_BITMAP,
                334, 291, 316, 136, hwnd, (HMENU)ID_IMAGE2, NULL, NULL);

            SendMessage(hBitmapButton, BM_SETIMAGE,
                (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap2);
            break;

        case WM_COMMAND:

            if (LOWORD(wParam) == ID_IMAGE2) {
                GetCursorPos(&posicao);
                x = posicao.x-127;
                y = posicao.y-150;

                LoadMyImage3();
                hitm = CreateWindowW(L"Static", L"",
                    WS_CHILD | WS_VISIBLE | SS_BITMAP,
                    x, y, 38, 38, hwnd, (HMENU) ID_IMAGE3, NULL, NULL);

                SendMessage(hitm, STM_SETIMAGE,
                    (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap3);

                Sleep(80);
                DeleteObject((HBITMAP)hBitmap3);
            }

            break;

        case WM_DESTROY:

            DeleteObject((HBITMAP)hBitmap);
            DeleteObject((HBITMAP)hBitmap2);
            PostQuitMessage(0);
            PostMessage(hWnd, WM_CLOSE, 0, 0);
            break;
    }

    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void LoadMyImage(void) {

    hBitmap = (HBITMAP) LoadImage(NULL, "antvirus.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

void LoadMyImage2(void) {

    hBitmap2 = (HBITMAP) LoadImage(NULL, "botao.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap2 == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

void LoadMyImage3(void) {

    hBitmap3 = (HBITMAP) LoadImage(NULL, "hitmarker.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap3 == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

I will attach the .bmp's:

hitmarker.bmp

antvirus.bmp

botao.bmp

The code in the answer below works, but I wanted the image to be printed when the button was pressed, that is, Case WM_COMMAND. I'm still trying to edit it, but thank you, it's very kind of you to help me. Thanks in advance.


Solution

  • The comments have given enough detailed information, all you have to do is use TransparentBlt.

    Minimal code example:

    #include <Windows.h>
    #pragma comment(lib,"Msimg32.lib")
    
    using namespace std;
    
    HBITMAP hBitmap;
    HBITMAP hBitmap3;
    
    void LoadMyImage(void) {
    
        hBitmap = (HBITMAP)LoadImage(NULL, L"C:\\Users\\xx\\Desktop\\PGUfb.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
        if (hBitmap == NULL) {
            MessageBox(NULL, L"Error while loading image", L"Error", MB_OK | MB_ICONERROR);
        }
    }
    
    void LoadMyImage3(void) {
    
        hBitmap3 = (HBITMAP)LoadImage(NULL, L"C:\\Users\\xx\\Desktop\\QZLMJ.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
        if (hBitmap3 == NULL) {
            MessageBox(NULL, L"Error while loading image", L"Error", MB_OK | MB_ICONERROR);
        }
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HDC memdc;
        HDC dcSkin;
        HBITMAP hOldMemBmp;
        HBITMAP hOldSkinBmp;
        switch (message)
        {   
        case WM_CREATE:
        {
            LoadMyImage();
            LoadMyImage3();
        }
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            // TODO: Add any drawing code that uses hdc here...
            memdc = CreateCompatibleDC(hdc);
            dcSkin = CreateCompatibleDC(hdc);
            hOldMemBmp = (HBITMAP)SelectObject(memdc, hBitmap);
            hOldSkinBmp = (HBITMAP)SelectObject(dcSkin, hBitmap3);
            TransparentBlt(memdc, 200, 100, 38,38, dcSkin, 0, 0, 38, 38, RGB(255, 255, 255));
            BitBlt(hdc, 0, 0, 988, 562, memdc, 0, 0, SRCCOPY);    
            DeleteObject(hOldSkinBmp);
            DeleteObject(hOldMemBmp);
            DeleteDC(memdc);
            DeleteDC(dcSkin);
            EndPaint(hwnd, &ps);
        }
        break;
        case WM_DESTROY:
            DeleteObject(hBitmap);
            DeleteObject(hBitmap3);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    };
    
    HINSTANCE hinst;
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
        HWND hwnd;
    
        hinst = GetModuleHandle(NULL);
        // create a window class:
        WNDCLASS wc = {};
        wc.lpfnWndProc = WndProc;
        wc.hInstance = hinst;
        wc.lpszClassName = L"win32";
    
        // register class with operating system:
        RegisterClass(&wc);
    
        // create and show window:
        hwnd = CreateWindow(L"win32", L"My program", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 0, 1000, 800, NULL, NULL, hinst, NULL);
    
        if (hwnd == NULL) {
            return 0;
        }
    
        ShowWindow(hwnd, SW_SHOW);
    
    
        MSG msg = {};
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
    }
    

    Debug:

    enter image description here