0

So I've found a lot of code samples, guides, and answers on SO about drawing an image to a layered window. I've tried using pure HBITMAPS and the WIC libs to draw, and now I'm on to GDI+ to draw (which is much simpler and is seemingly easier to use, and thus far it has solved a lot of errors that were caused by faulty WIC code).

I'm currently stuck on UpdateLayeredWindow. No matter what I try I can't get it to work. Right now, it's returning 87, or ERROR_INVALID_PARAMETER. The question is, which one is incorrect? I'm stumped! The below code seems to be the solution other than the fact that UpdateLayeredWindow is refusing to work.

What am I doing wrong?

Here is the code that sets up the HDC/bitmap information/graphics object.

// Create DC
_oGrphInf.canvasHDC = GetDC(_hwndWindow);

// Create drawing 'canvas'
_oGrphInf.lpBits = NULL;
_oGrphInf.bmpCanvas = CreateDIBSection(_oGrphInf.canvasHDC,
            &_oGrphInf.bmpWinInformation, DIB_RGB_COLORS,
            &_oGrphInf.lpBits, NULL, 0);

// Create graphics object
_oGrphInf.graphics = new Gdiplus::Graphics(_oGrphInf.canvasHDC);

The above works fine - I step through it and all of the pointers work.

And here is the method that draws the PNG.

void Splash::DrawPNG(PNG* lpPNG, int x, int y)
{
    LOGD("Drawing bitmap!");

    HDC hdcMem = CreateCompatibleDC(_oGrphInf.canvasHDC);

    // Select
    HBITMAP bmpOld = (HBITMAP)SelectObject(hdcMem, _oGrphInf.bmpCanvas);

    Gdiplus::Color trans(0, 0, 0, 0);
    _oGrphInf.graphics->Clear(trans);

    _oGrphInf.graphics->DrawImage(lpPNG->GetImage(), x, y);

    _oGrphInf.graphics->Flush();

    SIZE szSize = {_oGrphInf.bmpWinInformation.bmiHeader.biWidth,
                    _oGrphInf.bmpWinInformation.bmiHeader.biHeight};

    // Setup drawing location
    POINT ptLoc = {0, 0};
    POINT ptSrc = {0, 0};

    // Set up alpha blending
    BLENDFUNCTION blend = {0};
    blend.BlendOp = AC_SRC_OVER;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;
    blend.BlendFlags = 0;

    // Update
    if(UpdateLayeredWindow(_hwndWindow, _oGrphInf.canvasHDC, &ptLoc,
                                &szSize, hdcMem, &ptSrc,
                                (COLORREF)RGB(0, 0, 0),
                                &blend, ULW_ALPHA) == FALSE)
        LOGE("Could not update layered window: %u", GetLastError());

    // Delete temp objects
    SelectObject(hdcMem, bmpOld);
    DeleteObject(hdcMem);
    DeleteDC(hdcMem);
}

Pulling my hair out! Help?

EDIT: I just decided to re-write the call to UpdateLayeredWindow function, which solved the incorrect parameter issue. Here is what I came up with. However, it still does not work. What am I doing wrong?

UpdateLayeredWindow(_hwndWindow, _oGrphInf.canvasHDC,
            NULL, NULL, hdcMem, &ptLoc,
            RGB(0, 0, 0), &blend, ULW_ALPHA)
Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145

1 Answers1

1

For alpha information to be preserved in drawing operations, you have to make your Graphics object based on a memory-backed Bitmap object, not an HDC, and of course your Bitmap needs to be in a format with an alpha channel.

You'll need to use this Bitmap constructor: http://msdn.microsoft.com/en-us/library/ms536315%28v=vs.85%29.aspx

Just give that a stride of 0, a pointer to your DIB's bits, and PixelFormat32bppPARGB.

Then use Graphics::FromImage to create your Graphics object.

I've never used UpdateLayeredWindow, so I can't verify that that side of it is correct.

Esme Povirk
  • 3,004
  • 16
  • 24
  • Also, you probably should be drawing your image at (0,0), as your layered window should only be big enough to show your image. Or, even simpler, skip the Graphics object entirely and copy the bits from your Bitmap to your dib section using Bitmap::Lock with a user input buffer. – Esme Povirk Jul 21 '12 at 05:27