在父窗口上绘制具有半透明效果的子窗口,并带有图像。

3

我需要在WS_OVERLAPPED窗口中制作鸟类动画(如下图所示)。动画由8个图像表示:

Animation

图像中的蓝色(即RGB(0,255,255))必须是透明的(请参见下面的屏幕截图)。

我想使用CreateWindowEx()(鸟由分层窗口表示)并带有WS_EX_LAYERED参数来完成此操作。不幸的是,鸟必须是WS_CHILD。在Windows 7中混合使用WS_EX_LAYERED | WS_CHILD是不合法的

Windows 8: 支持对顶级窗口和子窗口使用WS_EX_LAYERED样式。之前的Windows版本仅支持顶级窗口使用WS_EX_LAYERED

最终效果应如下所示(我已经为窗口绘制了背景 - 唯一的问题是鸟):

enter image description here

如何实现此效果?如何在父窗口中制作动画鸟?
如果您有任何实现具有透明背景颜色的鸟类动画的想法,请分享。

2个回答

2

由于动画在没有与窗口的交互时也会执行,因此我们需要一个计时器:

case WM_CREATE:
    // load resources
    SetTimer(hwnd, 0, 250, NULL); // set timer to 250 ms
return 0;

...

case WM_DESTROY:
    KillTimer(hwnd, 0);
    // release the resources
return 0;

我们可以在每个计时器滴答声中使整个窗口失效,但最好只重绘需要的部分。我们还将在此更新当前帧编号:

case WM_TIMER:
    frame_number++;
    if (frame_number >= 8)
        frame_number = 0;

    RECT rc = { 30, 30, 80, 80 }; // a rectangle from (30,30) to (80,80)
    InvalidateRect(hwnd, &rc, FALSE);
return 0;

然后,在WM_PAINT处理程序中绘制当前帧:
case WM_PAINT:
    // draw the sky

    SelectObject(hDCMem, hBird);
    TransparentBlt(hDC, 30, 30, 50, 50, hDCMem, frame_number * 51, 0, 50, 50, RGB(0, 255, 255)); // 51 is 50 (side of a bird frame) + 1 (gap between the frames)

    // draw the rest
return 0;

我忘了提到在这个项目中TransparentBlt()是被禁止的(我不知道为什么)。 - patryk.beza
1
@patryk.beza,BitBlt也被禁止了吗?如果没有,您可以使用Wine实现的TransparentBlt:http://source.winehq.org/git/wine.git/blob/HEAD:/dlls/gdi32/bitblt.c#l827?如果是,您如何绘制背景? - skink
我使用BitBlt绘制背景,这是不被禁止的。 - patryk.beza

2

我终于找到了如何做到这一点的方法。 这相当棘手。

完整的解决方案描述在这里 - winprog.org/tutorial/transparency.html
对于波兰读者,在这里有伟大的翻译

简要说明:

使位图具有透明部分的外观非常简单,只需使用黑白掩码图像以及我们想要看起来透明的颜色图像即可。

为了使效果正常工作,必须满足以下条件:首先,所有希望显示为透明的区域的颜色图像必须为黑色。其次,在我们希望透明的区域中,掩码图像必须为白色,其他地方则为黑色。颜色和掩码图像显示为此页面上最左侧的两个图像。

简要解决方案:

#define TRANSPARENCY_COLOR RGB(0, 255, 255)

birdBmp = (HBITMAP) LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
hbmpMask = CreateBitmapMask(birdBmp, TRANSPARENCY_COLOR);

绘画:

case WM_PAINT:
{
    hdc = BeginPaint(hWnd, &ps);

    HDC birdMaskHdc = CreateCompatibleDC(hdc);

    BITMAP bmInfo;
    GetObject(birdBmp, sizeof(bmInfo), &bmInfo);

    HBITMAP hbmpOld = (HBITMAP) SelectObject(birdMaskHdc, hbmpMask);

    BitBlt(hdc, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, birdMaskHdc, 0, 0, SRCAND);
    SelectObject(birdMaskHdc, birdBmp);
    BitBlt(hdc, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, birdMaskHdc, 0, 0, SRCPAINT);

    SelectObject(birdMaskHdc, hbmpOld);
    DeleteDC(birdMaskHdc);

    EndPaint(hWnd, &ps);
    break;
}

清理:

case WM_DESTROY:
{
    DeleteObject(hbmpMask);
    DeleteObject(birdBmp);
    PostQuitMessage(0);
    break;
}

创建位图掩码的函数:

HBITMAP CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent)
{
    HDC hdcMem, hdcMem2;
    HBITMAP hbmMask, hbmOld, hbmOld2;
    BITMAP bm;

    GetObject( hbmColour, sizeof( BITMAP ), & bm );
    hbmMask = CreateBitmap( bm.bmWidth, bm.bmHeight, 1, 1, NULL );

    hdcMem = CreateCompatibleDC( NULL );
    hdcMem2 = CreateCompatibleDC( NULL );

    hbmOld =( HBITMAP ) SelectObject( hdcMem, hbmColour );
    hbmOld2 =( HBITMAP ) SelectObject( hdcMem2, hbmMask );

    SetBkColor( hdcMem, crTransparent );

    BitBlt( hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY );
    BitBlt( hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem2, 0, 0, SRCINVERT );

    SelectObject( hdcMem, hbmOld );
    SelectObject( hdcMem2, hbmOld2 );
    DeleteDC( hdcMem );
    DeleteDC( hdcMem2 );

    return hbmMask;
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接