C ++ GDI рисование проблемы эллипса - PullRequest
0 голосов
/ 10 августа 2010

хорошо, я могу нарисовать эллипс, проблема в том, что я пытаюсь нарисовать один эллипс, но измените его значение x на другое. вот так я рисую один эллипс и значение x равно 1 через десять секунд. Я хочу, чтобы значение x было равно 10, но, похоже, я создаю новый эллипс со значением x 10. вот мой код

while(sd==1)//sd equal 1 
{
    sf++;//sf equals 1
    onPaint(hdc);
    InvalidateRect(hWnd,0,true);
}
//on paint function
VOID onPaint(HDC hdc)
{
   Graphics graphics(hdc);
   Pen      pen(Color(255, 0, 0, 255));
   graphics.DrawEllipse(&pen,sf , 0, 50, 50);
}

хорошо, я думал, что недействительный прямоугольник очистит все, что было нарисовано, и перекрасит его, но это не сработало

Ответы [ 3 ]

0 голосов
/ 10 августа 2010

Если вы хотите сделать анимацию, вам лучше установить таймер.

Использование InvalidateRect в качестве способа генерации WM_PAINTs кажется излишним, оно сделает гораздо больше, чем это. Вместо этого вы можете рисовать непосредственно в вызове OnTimer, поскольку он находится вне WM_PAINT, вам необходимо получить контекст устройства с помощью GetDC.

Например, если вы можете использовать функцию DrawFrame (HDC hDC). OnTimer обновит текущую позицию и вызовет DrawFrame, OnPaint вызовет DrawFrame, но не обновит позицию (таким образом, если вы хотите остановить анимацию, у вас будет последний кадр рисовать).

DrawFrame очистит фон (возможно, с FillRect) и нарисует круг в новой позиции. Если у вас большая область, это будет мерцать, чтобы избежать этого, как Том предложил, вы можете использовать DC памяти и HBITMAP для двойного буфера.

0 голосов
/ 11 августа 2010

InvalidateRect помечает окно как "недействительное", но это не приводит к тому, что стирание и перерисовка происходят сразу. Стирание и рисование происходят только тогда, когда работает насос сообщений (например, цикл с GetMessage и DispatchMessage). Когда очередь сообщений иссякает, GetMessage будет синтезировать сообщения WM_ERASEBKGND и WM_PAINT для недопустимых окон. Когда эти сообщения отправляются в оконную процедуру, окно получает возможность рисовать.

Ваша onPaint функция только рисует, но не стирает. А поскольку ваш цикл никогда не завершается, насос сообщений никогда не запускается.

Для простых анимаций решением является SetTimer. В вашем обработчике для сообщений WM_TIMER обновите переменные для одного кадра, вызовите InvalidateRect и return (что позволяет насосу сообщений продолжать работать). Появится сообщение об удалении и рисовании, затем таймер снова сработает, и вы получите следующий кадр.

0 голосов
/ 10 августа 2010

Вы не должны пытаться нарисовать несколько кадров анимации за один снимок.

Сохраните вашу переменную sf где-нибудь, а в OnPaint(), увеличьте sf, нарисуйте один эллипс иcall Invalidate()

Invalidate вызовет повторный вызов OnPaint().

Это должно сработать, но будет очень мерцающим :) Мерцание можно исправить с помощью двойной буферизации.

...