sazr
sazr

Reputation: 25928

Using AlphaBlend to draw slightly transparent rectangle fails

I am attempting to draw a slightly transparent blue rectangle in Native Win32 C++. I am using the function AlphaBlend() but its not drawing anything onto the window, nothing happens.

My Problem: When I run my function to draw a slightly transparent rectangle, it doesn't get shown on my window. I have a feeling I am doing this wrong, maybe I should be using a HBITMAP?

Can you tell me what I need to do to get my function to draw a slightly transparent rectangle on the window?

Also I'm aware of GDI+ but I want to avoid it for now because I am getting alot of compile/include errors when I use that library plus I want to go as low/native as possible without the help of libraries that do everything for me.

bool paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, unsigned int opacity)
{
    HDC tempHdc         = CreateCompatibleDC(hdc);
    BLENDFUNCTION blend = {AC_SRC_OVER, 0, 127, AC_SRC_ALPHA};

    SetDCPenColor(tempHdc, RGB(255,255,0));
    SetDCBrushColor(tempHdc, RGB(255,255,0));
    Rectangle(tempHdc, dim.left, dim.top, dim.right, dim.bottom);

    return bool(AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHdc, dim.left, dim.top, dim.right, dim.bottom, blend)); 
}
// Usage
case WM_PAINT:
{
   HDC hdc;
   PAINTSTRUCT ps;
   hdc = BeginPaint(hwnd, &ps);

   RECT a = {0,0,100,100};
   paintRect(hdc, a, RGB(255,255,0), RGB(255,255,0), 127); // 127 is 50% transparency right?

   EndPaint(hwnd, &ps);
}
break;

Upvotes: 4

Views: 10745

Answers (2)

Tony
Tony

Reputation: 1616

This will work:

bool paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, unsigned int opacity)
{
        HDC tempHdc         = CreateCompatibleDC(hdc);
        BLENDFUNCTION blend = {AC_SRC_OVER, 0, 127, 0};

        HBITMAP hbitmap;       // bitmap handle 
        BITMAPINFO bmi;        // bitmap header 
        // zero the memory for the bitmap info 
        ZeroMemory(&bmi, sizeof(BITMAPINFO));

        // setup bitmap info  
        // set the bitmap width and height to 60% of the width and height of each of the three horizontal areas. Later on, the blending will occur in the center of each of the three areas. 
        bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth = dim.right-dim.left;
        bmi.bmiHeader.biHeight = dim.bottom-dim.top;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = 32;         // four 8-bit components 
        bmi.bmiHeader.biCompression = BI_RGB;
        bmi.bmiHeader.biSizeImage = (dim.right-dim.left) * (dim.bottom-dim.top) * 4;

        // create our DIB section and select the bitmap into the dc 
        hbitmap = CreateDIBSection(tempHdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0x0);
        SelectObject(tempHdc, hbitmap);

        SetDCPenColor(tempHdc, RGB(0,0,255));
        SetDCBrushColor(tempHdc, RGB(0,0,255));
        FillRect(tempHdc, &dim, CreateSolidBrush(RGB(0,0,255)));

        return bool(AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHdc, dim.left, dim.top, dim.right, dim.bottom, blend)); 
}

Upvotes: 6

Serge
Serge

Reputation: 7694

CreateCompatibleDC function returns a compatible dc with a defualt bitmap of a size 1x1. In order to draw something usefull first of all you should select a more suitable bitmap of a right size. You can use CreateCompatibleBitmap function.

Basically you should do something like this:

HDC tempHdc         = CreateCompatibleDC(hdc);
// create a bitmap of a size you need, let's say it 100x100
int width = 100;
int height = 100;
HBITMAP canvas = CreateCompatibleBitmap(hdc, width, height);
// select new bitmap into context, don't forget to save old bitmap handle
HBITMAP oldBmp = SelectObject(tepmHdc, canvas);

BLENDFUNCTION blend = {AC_SRC_OVER, 0, 127, AC_SRC_ALPHA};

SetDCPenColor(tempHdc, RGB(255,255,0));
SetDCBrushColor(tempHdc, RGB(255,255,0));
Rectangle(tempHdc, dim.left, dim.top, dim.right, dim.bottom);

bool res = AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHdc, dim.left, dim.top, dim.right, dim.bottom, blend);
// reset the old bitmap
SelectObect(tempHdc, oldBmp);
// canvas is no longer needed and should be deleted to avoid GDI leaks
DeleteObject(canvas);

return res;

But seriously you should reconsider GDI+, try to figure out why you have all those compiler errors and fix them. GDI is very old and not so friendly, with manual resource management and quite painful to use.

Good luck.

Upvotes: 3

Related Questions