Как определить, закрашен ли последний кадр в буферной анимации рисования? - PullRequest
0 голосов
/ 18 июня 2020

Я использую BeginBufferedAnimation() во время WM_PAINT для анимации настраиваемого элемента управления (плавное затухание). Я знаю, когда нарисован первый кадр анимации; когда я вызываю EndBufferedAnimation() с fUpdateTarget = TRUE. Я могу определить, выполняется ли анимация, проверив возвращаемое значение из BufferedPaintRenderAnimation().

Вопрос: как мне узнать, когда нарисован последний кадр анимации?

Я не мог не нашел вызова API, который мог бы это сделать.

Одна вещь, которая приходит в голову, - это использовать GetTickCount(), чтобы определить время, прошедшее с момента вызова EndBufferedAnimation(), и сравнить его с dwDuration член структуры BP_ANIMATIONPARAMS. Однако я не уверен, что этот метод очень точен.

Есть ли другой (надежный) способ определить, рисует ли WM_PAINT последний кадр анимации?

EDIT

Очевидно, что проверка прошедшего времени не работает, если анимация преждевременно остановлена ​​вызовом BufferedPaintStopAllAnimations() или аннулирует анимируемую часть клиентской области.

EDIT 2

Это мой (упрощенный) код WM_PAINT:

PAINTSTRUCT ps;

HDC DC = BeginPaint(Handle, &ps);

if (DC != NULL)
{
    // If animation in progress, paint the next frame.
    if (!BufferedPaintRenderAnimation(Handle, DC))
    {
        BP_ANIMATIONPARAMS ap = {sizeof(ap)};
        ap.style      = BPAS_LINEAR;
        ap.dwDuration = 1000;

        RECT R;

        GetClientRect(Handle, &R);

        HDC hdcFrom, hdcTo;

        HANIMATIONBUFFER Animation = BeginBufferedAnimation(Handle, DC, &R, BPBF_COMPATIBLEBITMAP, NULL, &ap, &hdcFrom, &hdcTo);

        if (Animation)
        {
            if (hdcFrom) Paint(hdcFrom, &R, OldState);
            if (hdcTo  ) Paint(hdcTo,   &R, NewState);

            // Paint the first frame.
            EndBufferedAnimation(Animation, true);
        }
        else
            Paint(DC, &R, NewState);
    }
    else
    {
        // Here, I want to check if BufferedPaintRenderAnimation() painted the last frame.
    }

    EndPaint(Handle, &ps);
}

EDIT 3

Мой пользовательский элемент управления имеет дочерний элемент управления, который необходимо анимировать синхронно c с его родительским элементом. Для этого я позволяю дочернему элементу управления рисовать себя в первом и последнем кадре анимации, отправляя ему сообщение WM_PRINT внутри моего метода Paint(). Дочерний элемент управления получает свое сообщение WM_PAINT после рисования родительского элемента. Чтобы предотвратить рисование дочернего элемента управления во время анимации родительского элемента, я хотел скрыть дочерний элемент управления при запуске анимации и показать его снова после завершения анимации.

Поскольку я не смог найти надежный способ чтобы определить, когда анимация заканчивается, я решил не скрывать дочерний элемент управления. Вместо этого я избегаю перерисовки дочернего элемента управления с помощью RedrawWindow(ChildHandle, NULL, NULL, RDW_VALIDATE | RDW_NOFRAME) после вызова EndBufferedAnimation() и когда BufferedPaintRenderAnimation() возвращает true. Таким образом, BufferedPaintRenderAnimation() закрашивает дочерний элемент управления в его конечном состоянии после завершения анимации, поэтому дочерний элемент управления не обязан.

1 Ответ

0 голосов
/ 20 июня 2020

Я нашел лучшее решение моей проблемы.

См. ИЗМЕНИТЬ 3.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...