анимация c ++ gdi не работает - PullRequest
2 голосов
/ 10 августа 2010

Я пытаюсь создать анимацию шара, используя gdi, но я не могу заставить ее работать.я создал шарик с помощью этой

   Graphics graphics(hdc);

ручки (цвет (255, 0, 0, 255));graphics.DrawEllipse (& pen, sf, 0, 10, 10);у меня есть цикл while, который зацикливается и добавляет 1 к значению sf в основном как этот sf ++;чем я пытаюсь перекрасить окно (оно не работает), так что в итоге я получу более одного круга; / вот цикл (цикл int WM_PAINT)

while(sd==1)//sd equals 1
    {
        sf++;
        onPaint(hdc);
        InvalidateRect (hWnd, NULL, TRUE);// this should repaint the window but it doesn't
        UpdateWindow(hWnd);
    }

заранее спасибо, Рами

Ответы [ 4 ]

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

Для достижения анимации я бы предложил вам использовать таймер.Например:

int OnCreate(HWND window, WPARAM wParam, LPARAM lParam)
{
   SetTimer(window, TIMER_ID, 1000, 0);
   return 0;
}

теперь окно будет получать сообщения WM_TIMER каждую секунду (1000 мс).Вы должны обработать их:

int OnTimer(HWND window, WPARAM wParam, LPARAM lParam)
{
   if(TIMER_ID == wParam)
   {
      /*do stuff*/
      InvalidateRect(window, NULL, TRUE);//force window to repaint
   }
   return 0;
}

тогда вам нужно обработать сообщение WM_PAINT, чтобы сделать рисунок

int OnPaint(HWND window, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC dc = BeginPaint(&ps);
   Graphics graphics(hdc);
   graphics.Draw...
   EndPaint(&ps);
   return 0;
}
2 голосов
/ 10 августа 2010

Вы понимаете, что увеличиваете sf в цикле с условием (sd == 1), верно? Это, конечно, будет просто зацикливаться бесконечно или никогда не будет введено, потому что значение sd никак не изменяется. Вы использовали отладчик вообще здесь? В любом случае, зачем вам такая петля? Вы не должны вызывать OnPaint в цикле.

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

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

Я нашел пример на MSDN, который показывает, как рисовать вещи в чистом win32.

Вы не должны вызывать Invalidate или Updatewindow в WM_PAINT, поскольку UpdateWindow отправляет новое WM_PAINT-событие, и недействительные данные накапливаются до события next wm_paint.

Вы должны разделить ваш код на две функции: одну для выполнения движения, а другую для рисования круга в текущем месте.

Ваша функция Mover может вызываться из любого места (возможно, в функции обработчика таймера?) И должна заканчиваться на

InvalidateRect (hWnd, NULL, TRUE);
UpdateWindow(hWnd);

Чтобы пометить свою клиентскую область для перерисовки и уведомить свое окно о перерисовке.

Ваша функция Draw () должна считывать положение, заданное с помощью функции перемещения, и просто рисовать окружность вокруг этого места.

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

UPDATE

Вам не хватало команды UpdateWindow в вашей функции обновления Ваша OnPaint-функция вызывается только тогда, когда ваше приложение получает сообщение WM_PAINT, поэтому вам необходимо отправить его.

UpdateWindow служит для этой цели

VOID update(HDC hdc,HWND hWnd) 
{ 
    sf++; 
    FillRect(hdc,rect,(HBRUSH)(COLOR_WINDOW+1)); 
    InvalidateRect (hWnd, NULL, TRUE); 
    UpdateWindow(hWND);//<- This Line sends a wm_paint-message to your window in order to make it redraw itself
} 
//i didn't do any changes to the onPaint functon but here is the code for it 
VOID onPaint(HDC hdc) 
{ 
    Graphics graphics(hdc); 
    Pen pen(Color(255, 0, 0, 255)); 
    graphics.DrawEllipse(&pen, sf , 0, 10, 10); 
} 

//here is the while loop 
while(sd==1) 
{   onPaint(hdc); 
    update(hdc,hWnd); 
} 
0 голосов
/ 10 августа 2010

InvalidateRect отправляет сообщение WM_ERASEBKGND, и если у вас нет элемента hbrBackground (кисть для перекраски фона), определенного в структуре WNDCLASS при создании окна, он не будет перерисовывать фон, если вы сами не обработаете сообщение WM_ERASEBKGND .

Если это не проблема, то, возможно, из-за того, что вы вызываете UpdateWindow напрямую, а не опрашиваете и обрабатываете сообщения, сообщение WM_ERASEBKGND никогда не обрабатывается. Попробуйте переписать предыдущий круг цветом фона, прежде чем рисовать новый.

Или вызовите SendMessage с WM_ERASEBKGRND в качестве сообщения.

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