0

im trying to create an app with a rotating cube, and i created the window, then when i press 'p' my cube is create and every time the pc get the 'p' pressed the cube rotates. the issue is that the old cube remains, so i have infinite cubes on my screen

here the code

#include <Windows.h>
#include <iostream>
#include <string>   //i mean, useless, we use wide strings
#include <sstream>
#include <unordered_map>
#include <chrono>

using namespace std::this_thread; // sleep_for, sleep_until
using namespace std::chrono; // nanoseconds, system_clock, seconds

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}


void drawLine(float x1, float y1, float x2, float y2, HDC hdc, HWND hWnd, HBRUSH brush)
{

    RECT cuberect;
    FillRect(hdc, &cuberect, brush);
    DeleteObject(brush);
    ReleaseDC(hWnd, hdc);

    InvalidateRect(hWnd, NULL, TRUE);
    float x = x1;
    float y = y1;
    float dx = fabsf(x2 - x1);
    float dy = fabsf(y2 - y1);
    float s1 = sgn(x2 - x1);
    float s2 = sgn(y2 - y1);
    float t;
    float intercharge;
    if (dy > dx) t = dx, dx = dy, dy = t, intercharge = 1;
    else intercharge = 0;
    float e = 2 * dy - dx;
    float a = 2 * dy;
    float b = 2 * dy - 2 * dx;
    SetPixel(hdc ,x, y, RGB (0, 0, 0));
    for (int i = 1; i < dx; i++)
    {
        if (e < 0)
        {
            if (intercharge == 1) y = y + s2;
            else
            {
                x = x + s1;
                e = e + a;
            }
        }
        else
        {
            y = y + s2;
            x = x + s1;
            e = e + b;
        }
        SetPixel(hdc, x, y, RGB (0, 0, 0));
        std::cout << x << " - " << y << std::endl;
    }
}

void rotateC(float cTmp[4][3], float rmatrix[3][3])
{

    cTmp[2][0] = cTmp[0][0] * rmatrix[0][0] + cTmp[0][1] * rmatrix[0][1] + cTmp[0][2] * rmatrix[0][2];
    cTmp[2][1] = cTmp[0][0] * rmatrix[1][0] + cTmp[0][1] * rmatrix[1][1] + cTmp[0][2] * rmatrix[1][2];
    cTmp[2][2] = cTmp[0][0] * rmatrix[2][0] + cTmp[0][1] * rmatrix[2][1] + cTmp[0][2] * rmatrix[2][2];
    cTmp[3][0] = cTmp[1][0] * rmatrix[0][0] + cTmp[1][1] * rmatrix[0][1] + cTmp[1][2] * rmatrix[0][2];
    cTmp[3][1] = cTmp[1][0] * rmatrix[1][0] + cTmp[1][1] * rmatrix[1][1] + cTmp[1][2] * rmatrix[1][2];
    cTmp[3][2] = cTmp[1][0] * rmatrix[2][0] + cTmp[1][1] * rmatrix[2][1] + cTmp[1][2] * rmatrix[2][2];
    cTmp[0][0] = cTmp[2][0];
    cTmp[0][1] = cTmp[2][1];
    cTmp[0][2] = cTmp[2][2];
    cTmp[1][0] = cTmp[3][0];
    cTmp[1][1] = cTmp[3][1];
    cTmp[1][2] = cTmp[3][2];

};


//
//WndProc,    the procedure part:  (window -> messages -> machine -> render -> window)

// #define CONVERT(x) *((x) = "L"(x)) // maybe?

