Я использую 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()
закрашивает дочерний элемент управления в его конечном состоянии после завершения анимации, поэтому дочерний элемент управления не обязан.