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)
有帮助吗?

解决方案

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top