3

Мне нужно сделать анимацию птицы в окне WS_OVERLAPPED (как показано ниже). Анимация представлена ​​8 изображений:Рисование полупрозрачного дочернего окна с изображением на родительском окне

Animation

Синий цвет на изображении (который RGB(0, 255, 255)) должен быть прозрачным (см рисунок ниже).

Я хотел сделать это, используя CreateWindowEx() (птица будет представлена ​​многослойным окном) с аргументом WS_EX_LAYERED. К сожалению, птица должна быть WS_CHILD. Смешивание WS_EX_LAYERED | WS_CHILDis not legal в Windows 7:

Windows 8: Стиль WS_EX_LAYERED поддерживается для окон верхнего уровня и дочерних окон. Предыдущие версии Windows поддерживают WS_EX_LAYERED только для окон верхнего уровня.

Окончательный эффект должен выглядеть следующим образом (я уже нарисовал фон окна - единственная проблема в том, птицу):

enter image description here

Как я могу добиться этого эффекта? Как оживить птицу в родительском окне?
Если у вас есть идея, как реализовать анимацию птиц с прозрачным цветом фона, пожалуйста, поделитесь.

ответ

2

Я, наконец, узнать, как это сделать. Это довольно сложно.

Полное описание решения доступно здесь - winprog.org/tutorial/transparency.html.
Для польских читателей здесь great translation.

Простая идея вкратце:

Давать растровые изображения видимость наличия прозрачных секций достаточно проста, и предполагает использование черно-белой маски изображения в дополнение к цвет изображения, который мы хотим посмотреть прозрачный.

Необходимо, чтобы эффект работал правильно: во-первых, цветное изображение должно быть черным во всех областях, которые мы хотим отображать как прозрачные. И во-вторых, изображение маски должно быть белым в областях, которые мы хотим прозрачно, и в другом месте. Изображения цвета и маски отображаются в виде двух левых изображений в примере на этой странице.

Простое решение вкратце:

#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; 
} 
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; 
+0

Я забыл упомянуть, что 'TransparentBlt()' запрещен в этом проекте (я не знаю, почему). –

+1

@ patryk.beza, также запрещен ли биттон? Если нет, вы можете использовать реализацию Wine для «TransparentBlt»: http://source.winehq.org/git/wine.git/blob/HEAD:/dlls/gdi32/bitblt.c#l827? Если да, как вы рисуете фон? – Joulukuusi

+0

Я рисую фон с помощью 'BitBlt', который не запрещен. –

Смежные вопросы