3

ウィンドウで鳥のアニメーションを作成する必要がありWS_OVERLAPPEDます(以下を参照)。アニメーションは8つの画像で表されます。

アニメーション

画像の青色(つまりRGB(0, 255, 255))は透明である必要があります(下のスクリーンショットを参照)。

引数CreateWindowEx()付きで(鳥はレイヤードウィンドウで表されます)これを実行したかったのです。WS_EX_LAYERED残念ながら鳥はしなければなりませんWS_CHILD。混合はWindows7ではWS_EX_LAYERED | WS_CHILD 合法ではありません:

Windows 8: WS_EX_LAYEREDスタイルは、トップレベルウィンドウと子ウィンドウでサポートされています以前のバージョンのWindowsは、トップレベルのウィンドウに対してのみWS_EX_LAYEREDをサポートします。

最終的な効果は次のようになります(ウィンドウの背景は既にペイントしています。唯一の問題は鳥です)。

ここに画像の説明を入力してください

どうすればこの効果を達成できますか?親ウィンドウで鳥をアニメートする方法は?
透明な背景色で鳥のアニメーションを実装する方法について何かアイデアがあれば、共有してください。

4

2 に答える 2

2

私はついにそれを行う方法を見つけました。かなりトリッキーです。

ソリューションの完全な説明は、winprog.org / tutorial/transparency.htmlから入手できます。
ポーランド語の読者にとって、ここは素晴らしい翻訳です。

簡単なアイデア:

ビットマップに透明なセクションがあるように見せることは非常に簡単で、透明に見せたいカラー画像に加えて、白黒のマスク画像を使用する必要があります。

効果を正しく機能させるには、次の条件を満たす必要があります。まず、透明として表示するすべての領域でカラー画像を黒にする必要があります。次に、マスク画像は、透明にしたい領域では白で、他の領域では黒である必要があります。カラー画像とマスク画像は、このページのサンプル画像の左端の2つの画像として表示されます。

簡単な解決策:

#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;
 }
于 2013-03-11T22:35:07.907 に答える
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;
于 2013-03-10T19:56:33.470 に答える