bool lbutton = false;
short x = 0, y = 0, px = 0, py = 0;
const int size = 10;
static int dotx = 50;
static int doty = 50;
int width = 1024;
int height = 512;
COLORREF white = RGB(255, 255, 255);
float angle = 0;
HBRUSH whitebrush = CreateSolidBrush(RGB(255, 255, 255));

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { //hWnd = handle to window, msg = message (like WM_SIZE or WM_QUIT). wparal and lparam contain additional data

    //
    //dot creation
    HDC device_context = GetDC(hWnd);
    static COLORREF color = RGB(255, 0, 0);
    int oldx = dotx;
    int oldy = doty;
    RECT pixelmovementrect = { oldx, oldy, oldx + size, oldy + size };
    HDC hdc = GetDC(hWnd);
    bool w = false, a = false, s = false, d = false; 

    switch (msg) {  // switch cases on changing msg value

    case WM_CREATE:

        SetTimer(hWnd, 1, 20, NULL); //the third arg is the n of milliseconds

        break;


    case WM_TIMER:

        oldx = dotx;
        oldy = doty;

        if (GetAsyncKeyState('W') & 0x8000) {

            doty--;

            FillRect(hdc, &pixelmovementrect, whitebrush);
            DeleteObject(whitebrush);
            ReleaseDC(hWnd, hdc);

            InvalidateRect(hWnd, NULL, TRUE);
        }
        if (GetAsyncKeyState('A') & 0x8000) {

            dotx--;

            FillRect(hdc, &pixelmovementrect, whitebrush);
            DeleteObject(whitebrush);
            ReleaseDC(hWnd, hdc);

            InvalidateRect(hWnd, NULL, TRUE);
        }
        if (GetAsyncKeyState('S') & 0x8000) {

            doty++;

            FillRect(hdc, &pixelmovementrect, whitebrush);
            DeleteObject(whitebrush);
            ReleaseDC(hWnd, hdc);

            InvalidateRect(hWnd, NULL, TRUE);
        }
        if (GetAsyncKeyState('D') & 0x8000) {
            
            if (dotx < (300 - size)) {

                dotx++;

            }

            FillRect(hdc, &pixelmovementrect, whitebrush);
            DeleteObject(whitebrush);
            ReleaseDC(hWnd, hdc);

            InvalidateRect(hWnd, NULL, TRUE);
        }
        if (GetAsyncKeyState('P') & 0x8000) {

            int cubewidth = 1024; // window width
            int cubeheight = 512; // window height

            int matrix[8][3]{ //vertici

                    {63,63,63},
                    {63,-63,63},
                    {-63,-63,63},
                    {-63,63,63},
                    {63,63,-63}, //
                    {63,-63,-63}, //
                    {-63,-63,-63},
                    {-63,63, -63}

            };

            int vector[12][2]{

                    {0,1}, //linea da vertice 0 a vertice 1
                    {1,2},
                    {2,3},
                    {3,0},
                    {4,5},
                    {5,6},
                    {6,7},
                    {7,4},
                    {0,4},
                    {1,5},
                    {2,6},
                    {3,7}

            };

            float xt1, yt1, xt2, yt2, zt1, zt2, flenght = 500, rotspeed = -0.015, dime = 1, osX = 0, osY = 0;
            bool exit = true;

            float rmatrix1[3][3]{ {1,      0,     0},
                      {0, cos(angle),sin(angle)},
                      {0,-sin(angle),cos(angle)} };

            float rmatrix2[3][3]{ { cos(angle),0,sin(angle)},
                                  {      0,1,0     },
                                  {-sin(angle),0,cos(angle)} };

            float rmatrix3[3][3]{ { cos(angle),sin(angle),0},
                                  {-sin(angle),cos(angle),0},
                                  {0,      0,     1} };

            float cTmp[4][3];

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

                // MoveToEx(dev_con_cube, int(cTmp[0][0] * dime + (cubewidth / 2) + osX), int(cTmp[0][1] * dime + (cubeheight / 2) + osY), nullptr);
                // LineTo(dev_con_cube, int(cTmp[1][0] * dime + (cubewidth / 2) + osX), int(cTmp[1][1] * dime + (cubeheight / 2) + osY));
                // EndPaint(hWnd, &paints);

                cTmp[0][0] = matrix[vector[i][0]][0],
                    cTmp[0][1] = matrix[vector[i][0]][1],
                    cTmp[0][2] = matrix[vector[i][0]][2],
                    cTmp[1][0] = matrix[vector[i][1]][0],
                    cTmp[1][1] = matrix[vector[i][1]][1],
                    cTmp[1][2] = matrix[vector[i][1]][2];

                //rotateC(cTmp, rmatrix1);
                rotateC(cTmp, rmatrix2);
                rotateC(cTmp, rmatrix3);

                cTmp[0][0] = (cTmp[0][0] * flenght) / (cTmp[0][2] + flenght);
                cTmp[1][0] = (cTmp[1][0] * flenght) / (cTmp[1][2] + flenght);
                cTmp[0][1] = (cTmp[0][1] * flenght) / (cTmp[0][2] + flenght);
                cTmp[1][1] = (cTmp[1][1] * flenght) / (cTmp[1][2] + flenght);

                //
                // MoveToEx(dev_con_cube, int(cTmp[0][0] * dime + (cubewidth / 2) + osX), int(cTmp[0][1] * dime + (cubeheight / 2) + osY), nullptr);
                // LineTo(dev_con_cube, int(cTmp[1][0] * dime + (cubewidth / 2) + osX), int(cTmp[1][1] * dime + (cubeheight / 2) + osY));
                // EndPaint(hWnd, &paints);
                drawLine(int(cTmp[0][0] * dime + (cubewidth / 2) + osX), int(cTmp[0][1] * dime + (cubeheight / 2) + osY), int(cTmp[1][0] * dime + (cubewidth / 2) + osX), int(cTmp[1][1] * dime + (cubeheight / 2) + osY), hdc, hWnd, whitebrush);


                // sleep_for(nanoseconds(1000000000));
                // sleep_until(system_clock::now() /* + seconds(1) */ );

                //drawLine(cTmp[0][0] * d + (width / 2) + osX, cTmp[0][1] * d + (height / 2)  + osY, """" cTmp[1][0] * d + (width / 2) + osX, cTmp[1][1] * d + (height / 2) + osY, renderer);
                std::cout << "--|" << (int)cTmp[0][0] << " | " << (int)cTmp[0][1] << " | " << (int)cTmp[1][0] << " | " << (int)cTmp[1][1] << "|--" << std::endl;
            }

            angle += rotspeed;
            rotspeed -= 0.5;

        }

        break;

    /*
    case WM_SIZE: //should make it paint only pixels were not existent
    {
        HDC reshdc = GetDC(hWnd);
        RECT rect;
        HBRUSH brush = CreateSolidBrush(RGB(255, 255, 255));
        GetClientRect(hWnd, &rect);
        FillRect(reshdc, &rect, brush);
        DeleteObject(brush);
        
    }

    break;

    */

    case WM_LBUTTONDOWN:
    {
        std::cout << "fnc called" << std::endl;

        HDC device_context = GetDC(hWnd);
        x = LOWORD(lParam);
        y = HIWORD(lParam);

        if (!lbutton) {

            px = LOWORD(lParam);
            py = HIWORD(lParam);
            std::cout << px << "|" << py << "|" << x << "|" << y << "|" << lbutton << std::endl; //yes
            lbutton = true;
            std::cout << px << "|" << py << "|" << x << "|" << y << "|" << lbutton << std::endl; //yes

        }
        else {

            HPEN penna = CreatePen(PS_SOLID, 5, RGB(0, 0, 150));
            SelectObject(device_context, penna);
            MoveToEx(device_context, px, py, nullptr);
            LineTo(device_context, x, y);
            ReleaseDC(hWnd, device_context);
            std::cout << px << "|" << py << "|" << x << "|" << y << "|" << lbutton << std::endl; //yes
            lbutton = false;
            std::cout << px << "|" << py << "|" << x << "|" << y << "|" << lbutton << std::endl; //yes

        }
        std::cout << px << "|" << py << "|" << x << "|" << y << "|" << lbutton << std::endl; //yes

        SetWindowText(hWnd, L"second title");    //pass handle to window

        std::wstring titolo = L" X: " + std::to_wstring(x) + L" Y: " + std::to_wstring(y);
        SetWindowText(hWnd, titolo.c_str());

    }
    break;


    case WM_LBUTTONUP:
    {
        SetWindowText(hWnd, L"uwu");
    }

    break;

    /* case WM_MOUSEMOVE: //godo worka
    {
        unsigned short xPos = LOWORD(lParam);
        unsigned short yPos = HIWORD(lParam);

        std::wstring titolo = L" X: " + std::to_wstring(xPos) + L" Y: " + std::to_wstring(yPos);
        SetWindowText(hWnd, titolo.c_str());

    }

    */

    case WM_CLOSE:  //case window get closed
    {
        PostQuitMessage(69); //  "the task ended with code 0"
    }

    break;

    case WM_PAINT:
    {

        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                SetPixel(hdc, dotx + i, doty + j, color);
            }
        }

        MoveToEx(hdc, 300, 0, nullptr);
        LineTo(hdc, 300, 300);
        
        EndPaint(hWnd, &ps);

    }
    
    case WM_KEYUP:
    {

        if (wParam == 'F') {

            SetWindowText(hWnd, L"third title");
            MessageBox(hWnd, L"jgjfgdfg", L"uuuvloa", MB_OK);

        }

    }

    break;

    case WM_CHAR:
    {
        if (wParam != 'w') {

            std::wstring title = L"aaaaa";    //strings are 8 bit (like abcdef), LPCWSTR is wchar_t* so 16bit so chinese things, wstring is wide string so it is wchar* array and not char* array
            title.push_back((wchar_t)wParam);
            SetWindowTextW(hWnd, title.c_str());    // https://stackoverflow.com/questions/22990044/lpcwstr-error-is-there-a-better-solution

        }

    }

    break;


    }

    return DefWindowProc(hWnd, msg, wParam, lParam);

}

