Анимация квадратов с помощью GDI C++

Я хочу анимировать движение нескольких квадратов. В этом примере я создаю два квадрата. Когда я строю и запускаю, я вижу эти 2 квадрата, но они не двигаются.

Я создал класс, который представляет квадрат

#pragma once
#include <windows.h>

class Square {


private:
     int x,y;

     int moveWith_x, moveWith_y;

public:
    void DrawSquare(HDC,int,int,int,int);
    void MoveSquare(int,int);

    Square(void);
    ~Square(void);
};

И файл реализации (здесь я создаю квадраты, используя функцию Rectangle в DrawSquare) и пытаюсь анимировать движение в MoveSquares:

    #include "Square.h"

    void Square::DrawSquare(HDC hdc,int rx,int ry, int lx, int ly) {

        Rectangle(hdc,rx,ry,lx,ly); 
    }

void Square::MoveSquare(int mod_x_Size,int mod_y_Size) {

        x=x+ moveWith_x;
        y=y+ moveWith_y;

            if ( x >= mod_x_Size - 30)  {

                 x= mod_x_Size - 30 ;
                 moveWith_x =  -moveWith_x++;
            }


            if ( y >= mod_y_Size -30) {
                  y=mod_y_Size - 30 ;
                 moveWith_y= -moveWith_y++;
            }

            if ( x < 30) {

             x=30;
             moveWith_x= -moveWith_x++;
            }

            if ( y <30) {

                 y=50;
                 moveWith_y= -moveWith_x++; 
            }
    }

 Square::Square(void) {
        x=0;
        y=0;

        moveWith_x = 0;
        moveWith_y = 0; 
    }

    Square::~Square(void) {

    }

В моем main.cpp я устанавливаю таймер, создаю и рисую заданное количество квадратов (белой кистью).

#include <windows.h>
#include <windowsx.h>

#include "Square.h"

#define NUMARUL_DE_FIGURI  2


LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);
void moveObject(int,int);

    //Coordonatele in caz de redimensionare a ferestrei
    static int mod_x_Size, mod_y_Size;

    // Crearea ferestrei de lucru
HWND hwnd;

int WINAPI WinMain (HINSTANCE hInt, HINSTANCE,LPSTR,int) {

char atitle[] = "Drawing with GDI";
char className[] = "Main Window";

MSG msg;

// Crearea si initializarea ferestrei principale
WNDCLASS wnd;
ZeroMemory(&wnd,sizeof(wnd));

wnd.lpfnWndProc = WndProc;
wnd.hInstance = hInt;
wnd.hIcon = LoadIcon (NULL,IDI_APPLICATION);
wnd.hCursor = LoadCursor (NULL,IDC_ARROW);
wnd.hbrBackground = GetStockBrush (BLACK_BRUSH);
wnd.lpszClassName = className;

// Inregistrarea clasei in SO
RegisterClass (&wnd);


    // Crearea unui timer
 SetTimer (hwnd, 1, 40, NULL) ;

hwnd = CreateWindow (className,atitle,WS_OVERLAPPEDWINDOW,200,200,600,600,HWND_DESKTOP,NULL,hInt,NULL);

//Afisarea ferestrei in mod obisnuit
ShowWindow (hwnd,SW_SHOWNORMAL);

// Daca aplicatia primeste mesaj de la SO are loc transmiterea p-u prelucrare
while (GetMessage(&msg,NULL,0,0)) DispatchMessage(&msg);

     return 0;
}

// Prelucrarea mesajelor
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {

    // Structura ce detine informatii despre dispozitivul de desenare
    PAINTSTRUCT ps;

    // Descriptorul dispozitivului de desen
    HDC hdc;

    Square square[NUMARUL_DE_FIGURI];

    // Culoarea figurii
    HBRUSH shapeColor;

    switch (msg) {

// Prelucrarea mesajelor primite la modificarea dimensiunilor ferestrei
case WM_SIZE :      

        //La fiecare redimensionare a ferestrei se reinnoiesc coordonatele speciale 
        mod_x_Size = LOWORD (lparam) ;
        mod_y_Size = HIWORD (lparam) ;
        break ;

// Prelucrarea mesajelor primite la fiecare interval al timerului
case WM_TIMER:

    InvalidateRect (hwnd, NULL, TRUE) ;

for (int i=0;i<NUMARUL_DE_FIGURI;i++) {

    square[i].MoveSquare( mod_x_Size, mod_y_Size);

}



// Prelucrarea mesajului de desenare 
case WM_PAINT: 

    // Permite desenarea pe dispozitivul de desenare
    hdc = BeginPaint(hwnd, &ps);

    // Crearea patratelor
   for (int i=0;i<NUMARUL_DE_FIGURI;i++) {

        shapeColor = (HBRUSH)SelectObject(hdc, CreateSolidBrush(RGB(255,255,255)));

        square[i].DrawSquare(hdc,mod_x_Size-((i*200)+50),mod_y_Size-((i*200)+50),mod_x_Size-((i*20)+100),mod_y_Size-((i*20)+100)); 
    }

  // 
    //ReleaseDC(hwnd,hdc);

   // Finiseaza procesul de desenare pe dispozitiv
    EndPaint(hwnd, &ps);

    break;

// Distrugerea ferestrei aplicatiei
case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, msg, wparam, lparam);
    }

    return 0;
}

Где я ошибаюсь? простите меня за комментарии к коду (это мой язык), если вы хотите, чтобы я конкретизировал проблему, просто спросите.


person develoops    schedule 21.11.2011    source источник
comment
Что не работает, как ожидалось?   -  person pezcode    schedule 21.11.2011
comment
Я создаю в этом примере два квадрата. Когда я строю и запускаю, я вижу эти 2 квадрата, но они не двигаются.   -  person develoops    schedule 21.11.2011


Ответы (2)


// Crearea unui timer
SetTimer (hwnd, 1, 40, NULL) ;

hwnd = CreateWindow (className,atitle,WS_OVERLAPPEDWINDOW,200,200,600,600,HWND_DESKTOP,NULL,hInt,NULL);

Вы вызываете SetTimer перед назначением дескриптора окна hwnd, его следует вызывать после CreateWindow.

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

person pezcode    schedule 21.11.2011
comment
моя вина, но все равно не помогло - person develoops; 21.11.2011

// Prelucrarea mesajelor primite la fiecare interval al timerului
case WM_TIMER:
    InvalidateRect (hwnd, NULL, TRUE);
    for (int i=0;i<NUMARUL_DE_FIGURI;i++) {
        square[i].MoveSquare(mod_x_Size, mod_y_Size);
    }

Это кажется неправильным, это будет выполнять цикл for каждый раз, когда будет получено сообщение таймера, и результирующая позиция будет для i==NUMARUL_DE_FIGURI каждый раз.

Вам нужно сделать int i переменной состояния (член класса?), и просто

case WM_TIMER:
    if (i<0) i =0;
    if (i<NUMARUL_DE_FIGURI)
    {
        square[i].MoveSquare(mod_x_Size, mod_y_Size);
        InvalidateRect (hwnd, NULL, TRUE);        
    }
    i++;
person sehe    schedule 21.11.2011
comment
когда вы отлаживаете, можете ли вы увидеть, что таймер даже запущен, и значение i увеличивается? - person sehe; 21.11.2011