alien_fx_fiend

Infinite Canvas (KeysFix+TitleButtons) Tweaks V2

Nov 5th, 2024 (edited)
14
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 30.47 KB | Source Code | 0 0
  1. ==++ Here's the full source code for (file 1/1) of "main.cpp"::++==
  2. #define NOMINMAX
  3. #include <windows.h>
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <vector>
  7. #include <commctrl.h>
  8. //#include <windows.h>
  9. #include <stdio.h>
  10. #include <iostream>
  11. #include "resource.h"  // Add this with your other includes
  12.  
  13. #pragma comment(lib, "comctl32.lib")
  14. using namespace std;
  15. // Forward Declarations
  16. //struct Brushstroke;
  17. //struct Eraserstroke;
  18.  
  19. void DrawBrush(HDC hdc, int x, int y, bool isEraser = false);
  20. //void DebugDraw(HDC hdc);
  21. void Erase(HDC hdc, int x, int y);
  22. void ClearDrawing(HWND hwnd);
  23. void UpdateStatus(HWND hwnd);
  24. //void ClearDrawing(HDC hdc, int width, int height);
  25. //void DrawSmoothBrush(HDC hdc, int x, int y, bool isScreenDC);
  26. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  27.  
  28.  
  29. // Add these global variables at the top
  30. int virtualWidth = 8192;
  31. int virtualHeight = 8192;
  32. int scrollX = 0;  // Will be initialized properly in InitializeMemoryBitmap
  33. int scrollY = 0;  // Will be initialized properly in InitializeMemoryBitmap
  34. int canvasWidth = 8192;
  35. int canvasHeight = 8192;
  36. bool isSpacePressed = false;
  37. bool isPanning = false;  // Add this new variable
  38. POINT lastMousePos = { 0, 0 };
  39. POINT dragStart = { 0, 0 };
  40. // Add these global variables if not already present
  41. //std::vector<Brushstroke> storedBrushstrokes;
  42. //std::vector<Eraserstroke> storedEraserstrokes;
  43. HDC hMemoryDC = NULL;
  44. HBITMAP hMemoryBitmap = NULL;
  45. HBITMAP hOldBitmap = NULL;  // Add this to store the old bitmap
  46. HINSTANCE hInst;
  47. //bool isPaintbrushSelected = true;  // Add a global variable to track the selected tool
  48. // Define a vector to store the doodle points for the Paintbrush tool
  49. //std::vector<POINT> paintbrushDoodlePoints;
  50. //new mod code
  51. POINT previousPoint;  // Add a new global variable to track the previous point
  52. // Declare hdc as a global variable
  53. HDC hdc;
  54. HWND hWnd;  // Declare the window handle variable globally or within the appropriate scope
  55. //bool needsRedraw = true;  // Add this line at the top of your file
  56.            // Declare a global variable to specify the grid spacing
  57. //int gridSpacing = 20;
  58. bool isInitialized = false;
  59. bool isPaintbrushSelected = true;;
  60. bool isDrawing = false;
  61. bool isErasing = false;
  62. bool isClearing = false;
  63. bool isEraserMode = false;
  64. bool isEraserSelected = false;
  65. int minBrushSize = 5;
  66. int maxBrushSize = 50;
  67. int brushSize = 10;
  68. //POINT previousPoint;
  69.  
  70.  
  71. // Define a struct to store brushstroke information
  72. /*struct Brushstroke {
  73.    int x;
  74.    int y;
  75.    int size;
  76.    COLORREF color;
  77.    // Add any other necessary properties for the brushstroke
  78. };*/
  79.  
  80. // Define a struct to store eraserstroke information
  81. /*struct Eraserstroke {
  82.    int x;
  83.    int y;
  84.    int size;
  85.    COLORREF color;
  86.    // Add any other necessary properties for the eraserstroke
  87. };*/
  88.  
  89. // Declare a vector to store the brushstrokes
  90. //std::vector<Brushstroke> storedBrushstrokes;
  91. //std::vector<Eraserstroke> storedEraserstrokes;
  92. // Global variables to store the minimized brushstrokes
  93. //std::vector<Brushstroke> minimizedDrawnBrushstrokes;
  94. //std::vector<Eraserstroke> minimizedErasedBrushstrokes;
  95.  
  96. // Function declaration for DrawGrid
  97. //void DrawGrid(HDC hdc, int spacing, COLORREF color); //drawgrid disableddefault
  98.  
  99. // Optimized DrawGrid function to efficiently draw both vertical and horizontal lines
  100.  
  101. // Add this function
  102. /*void CleanupOldStrokes() {
  103.    const size_t MAX_STROKES = 100000;
  104.    if (storedBrushstrokes.size() > MAX_STROKES) {
  105.        storedBrushstrokes.erase(storedBrushstrokes.begin(),
  106.            storedBrushstrokes.begin() + (storedBrushstrokes.size() - MAX_STROKES));
  107.    }
  108.    if (storedEraserstrokes.size() > MAX_STROKES) {
  109.        storedEraserstrokes.erase(storedEraserstrokes.begin(),
  110.            storedEraserstrokes.begin() + (storedEraserstrokes.size() - MAX_STROKES));
  111.    }
  112. }*/
  113.  
  114. //new gpt broken?
  115. /*void DrawBrush(HDC hdc, int x, int y) {
  116.    // Debug output
  117.    char debug[256];
  118.    sprintf_s(debug, "DrawBrush called at: x=%d, y=%d\n", x, y);
  119.    OutputDebugStringA(debug);
  120.  
  121.    HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
  122.    HPEN redPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
  123.  
  124.    if (!redBrush || !redPen) {
  125.        OutputDebugStringA("Failed to create brush or pen\n");
  126.        return;
  127.    }
  128.  
  129.    HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, redBrush);
  130.    HPEN oldPen = (HPEN)SelectObject(hdc, redPen);
  131.  
  132.    if (!oldBrush || !oldPen) {
  133.        OutputDebugStringA("Failed to select brush or pen\n");
  134.        DeleteObject(redBrush);
  135.        DeleteObject(redPen);
  136.        return;
  137.    }
  138.  
  139.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  140.  
  141.    SelectObject(hdc, oldBrush);
  142.    SelectObject(hdc, oldPen);
  143.    DeleteObject(redBrush);
  144.    DeleteObject(redPen);
  145. }*/
  146.  
  147.  
  148. // Add this function to initialize the memory bitmap
  149. // Add this function
  150. // Modify InitializeMemoryBitmap:
  151. void InitializeMemoryBitmap(HWND hwnd) {
  152.    HDC hdc = GetDC(hwnd);
  153.    if (!hdc) {
  154.        return;
  155.    }
  156.  
  157.    hMemoryDC = CreateCompatibleDC(hdc);
  158.    if (!hMemoryDC) {
  159.        ReleaseDC(hwnd, hdc);
  160.        return;
  161.    }
  162.  
  163.    hMemoryBitmap = CreateCompatibleBitmap(hdc, virtualWidth, virtualHeight);
  164.    if (!hMemoryBitmap) {
  165.        DeleteDC(hMemoryDC);
  166.        ReleaseDC(hwnd, hdc);
  167.        return;
  168.    }
  169.  
  170.    hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hMemoryBitmap);
  171.  
  172.    // Fill with white background
  173.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  174.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  175.    FillRect(hMemoryDC, &rect, whiteBrush);
  176.    DeleteObject(whiteBrush);
  177.  
  178.    ReleaseDC(hwnd, hdc);
  179.    isInitialized = true;
  180.  
  181.    // Draw coordinate guides
  182.    HPEN guidePen = CreatePen(PS_SOLID, 1, RGB(200, 200, 200));
  183.    SelectObject(hMemoryDC, guidePen);
  184.  
  185.    // Draw center lines
  186.    MoveToEx(hMemoryDC, virtualWidth / 2, 0, NULL);
  187.    LineTo(hMemoryDC, virtualWidth / 2, virtualHeight);
  188.    MoveToEx(hMemoryDC, 0, virtualHeight / 2, NULL);
  189.    LineTo(hMemoryDC, virtualWidth, virtualHeight / 2);
  190.  
  191.    // Draw border
  192.    HPEN edgePen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
  193.    SelectObject(hMemoryDC, edgePen);
  194.    Rectangle(hMemoryDC, 0, 0, virtualWidth - 1, virtualHeight - 1);
  195.  
  196.    DeleteObject(guidePen);
  197.    DeleteObject(edgePen);
  198.  
  199.    // Initialize scroll position to center the canvas
  200.    RECT clientRect;
  201.    GetClientRect(hwnd, &clientRect);
  202.    scrollX = (virtualWidth - clientRect.right) / 2;
  203.    scrollY = (virtualHeight - clientRect.bottom) / 2;
  204. }
  205.  
  206.    // Initialize scroll position to center the canvas
  207.    //RECT clientRect;
  208.    //GetClientRect(hwnd, &clientRect);
  209.    //scrollX = -virtualWidth / 2 + (clientRect.right / 2);
  210.    //scrollY = -virtualHeight / 2 + (clientRect.bottom / 2);
  211. //}
  212.  
  213. // Replace your DrawBrush function with this simpler version:
  214. void DrawBrush(HDC hdc, int x, int y, bool isEraser) {
  215.    COLORREF color = isEraser ? RGB(255, 255, 255) : RGB(255, 0, 0);
  216.    HBRUSH brush = CreateSolidBrush(color);
  217.    HPEN pen = CreatePen(PS_SOLID, 1, color);
  218.  
  219.    HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, brush);
  220.    HPEN oldPen = (HPEN)SelectObject(hdc, pen);
  221.  
  222.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  223.  
  224.    SelectObject(hdc, oldBrush);
  225.    SelectObject(hdc, oldPen);
  226.    DeleteObject(brush);
  227.    DeleteObject(pen);
  228. }
  229.  
  230. //old pre-gpt
  231. /*void DrawBrush(HDC hdc, int x, int y) {
  232.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0));  // Set the brush color to fully red
  233.    SelectObject(hdc, GetStockObject(NULL_PEN));  // Set the pen to null to remove the border
  234.    SelectObject(hdc, hBrush);
  235.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  236.    DeleteObject(hBrush);
  237. }*/
  238.  
  239.  
  240.  
  241. // Add this debug function
  242. /*void DebugDraw(HDC hdc) {
  243.    HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
  244.    RECT testRect = { 100, 100, 200, 200 };
  245.    FillRect(hdc, &testRect, redBrush);
  246.    DeleteObject(redBrush);
  247. }*/
  248. /*void DrawBrush(HDC hdc, int x, int y) {
  249.    HRGN hRgn = CreateEllipticRgn(x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  250.    FillRgn(hdc, hRgn, CreateSolidBrush(RGB(255, 0, 0)));
  251.    DeleteObject(hRgn);
  252. }*/
  253.  
  254. //broken old
  255. void Erase(HDC hdc, int x, int y) {
  256.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  257.    SelectObject(hdc, GetStockObject(NULL_PEN));
  258.    SelectObject(hdc, hBrush);
  259.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  260.    DeleteObject(hBrush);
  261. }
  262. /*void Erase(HDC hdc, int x, int y) {
  263.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the brush color to white
  264.    HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);
  265.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  266.    SelectObject(hdc, hOldBrush);
  267.    DeleteObject(hBrush);
  268. }*/
  269.  
  270. //start test of new eraser
  271. /*void Erase(HDC hdc, int x, int y) {
  272.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  273.    SelectObject(hdc, GetStockObject(NULL_PEN));
  274.    SelectObject(hdc, hBrush);
  275.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  276.    DeleteObject(hBrush);
  277. }*/
  278. //end test of new eraser
  279.  
  280. //start commented out testing new gpt function eraser
  281. /*void Erase(HDC hdc, int x, int y) {
  282.    // HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the brush color to white
  283.    // HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));  // Set the brush color to black
  284.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the brush color to white
  285.    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));  // Set the pen color to white
  286.    HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);
  287.    HGDIOBJ hOldPen = SelectObject(hdc, hPen);
  288.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  289.    SelectObject(hdc, hOldBrush);
  290.    SelectObject(hdc, hOldPen);
  291.    DeleteObject(hBrush);
  292.    DeleteObject(hPen);
  293. }*/
  294. //end commented out testing new gpt function eraser
  295. void ClearCanvas(HWND hwnd) {
  296.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  297.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  298.    FillRect(hMemoryDC, &rect, whiteBrush);
  299.    DeleteObject(whiteBrush);
  300.    InvalidateRect(hwnd, NULL, FALSE);
  301. }
  302. void ClearDrawing(HWND hwnd) {
  303.    // Clear the canvas
  304.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  305.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  306.    FillRect(hMemoryDC, &rect, whiteBrush);
  307.    DeleteObject(whiteBrush);
  308.  
  309.    // Reset scroll position to center
  310.    RECT clientRect;
  311.    GetClientRect(hwnd, &clientRect);
  312.    scrollX = (virtualWidth - clientRect.right) / 2;
  313.    scrollY = (virtualHeight - clientRect.bottom) / 2;
  314.  
  315.    // Redraw coordinate guides and border
  316.    // Draw coordinate guides
  317.    HPEN guidePen = CreatePen(PS_SOLID, 1, RGB(200, 200, 200));
  318.    SelectObject(hMemoryDC, guidePen);
  319.  
  320.    // Draw center lines
  321.    MoveToEx(hMemoryDC, virtualWidth / 2, 0, NULL);
  322.    LineTo(hMemoryDC, virtualWidth / 2, virtualHeight);
  323.    MoveToEx(hMemoryDC, 0, virtualHeight / 2, NULL);
  324.    LineTo(hMemoryDC, virtualWidth, virtualHeight / 2);
  325.  
  326.    // Draw border
  327.    HPEN edgePen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
  328.    SelectObject(hMemoryDC, edgePen);
  329.    Rectangle(hMemoryDC, 0, 0, virtualWidth - 1, virtualHeight - 1);
  330.  
  331.    DeleteObject(guidePen);
  332.    DeleteObject(edgePen);
  333.  
  334.    // Force redraw
  335.    InvalidateRect(hwnd, NULL, FALSE);
  336. }
  337. //newgptdelete
  338. /*void ClearDrawing(HWND hwnd) {
  339.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  340.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  341.    FillRect(hMemoryDC, &rect, whiteBrush);
  342.    DeleteObject(whiteBrush);
  343.    scrollX = -virtualWidth / 2;  // Reset to center
  344.    scrollY = -virtualHeight / 2; // Reset to center
  345.    InvalidateRect(hwnd, NULL, FALSE);
  346. }*/
  347. /*void ClearDrawing(HDC hdc, int width, int height) {
  348.    RECT rect = { 0, 0, width, height };
  349.    // HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the color to white
  350.    // HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));  // Set the color to black
  351.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the color to white
  352.    FillRect(hdc, &rect, hBrush);
  353.    DeleteObject(hBrush);
  354. }*/
  355.  
  356. //removing drawgrid
  357. /*void DrawGrid(HDC hdc, int spacing, COLORREF color) {
  358.    RECT rect;
  359.    GetClientRect(hWnd, &rect);
  360.  
  361.    HPEN hPen = CreatePen(PS_SOLID, 1, color);
  362.    HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
  363.  
  364.    // Draw vertical lines
  365.    for (int x = 0; x <= rect.right; x += spacing) {
  366.        MoveToEx(hdc, x, 0, NULL);
  367.        LineTo(hdc, x, rect.bottom);
  368.    }
  369.  
  370.    // Draw horizontal lines
  371.    for (int y = 0; y <= rect.bottom; y += spacing) {
  372.        MoveToEx(hdc, 0, y, NULL);
  373.        LineTo(hdc, rect.right, y);
  374.    }
  375.  
  376.    SelectObject(hdc, hOldPen);
  377.    DeleteObject(hPen);
  378. }*/
  379.  
  380. //gpts old drawgrid
  381. /*void DrawGrid(HDC hdc, int spacing, COLORREF color) {
  382.    RECT rect;
  383.    GetClientRect(hWnd, &rect);
  384.  
  385.    HPEN hPen = CreatePen(PS_SOLID, 1, color);
  386.    HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
  387.  
  388.    // Draw vertical lines
  389.    for (int x = 0; x < rect.right; x += spacing) {
  390.        MoveToEx(hdc, x, 0, NULL);
  391.        LineTo(hdc, x, rect.bottom);
  392.    }
  393.  
  394.    // Draw horizontal lines
  395.    for (int y = 0; y < rect.bottom; y += spacing) {
  396.        MoveToEx(hdc, 0, y, NULL);
  397.        LineTo(hdc, rect.right, y);
  398.    }
  399.  
  400.    SelectObject(hdc, hOldPen);
  401.    DeleteObject(hPen);
  402. }*/
  403.  
  404. //chatgpt disabled
  405. /*void DrawGrid(HDC hdc, int spacing, COLORREF color) {
  406.    RECT rect;
  407.    GetClientRect(hWnd, &rect);
  408.  
  409.    HPEN hPen = CreatePen(PS_SOLID, 1, color);
  410.    HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
  411.  
  412.    // Draw vertical lines
  413.    for (int x = 0; x < rect.right; x += spacing) {
  414.        MoveToEx(hdc, x, 0, NULL);
  415.        LineTo(hdc, x, rect.bottom);
  416.    }
  417.  
  418.    // Draw horizontal lines
  419.    for (int y = 0; y < rect.bottom; y += spacing) {
  420.        MoveToEx(hdc, 0, y, NULL);
  421.        LineTo(hdc, rect.right, y);
  422.    }
  423.  
  424.    SelectObject(hdc, hOldPen);
  425.    DeleteObject(hPen);
  426. }*/
  427.  
  428. //temp disabled for relocated code
  429. /*int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
  430.    const wchar_t CLASS_NAME[] = L"DoodleAppClass";
  431.  
  432.    WNDCLASS wc = { };
  433.  
  434.    wc.lpfnWndProc = WindowProc;
  435.    wc.hInstance = hInstance;
  436.    wc.lpszClassName = CLASS_NAME;
  437.  
  438.    RegisterClass(&wc);
  439.  
  440.    hInst = hInstance;
  441.  
  442.    HWND hwnd = CreateWindowEx(
  443.        0,
  444.        CLASS_NAME,
  445.        L"Doodle App",
  446.        WS_OVERLAPPEDWINDOW | WS_MAXIMIZE, //& ~WS_MINIMIZEBOX,  Add WS_MAXIMIZE style
  447.        // Disable the Minimize button
  448.  
  449.        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  450.  
  451.        NULL,
  452.        NULL,
  453.        hInstance,
  454.        NULL
  455.    );
  456.  
  457.    //hdc = GetDC(hWnd); //gptadded
  458.    if (hwnd == NULL) {
  459.        return 0;
  460.    }
  461.  
  462.    ShowWindow(hwnd, SW_SHOWMAXIMIZED);  // Show the window maximized
  463.  
  464.    //old code
  465.    //ShowWindow(hwnd, nCmdShow);
  466.  
  467.    MSG msg = { };
  468.    while (GetMessage(&msg, NULL, 0, 0)) {
  469.        TranslateMessage(&msg);
  470.        DispatchMessage(&msg);
  471.    }
  472.  
  473.    return 0;
  474. }*/
  475.  
  476. //new code
  477. /*void DrawSmoothBrush(HDC hdc, int x, int y) {
  478.    if (!isDrawing) return;
  479.  
  480.    int currentX = x + scrollX;
  481.    int currentY = y + scrollY;
  482.    int prevX = previousPoint.x + scrollX;
  483.    int prevY = previousPoint.y + scrollY;
  484.  
  485.    // Draw line between points for smoothness
  486.    int numPoints = 10;
  487.    for (int i = 0; i <= numPoints; i++) {
  488.        float t = (float)i / numPoints;
  489.        int drawX = prevX + (int)(t * (currentX - prevX));
  490.        int drawY = prevY + (int)(t * (currentY - prevY));
  491.  
  492.        if (isPaintbrushSelected) {
  493.            DrawBrush(hdc, drawX, drawY);
  494.        }
  495.        else if (isEraserSelected) {
  496.            Erase(hdc, drawX, drawY);
  497.        }
  498.    }
  499.  
  500.    previousPoint.x = x;
  501.    previousPoint.y = y;
  502. }*/
  503.  
  504. // Update status text when tool changes:
  505. void UpdateStatus(HWND hwnd) {
  506.    HWND hStatus = GetDlgItem(hwnd, 0);
  507.    if (hStatus) {
  508.        wchar_t status[256];
  509.        swprintf_s(status, L"Mode: %s | Brush Size: %d",
  510.            isEraserMode ? L"Eraser" : L"Draw", brushSize);
  511.        SetWindowText(hStatus, status);
  512.    }
  513. }
  514.  
  515. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  516.    switch (uMsg) {
  517.    case WM_CREATE:
  518.    {
  519.        InitializeMemoryBitmap(hwnd);
  520.        if (hMemoryDC) {
  521.            HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
  522.            RECT testRect = { 100, 100, 200, 200 };
  523.            FillRect(hMemoryDC, &testRect, redBrush);
  524.            DeleteObject(redBrush);
  525.            InvalidateRect(hwnd, NULL, FALSE);
  526.        }
  527.        else {
  528.            MessageBox(hwnd, L"Memory DC failed to initialize", L"Error", MB_OK);
  529.        }
  530.        UpdateStatus(hwnd);  // Initial status update
  531.        return 0;
  532.    }
  533.  
  534.    case WM_KEYDOWN:
  535.    {
  536.        if (wParam == VK_SPACE && !isSpacePressed) {
  537.            isSpacePressed = true;
  538.            GetCursorPos(&lastMousePos);
  539.            ScreenToClient(hwnd, &lastMousePos);
  540.            SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  541.            SetCapture(hwnd);  // Capture mouse when space is pressed
  542.            return 0;
  543.        }
  544.        else if (wParam == 0x50) {  // 'P' key
  545.            isPaintbrushSelected = true;
  546.            isEraserMode = false;
  547.            UpdateStatus(hwnd);
  548.        }
  549.        else if (wParam == 0x45) {  // 'E' key
  550.            isPaintbrushSelected = false;
  551.            isEraserMode = true;
  552.            UpdateStatus(hwnd);
  553.        }
  554.        else if (wParam == VK_ADD || wParam == VK_OEM_PLUS) {
  555.            brushSize = std::min(50, brushSize + 5);
  556.            UpdateStatus(hwnd);
  557.        }
  558.        else if (wParam == VK_SUBTRACT || wParam == VK_OEM_MINUS) {
  559.            brushSize = std::max(5, brushSize - 5);
  560.            UpdateStatus(hwnd);
  561.        }
  562.        else if (wParam == 0x43) {  // 'C' key
  563.            if (!(GetKeyState(VK_CONTROL) & 0x8000)) {
  564.                ClearDrawing(hwnd);
  565.            }
  566.        }
  567.        else if (wParam == VK_ESCAPE) {
  568.            if (hMemoryDC) {
  569.                if (hOldBitmap) {
  570.                    SelectObject(hMemoryDC, hOldBitmap);
  571.                }
  572.                DeleteDC(hMemoryDC);
  573.            }
  574.            if (hMemoryBitmap) {
  575.                DeleteObject(hMemoryBitmap);
  576.            }
  577.            PostQuitMessage(0);
  578.        }
  579.        else if (wParam == VK_F1) {
  580.            MessageBox(hwnd, TEXT("I made an Infinite Canvas app using GDI and Memory DC, no need for bloated Godot Engine/ Frameworks or M$ Infinite Canvas Control! Eternity of effort paid off! (763 lines of code) by Entisoft Software (c) Evans Thorpemorton"), TEXT("Information"), MB_OK | MB_ICONINFORMATION);
  581.        }
  582.        return 0;
  583.    }
  584.  
  585.    case WM_KEYUP:
  586.    {
  587.        if (wParam == VK_SPACE) {
  588.            isSpacePressed = false;
  589.            SetCursor(LoadCursor(NULL, IDC_ARROW));
  590.            ReleaseCapture();  // Release mouse capture when space is released
  591.            return 0;
  592.        }
  593.    }
  594.        //break;
  595.  
  596.        // Update WM_LBUTTONDOWN handler:
  597.    case WM_LBUTTONDOWN:
  598.    {
  599.        if (!isSpacePressed) {
  600.            isDrawing = true;
  601.            SetCapture(hwnd);
  602.  
  603.            // Get cursor position
  604.            int x = LOWORD(lParam);
  605.            int y = HIWORD(lParam);
  606.  
  607.            // Convert screen coordinates to canvas coordinates
  608.            int canvasX = x + scrollX;
  609.            int canvasY = y + scrollY;
  610.  
  611.            // Draw at the cursor position
  612.            DrawBrush(hMemoryDC, canvasX, canvasY);
  613.  
  614.            // Draw on screen for immediate feedback
  615.            HDC screenDC = GetDC(hwnd);
  616.            DrawBrush(screenDC, x, y);
  617.            ReleaseDC(hwnd, screenDC);
  618.        }
  619.        return 0;
  620.    }
  621.    //break;
  622.  
  623.  
  624.    // Optional: Add this to WM_LBUTTONUP to ensure smooth lines start fresh:
  625.    case WM_LBUTTONUP:
  626.    {
  627.        if (isPanning) {
  628.            isPanning = false;
  629.            ReleaseCapture();
  630.        }
  631.        if (isDrawing) {
  632.            isDrawing = false;
  633.            ReleaseCapture();
  634.        }
  635.        return 0;
  636.    }
  637.    //break;
  638.  
  639.    //new code
  640. // Modified WM_MOUSEMOVE handler:
  641. // Modify the WM_MOUSEMOVE handler:
  642.    // Modify the WM_MOUSEMOVE case in WindowProc:
  643.    case WM_MOUSEMOVE:
  644.    {
  645.        int x = LOWORD(lParam);
  646.        int y = HIWORD(lParam);
  647.  
  648.        if (isSpacePressed) {  // Removed the left click check
  649.            RECT clientRect;
  650.            GetClientRect(hwnd, &clientRect);
  651.  
  652.            int deltaX = x - lastMousePos.x;
  653.            int deltaY = y - lastMousePos.y;
  654.  
  655.            scrollX = std::max(0, std::min<int>(virtualWidth - clientRect.right, scrollX - deltaX));
  656.            scrollY = std::max(0, std::min<int>(virtualHeight - clientRect.bottom, scrollY - deltaY));
  657.  
  658.            lastMousePos.x = x;
  659.            lastMousePos.y = y;
  660.            InvalidateRect(hwnd, NULL, FALSE);
  661.        }
  662.        else if (isDrawing && (wParam & MK_LBUTTON)) {
  663.            int canvasX = x + scrollX;
  664.            int canvasY = y + scrollY;
  665.  
  666.            DrawBrush(hMemoryDC, canvasX, canvasY, isEraserMode);
  667.  
  668.            HDC screenDC = GetDC(hwnd);
  669.            DrawBrush(screenDC, x, y, isEraserMode);
  670.            ReleaseDC(hwnd, screenDC);
  671.        }
  672.        return 0;
  673.    }
  674.    //break;
  675.  
  676.    /*    case WM_MOUSEMOVE:
  677.            if (isDrawing) {
  678.                HDC hdc = GetDC(hwnd);
  679.                DrawBrush(hdc, LOWORD(lParam), HIWORD(lParam));
  680.                ReleaseDC(hwnd, hdc);
  681.            }
  682.            else if (isErasing) {
  683.                HDC hdc = GetDC(hwnd);
  684.                Erase(hdc, LOWORD(lParam), HIWORD(lParam));
  685.                ReleaseDC(hwnd, hdc);
  686.            }
  687.            else if (isClearing) {
  688.                HDC hdc = GetDC(hwnd);
  689.                RECT rect;
  690.                GetClientRect(hwnd, &rect);
  691.                ClearDrawing(hdc, rect.right, rect.bottom);
  692.                ReleaseDC(hwnd, hdc);
  693.                isClearing = false;
  694.            }
  695.            break;
  696.    */
  697.    case WM_SIZE:
  698.    {
  699.        // Handle status bar
  700.        HWND hStatus = GetDlgItem(hwnd, 0);
  701.        if (hStatus) {
  702.            SendMessage(hStatus, WM_SIZE, 0, 0);
  703.            UpdateStatus(hwnd);  // Update after resize
  704.        }
  705.  
  706.        // Handle window size changes
  707.        if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) {
  708.            InvalidateRect(hwnd, NULL, TRUE);
  709.        }
  710.  
  711.        return 0;
  712.    }
  713.  
  714.    //LASTCLASS::
  715.    /*if (wParam == SIZE_MINIMIZED) {
  716.        minimizedDrawnBrushstrokes = storedBrushstrokes;
  717.        minimizedErasedBrushstrokes = storedEraserstrokes;
  718.    }
  719.    else if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) {
  720.        storedBrushstrokes = minimizedDrawnBrushstrokes;
  721.        storedEraserstrokes = minimizedErasedBrushstrokes;
  722.  
  723.        // Redraw the window
  724.        InvalidateRect(hwnd, NULL, TRUE);
  725.    }*/
  726.    //gonnareplace winner!
  727.    /*if (wParam == SIZE_MINIMIZED) {
  728.        minimizedDrawnBrushstrokes = storedBrushstrokes;
  729.        minimizedErasedBrushstrokes = storedEraserstrokes;
  730.    }
  731.    else if (wParam == SIZE_RESTORED) {
  732.        storedBrushstrokes = minimizedDrawnBrushstrokes;
  733.        storedEraserstrokes = minimizedErasedBrushstrokes;
  734.        InvalidateRect(hwnd, NULL, TRUE);
  735.    }*/
  736.    //start chatgpt new modified code
  737.    /*if (wParam == SIZE_MINIMIZED) {
  738.        // Save the drawn and erased brushstrokes when minimizing
  739.        minimizedDrawnBrushstrokes = storedBrushstrokes;
  740.        minimizedErasedBrushstrokes = storedEraserstrokes;
  741.    }
  742.    else if (wParam == SIZE_RESTORED) {
  743.        // Restore the minimized brushstrokes when restoring
  744.        storedBrushstrokes = minimizedDrawnBrushstrokes;
  745.        storedEraserstrokes = minimizedErasedBrushstrokes;
  746.        // Trigger a repaint to redraw the brushstrokes
  747.        InvalidateRect(hwnd, NULL, TRUE);
  748.    }*/
  749.    //end chatgpt new modified code
  750.  
  751.    //start working but no erase history code (adding brushstruct for eraser logic) fallbackcode
  752.    /*if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) {
  753.        RECT rect;
  754.        GetClientRect(hwnd, &rect);
  755.        //ClearDrawing(hdc, rect.right, rect.bottom);
  756.    }*/
  757.    //end working but no erase history code fallbackcode
  758.  
  759.    //new replaced chatgpt
  760.    /*if (wParam == SIZE_MAXIMIZED) {
  761.        RECT rect;
  762.        GetClientRect(hwnd, &rect);
  763.        ClearDrawing(hdc, rect.right, rect.bottom);
  764.    }*/
  765.    /*else if (wParam == SIZE_RESTORED) {
  766.         RECT rect;
  767.         GetClientRect(hwnd, &rect);
  768.         if (isPaintbrushSelected) {
  769.             // Redraw the stored doodle contents for the Paintbrush tool
  770.             for (const auto& point : paintbrushDoodlePoints) {
  771.                 // Use the stored points to redraw the doodle contents for the Paintbrush tool
  772.                 // Example: Draw a small circle at each point
  773.                 Ellipse(hdc, point.x - 2, point.y - 2, point.x + 2, point.y + 2);
  774.             }
  775.         }
  776.     }*/
  777.     //old code
  778. //new replaced chatgpt
  779. /*else if (wParam == SIZE_RESTORED) {
  780.     RECT rect;
  781.     GetClientRect(hwnd, &rect);
  782.         // Handle resizing of contents when the window is restored
  783.         // Add code to restore doodle contents here
  784.     }
  785.     else if (wParam == SIZE_MINIMIZED) {
  786.         // Handle content when the window is minimized
  787.     }*/
  788.     //}
  789.     //break;
  790.  
  791.     // Modified WM_PAINT handler:
  792.    // Modify WM_PAINT to handle the centered view
  793.    case WM_PAINT:
  794.    {
  795.        PAINTSTRUCT ps;
  796.        HDC hdc = BeginPaint(hwnd, &ps);
  797.  
  798.        RECT clientRect;
  799.        GetClientRect(hwnd, &clientRect);
  800.        int windowWidth = clientRect.right - clientRect.left;
  801.        int windowHeight = clientRect.bottom - clientRect.top;
  802.  
  803.        // Create double buffer
  804.        HDC memDC = CreateCompatibleDC(hdc);
  805.        HBITMAP memBitmap = CreateCompatibleBitmap(hdc, windowWidth, windowHeight);
  806.        HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
  807.  
  808.        // Clear background in memory DC
  809.        HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  810.        FillRect(memDC, &clientRect, whiteBrush);
  811.        DeleteObject(whiteBrush);
  812.  
  813.        // Draw from memory DC to double buffer
  814.        BitBlt(memDC, 0, 0, windowWidth, windowHeight,
  815.            hMemoryDC, scrollX, scrollY, SRCCOPY);
  816.  
  817.        // Copy double buffer to screen
  818.        BitBlt(hdc, 0, 0, windowWidth, windowHeight,
  819.            memDC, 0, 0, SRCCOPY);
  820.  
  821.        // Cleanup
  822.        SelectObject(memDC, oldBitmap);
  823.        DeleteObject(memBitmap);
  824.        DeleteDC(memDC);
  825.  
  826.        EndPaint(hwnd, &ps);
  827.        return 0;
  828.    }
  829.  
  830.    // added newly to set Normal Pointer & not Busy Pointer
  831.    case WM_SETCURSOR:
  832.    {
  833.        if (LOWORD(lParam) == HTCLIENT) {  // Only in client area
  834.            if (isSpacePressed) {
  835.                SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  836.                return TRUE;
  837.            }
  838.            else if (isPaintbrushSelected || isEraserMode) {
  839.                SetCursor(LoadCursor(NULL, IDC_CROSS));
  840.                return TRUE;
  841.            }
  842.        }
  843.        return DefWindowProc(hwnd, uMsg, wParam, lParam);  // Use default cursor for non-client area
  844.    }
  845.  
  846.    case WM_DESTROY:
  847.    {
  848.        if (hMemoryDC) {
  849.            if (hOldBitmap) {
  850.                SelectObject(hMemoryDC, hOldBitmap);
  851.            }
  852.            DeleteDC(hMemoryDC);
  853.        }
  854.        if (hMemoryBitmap) {
  855.            DeleteObject(hMemoryBitmap);
  856.        }
  857.        PostQuitMessage(0);
  858.        return 0;
  859.    }
  860.  
  861.    default:
  862.        return DefWindowProc(hwnd, uMsg, wParam, lParam);
  863.    }
  864.    return 0;
  865. }
  866.  
  867. // Add this before WinMain
  868. INITCOMMONCONTROLSEX icex;
  869.  
  870. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
  871.    // Initialize Common Controls
  872.    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  873.    icex.dwICC = ICC_BAR_CLASSES;
  874.    InitCommonControlsEx(&icex);
  875.    
  876.    const wchar_t CLASS_NAME[] = L"DoodleAppClass";
  877.  
  878.    WNDCLASS wc = { };
  879.  
  880.    wc.lpfnWndProc = WindowProc;
  881.    wc.hInstance = hInstance;
  882.    wc.lpszClassName = CLASS_NAME;
  883.    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));     // Add this line
  884.  
  885.    RegisterClass(&wc);
  886.  
  887.    hInst = hInstance;
  888.  
  889.    // In WinMain, modify CreateWindowEx:
  890.    HWND hwnd = CreateWindowEx(
  891.        0,  // No extra styles needed
  892.        CLASS_NAME,
  893.        L"Infinite Canvas Doodle App (P=Brush E=Eraser C=Clear +-=BrushSize Space+Drag=Scroll F1=About)",
  894.        WS_OVERLAPPEDWINDOW | WS_MAXIMIZE,
  895.        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  896.        NULL,
  897.        NULL,
  898.        hInstance,
  899.        NULL
  900.    );
  901.  
  902.    // Enable double buffering using SetWindowLong
  903.    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_COMPOSITED);
  904.  
  905.    //hdc = GetDC(hwnd);
  906.    if (hwnd == NULL) {
  907.        return 0;
  908.    }
  909.  
  910.    // Add to WinMain after creating main window
  911.    HWND hStatus = CreateWindowEx(
  912.        0,
  913.        STATUSCLASSNAME,
  914.        NULL,
  915.        WS_CHILD | WS_VISIBLE,
  916.        0, 0, 0, 0,
  917.        hwnd,
  918.        NULL,
  919.        hInstance,
  920.        NULL
  921.    );
  922.  
  923.    // Initial status update
  924.    UpdateStatus(hwnd);
  925.  
  926.    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
  927.  
  928.    //start chatgpt new modified code
  929.    /*MSG msg = {};
  930.    while (GetMessage(&msg, NULL, 0, 0)) {
  931.        TranslateMessage(&msg);
  932.        DispatchMessage(&msg);
  933.        if (msg.message == WM_SIZE) {
  934.            if (msg.wParam == SIZE_MINIMIZED) {
  935.                // Save the drawn and erased brushstrokes when minimizing
  936.                std::vector<Brushstroke> minimizedDrawnBrushstrokes = storedBrushstrokes;
  937.                std::vector<Eraserstroke> minimizedErasedBrushstrokes = storedEraserStrokes;
  938.            }
  939.            else if (msg.wParam == SIZE_RESTORED) {
  940.                // Restore the minimized brushstrokes when restoring
  941.                storedBrushstrokes = minimizedDrawnBrushstrokes;
  942.                storedEraserStrokes = minimizedErasedBrushstrokes;
  943.                // Trigger a repaint to redraw the brushstrokes
  944.                InvalidateRect(hwnd, NULL, TRUE);
  945.            }
  946.        }
  947.    }*/
  948.    //end chatgpt new modified code
  949.  
  950.    //start working but no erase history code (adding brushstruct for eraser logic) fallbackcode
  951.    MSG msg = {};
  952.    while (GetMessage(&msg, NULL, 0, 0)) {
  953.        TranslateMessage(&msg);
  954.        DispatchMessage(&msg);
  955.    }
  956.    //end working but no erase history code fallbackcode
  957.  
  958.    return 0;
  959. }
Add Comment
Please, Sign In to add comment