#pragma comment (linker, "/entry:WinMainCRTStartup /subsystem:console")  //show console

//
//entry point

int WINAPI WinMain(
    _In_ HINSTANCE hInstance,   //hinstance is a pointer (class HINSTANCE) to an object holding infos (like an handle)
    _In_opt_ HINSTANCE hPrevInstance,   //always null
    _In_ LPSTR lpCmdLine,   //pass params with cmd (string args but in a single string)
    _In_ int nCmdShow   //changing this value the app will be showed or not, or displayed in different ways
) {

    std::cout << "aaaa" << std::endl;

    const auto pClassName = L"title";

    //
    //register window class
    WNDCLASSEX wc = { 0 }; //created window object ("wc" is the object name)
    wc.cbSize = sizeof(wc); // type UINT, size of the structure (the window)
    wc.style = CS_OWNDC;    // type UINT, style of the window (point 2 of header comment -> msdn docs) owndc = allocates a unique device context for each window in the class (0x0020) basic windows gdi
    wc.lpfnWndProc = WndProc;    //type WNDPROC, pointer to window procedure, must use "callwindowproc", watch the video #2 of the playlist for more info, DEFaultWINDOWPROCedure
    wc.cbClsExtra = 0;  // type int, number of bites to allocate following window-class structure, the os initialise them to zero
    wc.cbWndExtra = 0;  // type int, number of extra bytes to allocate following the window instance, bytes initialised to zero (by os). if an app uses WNDCLASSEX to register a dialog box created by using the class directive in the resource file, it musrt set this member to DLGWINDOWEXTRA
    wc.hInstance = hInstance;   // type HINSTANCE, handle to the instance
    wc.hIcon = nullptr;   // type HICON, handle to class icon, it must be handle to an icon resource, if it's NULL the system provides a default icon
    wc.hCursor = nullptr;   // type HCURSOR, handle to the class cursor, must be handle to cursor resource, if this member is NULL an app must explicitly set the cursor shape whenever the mouse moves into the app window
    wc.hbrBackground = nullptr;    // type HBRUSH, handle to class background brush, this member can be a handle to the brush to be used for painting the background, or it can be a color value. A color value must be one of the following standard system colors (the value 1 must be added to the chosen color). If a color value is given, you must convert it to one of the HBRUSH types you can find on link 2 of point 2 of header comment
    wc.lpszMenuName = nullptr;    // type LPCTSTR, specify the resource name of the class menu, if it's null the app will have no default menu
    wc.lpszClassName = pClassName;    // type LPCTSTR, changes the behavior depending on use, more info on the link 2 of point 2 of header comment
    wc.hIconSm = nullptr;   // a handle to a small icon associated with window class, if NULL the system searches the icon resource speciied by hIcon

    RegisterClassEx(&wc); //register class extended (extended version)

    //
    //create window instance

    HWND hWnd = CreateWindowEx( //pass there parameters requested, some are from default window and not extended, like style. hWnd is an handle

        0, pClassName, // dwExStyle, class name (DWORD, LPCWSTR)
        L"window name", // window name (LPCWSTR)
        WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_THICKFRAME, // dw style (DWORD)
        100, 100, width, height,  // position x, position y, width, height (int)
        nullptr, nullptr, hInstance, nullptr // hWndParent, hMenu, hInstance, lpParam ( HWND, HMENU, HINSTANCE, LPVOID ) 


    );

    //
    //show window
    ShowWindow(hWnd, 5);  // 2 instead of 5 does not create background; 5 = SW_SHOW

    //
    //message pump, making the window responsable via input (messages), video #3
    MSG msg; //struct MSG (message),    the behavior is default because we used defaultwindowsprocedure (DefWindowProc) when we registered window class, that includes functs like WindowsMessageClose, but it doesn't work without msg because maybe u have 2 windows, you click to close one and both closes
    BOOL gResult;

    while ((gResult = GetMessage(&msg, nullptr, 0, 0)) > 0) { //passing params: [out] LPMSG lpmsg, [in, optional] HWND hwnd, [in] UINT wmsgfiltermin, [in] UINT wmsgfiltermax

        // 3rd point of docs header comment
        TranslateMessage(&msg);  // [in] const MSG *lpMsg,    pointer to msg structure that contains message information retrieved from calling threads message queu using getmessage or peekmessage
        DispatchMessage(&msg);  // same args as TranslateMessage, it dispatches a message retrieved with GetMessage

    }

    if (gResult == -1) {

        return -1;

    }
    else {

        return msg.wParam;  // WM_QUIT: https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-quit

    }

    return 0;

}

i except to have a cube, a red cube, with a white background. everytime i click 'p' it should "rotate" (a new cube is created but with a different angle) what happens: the new cube is created, the old one still remain

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • It looks like that WndProc always runs GetDC twice regardless of msg, and these DCs don't be released. This will cause many DC leaks. – fana Jul 31 '23 at 01:29
  • 1
    Consider to move all drawing code into WM_PAINT case, and post redraw request from other message cases. – fana Jul 31 '23 at 01:36
  • Another tip, draw the new cube to a bitmap (DC) first then copy this bitmap to the window in the onpaint. – Pepijn Kramer Jul 31 '23 at 04:01

0 Answers0