Search code examples
c++winapivisual-c++animationgdi

Animate Squares using GDI C++


I want to animate motion of a number of squares. In this example i create two squares. When i built and run , i can see those 2 squares ,but they are not moving .

I created a class which represent square

#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);
};

And implementation file (here i create squares using Rectangle function in DrawSquare) and try to animate a motion in 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) {

    }

In my main.cpp I set a timer , create and draw a given number od squares (with white brush)

#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;
}

Where i am wrong ? forgive me for code comments (it's my language) if you want from me to be more specific on problem just ask.


Solution

  • // Crearea unui timer
    SetTimer (hwnd, 1, 40, NULL) ;
    
    hwnd = CreateWindow (className,atitle,WS_OVERLAPPEDWINDOW,200,200,600,600,HWND_DESKTOP,NULL,hInt,NULL);
    

    You call SetTimer before assigning the window handle to hwnd, it should be called after CreateWindow.

    Also, your code resizes them to the client area whenever the main window is resized. Not sure if that's what you intend to do.