alien_fx_fiend

Infinite Canvas More Features Optimized v3 FINAL!

Nov 6th, 2024 (edited)
12
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 42.47 KB | Source Code | 0 0
  1. ==++ Here's the full source code for (file 1/1) of "main.cpp"::++==
  2. #define NOMINMAX
  3. #define WIN32_LEAN_AND_MEAN
  4. #include <windows.h>
  5. #include <windef.h>
  6. #include <wingdi.h>
  7. #include <algorithm>
  8. #include <iostream>
  9. #include <vector>
  10. #include <cmath>
  11. #include <commctrl.h>
  12. #include <commdlg.h>  // Add at the top with other includes
  13. //#include <msimg32.h>
  14. //#include <windows.h>
  15. #include <stdio.h>
  16. #include <iostream>
  17. #include "resource.h"  // Add this with your other includes
  18.  
  19. #pragma comment(lib, "comctl32.lib")
  20. #pragma comment(lib, "comdlg32.lib")
  21. #pragma comment(lib, "msimg32.lib")
  22. using namespace std;
  23.  
  24. struct DrawPoint {
  25.    int x, y;
  26.    DWORD timestamp;
  27.  
  28.    DrawPoint() : x(0), y(0), timestamp(0) {}  // Default constructor
  29.    DrawPoint(int px, int py) : x(px), y(py), timestamp(GetTickCount()) {}  // Two-parameter constructor
  30. };
  31.  
  32. std::vector<DrawPoint> strokeBuffer;
  33. const int STROKE_BUFFER_SIZE = 3;  // Adjust for curve smoothness
  34. const double MAX_SPEED = 1000.0;   // Maximum pixels per second
  35. const double MIN_DISTANCE = 2.0;   // Minimum distance between points
  36.  
  37. // Forward Declarations
  38. //struct Brushstroke;
  39. //struct Eraserstroke;
  40.  
  41. void DrawSmoothStroke(HDC hdc, const std::vector<DrawPoint>& points, bool isEraser);
  42. void DrawBrush(HDC hdc, int x, int y, bool isEraser = false, bool interpolate = true);
  43. //void DebugDraw(HDC hdc);
  44. void Erase(HDC hdc, int x, int y);
  45. void ClearDrawing(HWND hwnd);
  46. void UpdateStatus(HWND hwnd);
  47. //void ClearDrawing(HDC hdc, int width, int height);
  48. //void DrawSmoothBrush(HDC hdc, int x, int y, bool isScreenDC);
  49. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  50.  
  51. // Add these global variables at the top
  52. int virtualWidth = 8192;
  53. int virtualHeight = 8192;
  54. int scrollX = 0;  // Will be initialized properly in InitializeMemoryBitmap
  55. int scrollY = 0;  // Will be initialized properly in InitializeMemoryBitmap
  56. int canvasWidth = 8192;
  57. int canvasHeight = 8192;
  58. bool isSpacePressed = false;
  59. bool isPanning = false;  // Add this new variable
  60. POINT lastDrawPoint = { -1, -1 };
  61. POINT lastMousePos = { 0, 0 };
  62. POINT dragStart = { 0, 0 };
  63. //std::vector<POINT> currentStroke;  // Store points in current stroke
  64. // Add these global variables if not already present
  65. //std::vector<Brushstroke> storedBrushstrokes;
  66. //std::vector<Eraserstroke> storedEraserstrokes;
  67. HDC hMemoryDC = NULL;
  68. HBITMAP hMemoryBitmap = NULL;
  69. HBITMAP hOldBitmap = NULL;  // Add this to store the old bitmap
  70. HINSTANCE hInst;
  71. //bool isPaintbrushSelected = true;  // Add a global variable to track the selected tool
  72. // Define a vector to store the doodle points for the Paintbrush tool
  73. //std::vector<POINT> paintbrushDoodlePoints;
  74. //new mod code
  75. POINT previousPoint;  // Add a new global variable to track the previous point
  76. // Declare hdc as a global variable
  77. HDC hdc;
  78. HWND hWnd;  // Declare the window handle variable globally or within the appropriate scope
  79. //bool needsRedraw = true;  // Add this line at the top of your file
  80.            // Declare a global variable to specify the grid spacing
  81. //int gridSpacing = 20;
  82. const int GRID_SIZE = 100;  // Size of each grid cell
  83. const COLORREF GRID_COLOR = RGB(200, 200, 220);  // Lighter blue-grey
  84. HDC hGridDC = NULL;
  85. HBITMAP hGridBitmap = NULL;
  86. BOOL gridInitialized = FALSE;
  87. // Add to globals
  88. float gridZoomFactor = 1.0f;
  89. bool showGrid = true;
  90. bool useAlphaGrid = false;  // Toggle between normal and alpha-blended grid
  91. int gridOpacity = 255;  // 0-255
  92. COLORREF currentBrushColor = RGB(255, 0, 0);  // Default red
  93. bool isInitialized = false;
  94. bool isPaintbrushSelected = true;;
  95. bool isDrawing = false;
  96. bool isErasing = false;
  97. bool isClearing = false;
  98. bool isEraserMode = false;
  99. bool isEraserSelected = false;
  100. int minBrushSize = 5;
  101. int maxBrushSize = 50;
  102. int brushSize = 10;
  103. //POINT previousPoint;
  104.  
  105.  
  106. // Define a struct to store brushstroke information
  107. /*struct Brushstroke {
  108.    int x;
  109.    int y;
  110.    int size;
  111.    COLORREF color;
  112.    // Add any other necessary properties for the brushstroke
  113. };*/
  114.  
  115. // Define a struct to store eraserstroke information
  116. /*struct Eraserstroke {
  117.    int x;
  118.    int y;
  119.    int size;
  120.    COLORREF color;
  121.    // Add any other necessary properties for the eraserstroke
  122. };*/
  123.  
  124. // Declare a vector to store the brushstrokes
  125. //std::vector<Brushstroke> storedBrushstrokes;
  126. //std::vector<Eraserstroke> storedEraserstrokes;
  127. // Global variables to store the minimized brushstrokes
  128. //std::vector<Brushstroke> minimizedDrawnBrushstrokes;
  129. //std::vector<Eraserstroke> minimizedErasedBrushstrokes;
  130.  
  131. // Function declaration for DrawGrid
  132. //void DrawGrid(HDC hdc, int spacing, COLORREF color); //drawgrid disableddefault
  133.  
  134. // Optimized DrawGrid function to efficiently draw both vertical and horizontal lines
  135.  
  136. // Add this function
  137. /*void CleanupOldStrokes() {
  138.    const size_t MAX_STROKES = 100000;
  139.    if (storedBrushstrokes.size() > MAX_STROKES) {
  140.        storedBrushstrokes.erase(storedBrushstrokes.begin(),
  141.            storedBrushstrokes.begin() + (storedBrushstrokes.size() - MAX_STROKES));
  142.    }
  143.    if (storedEraserstrokes.size() > MAX_STROKES) {
  144.        storedEraserstrokes.erase(storedEraserstrokes.begin(),
  145.            storedEraserstrokes.begin() + (storedEraserstrokes.size() - MAX_STROKES));
  146.    }
  147. }*/
  148.  
  149. //new gpt broken?
  150. /*void DrawBrush(HDC hdc, int x, int y) {
  151.    // Debug output
  152.    char debug[256];
  153.    sprintf_s(debug, "DrawBrush called at: x=%d, y=%d\n", x, y);
  154.    OutputDebugStringA(debug);
  155.  
  156.    HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
  157.    HPEN redPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
  158.  
  159.    if (!redBrush || !redPen) {
  160.        OutputDebugStringA("Failed to create brush or pen\n");
  161.        return;
  162.    }
  163.  
  164.    HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, redBrush);
  165.    HPEN oldPen = (HPEN)SelectObject(hdc, redPen);
  166.  
  167.    if (!oldBrush || !oldPen) {
  168.        OutputDebugStringA("Failed to select brush or pen\n");
  169.        DeleteObject(redBrush);
  170.        DeleteObject(redPen);
  171.        return;
  172.    }
  173.  
  174.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  175.  
  176.    SelectObject(hdc, oldBrush);
  177.    SelectObject(hdc, oldPen);
  178.    DeleteObject(redBrush);
  179.    DeleteObject(redPen);
  180. }*/
  181.  
  182.  
  183. // Add this function to initialize the memory bitmap
  184. // Add this function
  185. // Modify InitializeMemoryBitmap:
  186. void InitializeMemoryBitmap(HWND hwnd) {
  187.    HDC hdc = GetDC(hwnd);
  188.    if (!hdc) {
  189.        return;
  190.    }
  191.  
  192.    hMemoryDC = CreateCompatibleDC(hdc);
  193.    if (!hMemoryDC) {
  194.        ReleaseDC(hwnd, hdc);
  195.        return;
  196.    }
  197.  
  198.    hMemoryBitmap = CreateCompatibleBitmap(hdc, virtualWidth, virtualHeight);
  199.    if (!hMemoryBitmap) {
  200.        DeleteDC(hMemoryDC);
  201.        ReleaseDC(hwnd, hdc);
  202.        return;
  203.    }
  204.  
  205.    hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hMemoryBitmap);
  206.  
  207.    // Fill with white background
  208.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  209.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  210.    FillRect(hMemoryDC, &rect, whiteBrush);
  211.    DeleteObject(whiteBrush);
  212.  
  213.    ReleaseDC(hwnd, hdc);
  214.    isInitialized = true;
  215.  
  216.    // Draw coordinate guides
  217.    HPEN guidePen = CreatePen(PS_SOLID, 1, RGB(200, 200, 200));
  218.    SelectObject(hMemoryDC, guidePen);
  219.  
  220.    // Draw center lines
  221.    MoveToEx(hMemoryDC, virtualWidth / 2, 0, NULL);
  222.    LineTo(hMemoryDC, virtualWidth / 2, virtualHeight);
  223.    MoveToEx(hMemoryDC, 0, virtualHeight / 2, NULL);
  224.    LineTo(hMemoryDC, virtualWidth, virtualHeight / 2);
  225.  
  226.    // Draw border
  227.    HPEN edgePen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
  228.    SelectObject(hMemoryDC, edgePen);
  229.    Rectangle(hMemoryDC, 0, 0, virtualWidth - 1, virtualHeight - 1);
  230.  
  231.    DeleteObject(guidePen);
  232.    DeleteObject(edgePen);
  233.  
  234.    // Initialize scroll position to center the canvas
  235.    RECT clientRect;
  236.    GetClientRect(hwnd, &clientRect);
  237.    scrollX = (virtualWidth - clientRect.right) / 2;
  238.    scrollY = (virtualHeight - clientRect.bottom) / 2;
  239. }
  240.  
  241.    // Initialize scroll position to center the canvas
  242.    //RECT clientRect;
  243.    //GetClientRect(hwnd, &clientRect);
  244.    //scrollX = -virtualWidth / 2 + (clientRect.right / 2);
  245.    //scrollY = -virtualHeight / 2 + (clientRect.bottom / 2);
  246. //}
  247.  
  248. void DrawSmoothStroke(HDC hdc, const std::vector<DrawPoint>& points, bool isEraser) {
  249.    if (points.size() < 2) return;
  250.  
  251.    COLORREF color = isEraser ? RGB(255, 255, 255) : currentBrushColor;
  252.    HBRUSH brush = CreateSolidBrush(color);
  253.    HPEN pen = CreatePen(PS_SOLID, 1, color);
  254.    HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, brush);
  255.    HPEN oldPen = (HPEN)SelectObject(hdc, pen);
  256.  
  257.    // Draw first point
  258.    Ellipse(hdc,
  259.        points[0].x - brushSize,
  260.        points[0].y - brushSize,
  261.        points[0].x + brushSize,
  262.        points[0].y + brushSize);
  263.  
  264.    // Draw smooth line between points
  265.    for (size_t i = 1; i < points.size(); ++i) {
  266.        const DrawPoint& prev = points[i - 1];
  267.        const DrawPoint& curr = points[i];
  268.  
  269.        double dx = curr.x - prev.x;
  270.        double dy = curr.y - prev.y;
  271.        double distance = sqrt(dx * dx + dy * dy);
  272.  
  273.        if (distance > 0) {
  274.            int steps = (int)(distance / (brushSize * 0.3)); // Adjust density
  275.            steps = min(max(steps, 1), 15); // Limit steps
  276.  
  277.            for (int step = 0; step <= steps; ++step) {
  278.                double t = step / (double)steps;
  279.                int x = (int)(prev.x + dx * t);
  280.                int y = (int)(prev.y + dy * t);
  281.  
  282.                // Draw interpolated point
  283.                Ellipse(hdc,
  284.                    x - brushSize,
  285.                    y - brushSize,
  286.                    x + brushSize,
  287.                    y + brushSize);
  288.            }
  289.        }
  290.    }
  291.  
  292.    SelectObject(hdc, oldBrush);
  293.    SelectObject(hdc, oldPen);
  294.    DeleteObject(brush);
  295.    DeleteObject(pen);
  296. }
  297.  
  298. // Replace your DrawBrush function with this simpler version:
  299. // Modify DrawBrush function to use currentBrushColor
  300. void DrawBrush(HDC hdc, int x, int y, bool isEraser, bool interpolate) {
  301.    if (x < 0 || x > virtualWidth || y < 0 || y > virtualHeight) {
  302.        return;
  303.    }
  304.  
  305.    COLORREF color = isEraser ? RGB(255, 255, 255) : currentBrushColor;
  306.    HBRUSH brush = CreateSolidBrush(color);
  307.    HPEN pen = CreatePen(PS_SOLID, 1, color);
  308.    HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, brush);
  309.    HPEN oldPen = (HPEN)SelectObject(hdc, pen);
  310.  
  311.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  312.  
  313.    SelectObject(hdc, oldBrush);
  314.    SelectObject(hdc, oldPen);
  315.    DeleteObject(brush);
  316.    DeleteObject(pen);
  317. }
  318.  
  319. // Optional: Add these helper functions for better stroke management
  320. void StartStroke(int x, int y) {
  321.    strokeBuffer.clear();
  322.    strokeBuffer.push_back(DrawPoint(x, y));
  323. }
  324.  
  325. void AddToStroke(int x, int y) {
  326.    if (strokeBuffer.empty()) {
  327.        StartStroke(x, y);
  328.        return;
  329.    }
  330.  
  331.    const DrawPoint& lastPt = strokeBuffer.back();
  332.    double dx = x - lastPt.x;
  333.    double dy = y - lastPt.y;
  334.    double distance = sqrt(dx * dx + dy * dy);
  335.  
  336.    if (distance >= MIN_DISTANCE) {
  337.        strokeBuffer.push_back(DrawPoint(x, y));
  338.        while (strokeBuffer.size() > STROKE_BUFFER_SIZE) {
  339.            strokeBuffer.erase(strokeBuffer.begin());
  340.        }
  341.    }
  342. }
  343.  
  344. void EndStroke() {
  345.    strokeBuffer.clear();
  346. }
  347.  
  348. // Add this function to show color dialog
  349. void ShowColorPicker(HWND hwnd) {
  350.    CHOOSECOLOR cc = { sizeof(CHOOSECOLOR) };
  351.    static COLORREF customColors[16] = { 0 };
  352.  
  353.    cc.hwndOwner = hwnd;
  354.    cc.rgbResult = currentBrushColor;
  355.    cc.lpCustColors = customColors;
  356.    cc.Flags = CC_FULLOPEN | CC_RGBINIT;
  357.  
  358.    if (ChooseColor(&cc)) {
  359.        currentBrushColor = cc.rgbResult;
  360.        UpdateStatus(hwnd);  // Update status bar to show new color
  361.    }
  362. }
  363.  
  364.  
  365. //old pre-gpt
  366. /*void DrawBrush(HDC hdc, int x, int y) {
  367.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0));  // Set the brush color to fully red
  368.    SelectObject(hdc, GetStockObject(NULL_PEN));  // Set the pen to null to remove the border
  369.    SelectObject(hdc, hBrush);
  370.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  371.    DeleteObject(hBrush);
  372. }*/
  373.  
  374.  
  375.  
  376. // Add this debug function
  377. /*void DebugDraw(HDC hdc) {
  378.    HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
  379.    RECT testRect = { 100, 100, 200, 200 };
  380.    FillRect(hdc, &testRect, redBrush);
  381.    DeleteObject(redBrush);
  382. }*/
  383. /*void DrawBrush(HDC hdc, int x, int y) {
  384.    HRGN hRgn = CreateEllipticRgn(x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  385.    FillRgn(hdc, hRgn, CreateSolidBrush(RGB(255, 0, 0)));
  386.    DeleteObject(hRgn);
  387. }*/
  388.  
  389. //broken old
  390. void Erase(HDC hdc, int x, int y) {
  391.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  392.    SelectObject(hdc, GetStockObject(NULL_PEN));
  393.    SelectObject(hdc, hBrush);
  394.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  395.    DeleteObject(hBrush);
  396. }
  397. /*void Erase(HDC hdc, int x, int y) {
  398.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the brush color to white
  399.    HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);
  400.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  401.    SelectObject(hdc, hOldBrush);
  402.    DeleteObject(hBrush);
  403. }*/
  404.  
  405. //start test of new eraser
  406. /*void Erase(HDC hdc, int x, int y) {
  407.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  408.    SelectObject(hdc, GetStockObject(NULL_PEN));
  409.    SelectObject(hdc, hBrush);
  410.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  411.    DeleteObject(hBrush);
  412. }*/
  413. //end test of new eraser
  414.  
  415. //start commented out testing new gpt function eraser
  416. /*void Erase(HDC hdc, int x, int y) {
  417.    // HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the brush color to white
  418.    // HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));  // Set the brush color to black
  419.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the brush color to white
  420.    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));  // Set the pen color to white
  421.    HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);
  422.    HGDIOBJ hOldPen = SelectObject(hdc, hPen);
  423.    Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  424.    SelectObject(hdc, hOldBrush);
  425.    SelectObject(hdc, hOldPen);
  426.    DeleteObject(hBrush);
  427.    DeleteObject(hPen);
  428. }*/
  429. //end commented out testing new gpt function eraser
  430. void ClearCanvas(HWND hwnd) {
  431.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  432.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  433.    FillRect(hMemoryDC, &rect, whiteBrush);
  434.    DeleteObject(whiteBrush);
  435.    InvalidateRect(hwnd, NULL, FALSE);
  436. }
  437. void ClearDrawing(HWND hwnd) {
  438.    // Clear the canvas
  439.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  440.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  441.    FillRect(hMemoryDC, &rect, whiteBrush);
  442.    DeleteObject(whiteBrush);
  443.  
  444.    // Reset scroll position to center
  445.    RECT clientRect;
  446.    GetClientRect(hwnd, &clientRect);
  447.    scrollX = (virtualWidth - clientRect.right) / 2;
  448.    scrollY = (virtualHeight - clientRect.bottom) / 2;
  449.  
  450.    // Redraw coordinate guides and border
  451.    // Draw coordinate guides
  452.    HPEN guidePen = CreatePen(PS_SOLID, 1, RGB(200, 200, 200));
  453.    SelectObject(hMemoryDC, guidePen);
  454.  
  455.    // Draw center lines
  456.    MoveToEx(hMemoryDC, virtualWidth / 2, 0, NULL);
  457.    LineTo(hMemoryDC, virtualWidth / 2, virtualHeight);
  458.    MoveToEx(hMemoryDC, 0, virtualHeight / 2, NULL);
  459.    LineTo(hMemoryDC, virtualWidth, virtualHeight / 2);
  460.  
  461.    // Draw border
  462.    HPEN edgePen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
  463.    SelectObject(hMemoryDC, edgePen);
  464.    Rectangle(hMemoryDC, 0, 0, virtualWidth - 1, virtualHeight - 1);
  465.  
  466.    DeleteObject(guidePen);
  467.    DeleteObject(edgePen);
  468.  
  469.    // Force redraw
  470.    InvalidateRect(hwnd, NULL, FALSE);
  471. }
  472.  
  473. // Add this function
  474. void InitializeGridCache(HDC hdc) {
  475.    if (hGridDC) {
  476.        DeleteDC(hGridDC);
  477.        DeleteObject(hGridBitmap);
  478.    }
  479.  
  480.    int scaledGridSize = (int)(GRID_SIZE * gridZoomFactor);
  481.    hGridDC = CreateCompatibleDC(hdc);
  482.    hGridBitmap = CreateCompatibleBitmap(hdc, scaledGridSize, scaledGridSize);
  483.    HBITMAP oldBitmap = (HBITMAP)SelectObject(hGridDC, hGridBitmap);
  484.  
  485.    // Fill with white background
  486.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  487.    RECT rect = { 0, 0, scaledGridSize, scaledGridSize };
  488.    FillRect(hGridDC, &rect, whiteBrush);
  489.    DeleteObject(whiteBrush);
  490.  
  491.    // Draw grid lines
  492.    HPEN gridPen = CreatePen(PS_SOLID, 1, GRID_COLOR);
  493.    HPEN oldPen = (HPEN)SelectObject(hGridDC, gridPen);
  494.  
  495.    // Draw right and bottom lines of the cell
  496.    MoveToEx(hGridDC, scaledGridSize - 1, 0, NULL);
  497.    LineTo(hGridDC, scaledGridSize - 1, scaledGridSize);
  498.    MoveToEx(hGridDC, 0, scaledGridSize - 1, NULL);
  499.    LineTo(hGridDC, scaledGridSize, scaledGridSize - 1);
  500.  
  501.    SelectObject(hGridDC, oldPen);
  502.    DeleteObject(gridPen);
  503.    gridInitialized = TRUE;
  504. }
  505.  
  506. // Add this function to draw the grid
  507. // Modified DrawGrid function using cached grid cell
  508. void DrawGrid(HDC hdc, const RECT& clientRect, int scrollX, int scrollY) {
  509.    // Set up DC for better line quality
  510.    SetBkMode(hdc, TRANSPARENT);
  511.  
  512.    HPEN gridPen = CreatePen(PS_SOLID, 1, GRID_COLOR);
  513.    HPEN oldPen = (HPEN)SelectObject(hdc, gridPen);
  514.  
  515.    int scaledGridSize = (int)(GRID_SIZE * gridZoomFactor);
  516.  
  517.    // Calculate grid offset
  518.    int offsetX = -(scrollX % scaledGridSize);
  519.    int offsetY = -(scrollY % scaledGridSize);
  520.  
  521.    // Draw vertical lines
  522.    for (int x = offsetX; x <= clientRect.right; x += scaledGridSize) {
  523.        MoveToEx(hdc, x, 0, NULL);
  524.        LineTo(hdc, x, clientRect.bottom);
  525.    }
  526.  
  527.    // Draw horizontal lines
  528.    for (int y = offsetY; y <= clientRect.bottom; y += scaledGridSize) {
  529.        MoveToEx(hdc, 0, y, NULL);
  530.        LineTo(hdc, clientRect.right, y);
  531.    }
  532.  
  533.    // Clean up
  534.    SelectObject(hdc, oldPen);
  535.    DeleteObject(gridPen);
  536. }
  537.  
  538. void DrawGridWithAlpha(HDC hdc, const RECT& clientRect, int scrollX, int scrollY) {
  539.    HDC tempDC = CreateCompatibleDC(hdc);
  540.    HBITMAP tempBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom);
  541.    HBITMAP oldTempBitmap = (HBITMAP)SelectObject(tempDC, tempBitmap);
  542.  
  543.    // Fill with white background
  544.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  545.    FillRect(tempDC, &clientRect, whiteBrush);
  546.    DeleteObject(whiteBrush);
  547.  
  548.    // Draw grid on temporary DC
  549.    SetBkMode(tempDC, TRANSPARENT);
  550.    HPEN gridPen = CreatePen(PS_SOLID, 1, GRID_COLOR);
  551.    HPEN oldPen = (HPEN)SelectObject(tempDC, gridPen);
  552.  
  553.    int scaledGridSize = (int)(GRID_SIZE * gridZoomFactor);
  554.    int offsetX = -(scrollX % scaledGridSize);
  555.    int offsetY = -(scrollY % scaledGridSize);
  556.  
  557.    // Draw vertical lines
  558.    for (int x = offsetX; x <= clientRect.right; x += scaledGridSize) {
  559.        MoveToEx(tempDC, x, 0, NULL);
  560.        LineTo(tempDC, x, clientRect.bottom);
  561.    }
  562.  
  563.    // Draw horizontal lines
  564.    for (int y = offsetY; y <= clientRect.bottom; y += scaledGridSize) {
  565.        MoveToEx(tempDC, 0, y, NULL);
  566.        LineTo(tempDC, clientRect.right, y);
  567.    }
  568.  
  569.    SelectObject(tempDC, oldPen);
  570.    DeleteObject(gridPen);
  571.  
  572.    // Blend the grid
  573.    BLENDFUNCTION bf;
  574.    bf.BlendOp = AC_SRC_OVER;
  575.    bf.BlendFlags = 0;
  576.    bf.SourceConstantAlpha = gridOpacity;
  577.    bf.AlphaFormat = 0;
  578.  
  579.    AlphaBlend(hdc, 0, 0, clientRect.right, clientRect.bottom,
  580.        tempDC, 0, 0, clientRect.right, clientRect.bottom,
  581.        bf);
  582.  
  583.    // Cleanup
  584.    SelectObject(tempDC, oldTempBitmap);
  585.    DeleteObject(tempBitmap);
  586.    DeleteDC(tempDC);
  587. }
  588.  
  589. //newgptdelete
  590. /*void ClearDrawing(HWND hwnd) {
  591.    RECT rect = { 0, 0, virtualWidth, virtualHeight };
  592.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  593.    FillRect(hMemoryDC, &rect, whiteBrush);
  594.    DeleteObject(whiteBrush);
  595.    scrollX = -virtualWidth / 2;  // Reset to center
  596.    scrollY = -virtualHeight / 2; // Reset to center
  597.    InvalidateRect(hwnd, NULL, FALSE);
  598. }*/
  599. /*void ClearDrawing(HDC hdc, int width, int height) {
  600.    RECT rect = { 0, 0, width, height };
  601.    // HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the color to white
  602.    // HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));  // Set the color to black
  603.    HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  // Set the color to white
  604.    FillRect(hdc, &rect, hBrush);
  605.    DeleteObject(hBrush);
  606. }*/
  607.  
  608. //removing drawgrid
  609. /*void DrawGrid(HDC hdc, int spacing, COLORREF color) {
  610.    RECT rect;
  611.    GetClientRect(hWnd, &rect);
  612.  
  613.    HPEN hPen = CreatePen(PS_SOLID, 1, color);
  614.    HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
  615.  
  616.    // Draw vertical lines
  617.    for (int x = 0; x <= rect.right; x += spacing) {
  618.        MoveToEx(hdc, x, 0, NULL);
  619.        LineTo(hdc, x, rect.bottom);
  620.    }
  621.  
  622.    // Draw horizontal lines
  623.    for (int y = 0; y <= rect.bottom; y += spacing) {
  624.        MoveToEx(hdc, 0, y, NULL);
  625.        LineTo(hdc, rect.right, y);
  626.    }
  627.  
  628.    SelectObject(hdc, hOldPen);
  629.    DeleteObject(hPen);
  630. }*/
  631.  
  632. //gpts old drawgrid
  633. /*void DrawGrid(HDC hdc, int spacing, COLORREF color) {
  634.    RECT rect;
  635.    GetClientRect(hWnd, &rect);
  636.  
  637.    HPEN hPen = CreatePen(PS_SOLID, 1, color);
  638.    HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
  639.  
  640.    // Draw vertical lines
  641.    for (int x = 0; x < rect.right; x += spacing) {
  642.        MoveToEx(hdc, x, 0, NULL);
  643.        LineTo(hdc, x, rect.bottom);
  644.    }
  645.  
  646.    // Draw horizontal lines
  647.    for (int y = 0; y < rect.bottom; y += spacing) {
  648.        MoveToEx(hdc, 0, y, NULL);
  649.        LineTo(hdc, rect.right, y);
  650.    }
  651.  
  652.    SelectObject(hdc, hOldPen);
  653.    DeleteObject(hPen);
  654. }*/
  655.  
  656. //chatgpt disabled
  657. /*void DrawGrid(HDC hdc, int spacing, COLORREF color) {
  658.    RECT rect;
  659.    GetClientRect(hWnd, &rect);
  660.  
  661.    HPEN hPen = CreatePen(PS_SOLID, 1, color);
  662.    HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
  663.  
  664.    // Draw vertical lines
  665.    for (int x = 0; x < rect.right; x += spacing) {
  666.        MoveToEx(hdc, x, 0, NULL);
  667.        LineTo(hdc, x, rect.bottom);
  668.    }
  669.  
  670.    // Draw horizontal lines
  671.    for (int y = 0; y < rect.bottom; y += spacing) {
  672.        MoveToEx(hdc, 0, y, NULL);
  673.        LineTo(hdc, rect.right, y);
  674.    }
  675.  
  676.    SelectObject(hdc, hOldPen);
  677.    DeleteObject(hPen);
  678. }*/
  679.  
  680. //temp disabled for relocated code
  681. /*int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
  682.    const wchar_t CLASS_NAME[] = L"DoodleAppClass";
  683.  
  684.    WNDCLASS wc = { };
  685.  
  686.    wc.lpfnWndProc = WindowProc;
  687.    wc.hInstance = hInstance;
  688.    wc.lpszClassName = CLASS_NAME;
  689.  
  690.    RegisterClass(&wc);
  691.  
  692.    hInst = hInstance;
  693.  
  694.    HWND hwnd = CreateWindowEx(
  695.        0,
  696.        CLASS_NAME,
  697.        L"Doodle App",
  698.        WS_OVERLAPPEDWINDOW | WS_MAXIMIZE, //& ~WS_MINIMIZEBOX,  Add WS_MAXIMIZE style
  699.        // Disable the Minimize button
  700.  
  701.        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  702.  
  703.        NULL,
  704.        NULL,
  705.        hInstance,
  706.        NULL
  707.    );
  708.  
  709.    //hdc = GetDC(hWnd); //gptadded
  710.    if (hwnd == NULL) {
  711.        return 0;
  712.    }
  713.  
  714.    ShowWindow(hwnd, SW_SHOWMAXIMIZED);  // Show the window maximized
  715.  
  716.    //old code
  717.    //ShowWindow(hwnd, nCmdShow);
  718.  
  719.    MSG msg = { };
  720.    while (GetMessage(&msg, NULL, 0, 0)) {
  721.        TranslateMessage(&msg);
  722.        DispatchMessage(&msg);
  723.    }
  724.  
  725.    return 0;
  726. }*/
  727.  
  728. //new code
  729. /*void DrawSmoothBrush(HDC hdc, int x, int y) {
  730.    if (!isDrawing) return;
  731.  
  732.    int currentX = x + scrollX;
  733.    int currentY = y + scrollY;
  734.    int prevX = previousPoint.x + scrollX;
  735.    int prevY = previousPoint.y + scrollY;
  736.  
  737.    // Draw line between points for smoothness
  738.    int numPoints = 10;
  739.    for (int i = 0; i <= numPoints; i++) {
  740.        float t = (float)i / numPoints;
  741.        int drawX = prevX + (int)(t * (currentX - prevX));
  742.        int drawY = prevY + (int)(t * (currentY - prevY));
  743.  
  744.        if (isPaintbrushSelected) {
  745.            DrawBrush(hdc, drawX, drawY);
  746.        }
  747.        else if (isEraserSelected) {
  748.            Erase(hdc, drawX, drawY);
  749.        }
  750.    }
  751.  
  752.    previousPoint.x = x;
  753.    previousPoint.y = y;
  754. }*/
  755.  
  756. // Update status text when tool changes:
  757. // Modify UpdateStatus to show current color
  758. void UpdateStatus(HWND hwnd) {
  759.    HWND hStatus = GetDlgItem(hwnd, 0);
  760.    if (hStatus) {
  761.        wchar_t status[512];
  762.        BYTE r = GetRValue(currentBrushColor);
  763.        BYTE g = GetGValue(currentBrushColor);
  764.        BYTE b = GetBValue(currentBrushColor);
  765.  
  766.        // Show canvas center position instead of mouse position
  767.        int centerX = scrollX + (virtualWidth / 2);
  768.        int centerY = scrollY + (virtualHeight / 2);
  769.  
  770.        swprintf_s(status,
  771.            L"Mode: %s | Brush: %d | Color: RGB(%d,%d,%d) | Grid: %s%s | Zoom: %.1fx | Opacity: %d%% | Canvas Pos: (%d,%d)",
  772.            isEraserMode ? L"Eraser" : L"Draw",
  773.            brushSize,
  774.            r, g, b,
  775.            showGrid ? L"On" : L"Off",
  776.            useAlphaGrid ? L"(Alpha)" : L"",
  777.            gridZoomFactor,
  778.            (gridOpacity * 100) / 255,
  779.            centerX, centerY
  780.        );
  781.        SetWindowText(hStatus, status);
  782.    }
  783. }
  784.  
  785. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  786.    switch (uMsg) {
  787.    case WM_CREATE:
  788.    {
  789.        InitializeMemoryBitmap(hwnd);
  790.        if (hMemoryDC) {
  791.            HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
  792.            RECT testRect = { 100, 100, 200, 200 };
  793.            FillRect(hMemoryDC, &testRect, redBrush);
  794.            DeleteObject(redBrush);
  795.            InvalidateRect(hwnd, NULL, FALSE);
  796.        }
  797.        else {
  798.            MessageBox(hwnd, L"Memory DC failed to initialize", L"Error", MB_OK);
  799.        }
  800.        UpdateStatus(hwnd);  // Initial status update
  801.        return 0;
  802.    }
  803.  
  804.    case WM_KEYDOWN:
  805.    {
  806.        if (wParam == VK_SPACE && !isSpacePressed) {
  807.            isSpacePressed = true;
  808.            GetCursorPos(&lastMousePos);
  809.            ScreenToClient(hwnd, &lastMousePos);
  810.            SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  811.            SetCapture(hwnd);  // Capture mouse when space is pressed
  812.            return 0;
  813.        }
  814.        else if (wParam == 0x50) {  // 'P' key
  815.            isPaintbrushSelected = true;
  816.            isEraserMode = false;
  817.            UpdateStatus(hwnd);
  818.        }
  819.        else if (wParam == 0x45) {  // 'E' key
  820.            isPaintbrushSelected = false;
  821.            isEraserMode = true;
  822.            UpdateStatus(hwnd);
  823.        }
  824.        else if (wParam == 'Q') {  // 'Q' key for color picker
  825.            ShowColorPicker(hwnd);
  826.        }
  827.        else if (wParam == VK_ADD || wParam == VK_OEM_PLUS) {
  828.            brushSize = std::min(50, brushSize + 5);
  829.            UpdateStatus(hwnd);
  830.        }
  831.        else if (wParam == VK_SUBTRACT || wParam == VK_OEM_MINUS) {
  832.            brushSize = std::max(5, brushSize - 5);
  833.            UpdateStatus(hwnd);
  834.        }
  835.        else if (wParam == 0x43) {  // 'C' key
  836.            if (!(GetKeyState(VK_CONTROL) & 0x8000)) {
  837.                ClearDrawing(hwnd);
  838.            }
  839.        }
  840.        else if (wParam == VK_HOME) {
  841.            RECT clientRect;
  842.            GetClientRect(hwnd, &clientRect);
  843.            // Calculate the center position
  844.            scrollX = (virtualWidth - clientRect.right) / 2;
  845.            scrollY = (virtualHeight - clientRect.bottom) / 2;
  846.            InvalidateRect(hwnd, NULL, FALSE);
  847.        }
  848.        else if (wParam == 'G') {  // Toggle grid visibility
  849.            showGrid = !showGrid;
  850.            InvalidateRect(hwnd, NULL, FALSE);
  851.            UpdateStatus(hwnd);
  852.        }
  853.        else if (wParam == 'A') {  // Toggle alpha grid
  854.            useAlphaGrid = !useAlphaGrid;
  855.            InvalidateRect(hwnd, NULL, FALSE);
  856.            UpdateStatus(hwnd);
  857.        }
  858.        else if (wParam == VK_OEM_PLUS && (GetKeyState(VK_CONTROL) & 0x8000)) {  // Ctrl + Plus
  859.            gridZoomFactor *= 1.1f;
  860.            gridInitialized = FALSE;  // Force grid cache rebuild
  861.            InvalidateRect(hwnd, NULL, FALSE);
  862.            UpdateStatus(hwnd);
  863.        }
  864.        else if (wParam == VK_OEM_MINUS && (GetKeyState(VK_CONTROL) & 0x8000)) {  // Ctrl + Minus
  865.            gridZoomFactor *= 0.9f;
  866.            if (gridZoomFactor < 0.1f) gridZoomFactor = 0.1f;
  867.            gridInitialized = FALSE;  // Force grid cache rebuild
  868.            InvalidateRect(hwnd, NULL, FALSE);
  869.            UpdateStatus(hwnd);
  870.        }
  871.        else if (wParam == VK_OEM_6 && useAlphaGrid) {  // ']' key - increase opacity
  872.            gridOpacity = min(255, gridOpacity + 15);
  873.            InvalidateRect(hwnd, NULL, FALSE);
  874.            UpdateStatus(hwnd);
  875.        }
  876.        else if (wParam == VK_OEM_4 && useAlphaGrid) {  // '[' key - decrease opacity
  877.            gridOpacity = max(0, gridOpacity - 15);
  878.            InvalidateRect(hwnd, NULL, FALSE);
  879.            UpdateStatus(hwnd);
  880.        }
  881.        else if (wParam == VK_ESCAPE) {
  882.            PostQuitMessage(0);
  883.            return 0;
  884.        }
  885.        else if (wParam == VK_F1) {
  886.            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! (1308 lines of code) by Entisoft Software (c) Evans Thorpemorton"), TEXT("Information"), MB_OK | MB_ICONINFORMATION);
  887.        }
  888.        return 0;
  889.    }
  890.  
  891.    case WM_KEYUP:
  892.    {
  893.        if (wParam == VK_SPACE) {
  894.            isSpacePressed = false;
  895.            SetCursor(LoadCursor(NULL, IDC_ARROW));
  896.            ReleaseCapture();  // Release mouse capture when space is released
  897.            return 0;
  898.        }
  899.    }
  900.        //break;
  901.  
  902.        // Update WM_LBUTTONDOWN handler:
  903.    case WM_LBUTTONDOWN:
  904.    {
  905.        if (!isSpacePressed) {
  906.            isDrawing = true;
  907.            SetCapture(hwnd);
  908.            int x = LOWORD(lParam);
  909.            int y = HIWORD(lParam);
  910.            int canvasX = x + scrollX;
  911.            int canvasY = y + scrollY;
  912.  
  913.            if (canvasX >= 0 && canvasX <= virtualWidth &&
  914.                canvasY >= 0 && canvasY <= virtualHeight) {
  915.  
  916.                StartStroke(canvasX, canvasY);
  917.                DrawBrush(hMemoryDC, canvasX, canvasY, isEraserMode, false);
  918.                HDC screenDC = GetDC(hwnd);
  919.                DrawBrush(screenDC, x, y, isEraserMode, false);
  920.                ReleaseDC(hwnd, screenDC);
  921.            }
  922.        }
  923.        return 0;
  924.    }
  925.    //break;
  926.  
  927.  
  928.    // Optional: Add this to WM_LBUTTONUP to ensure smooth lines start fresh:
  929.    case WM_LBUTTONUP:
  930.    {
  931.        if (isPanning) {
  932.            isPanning = false;
  933.            ReleaseCapture();
  934.        }
  935.        if (isDrawing) {
  936.            isDrawing = false;
  937.            EndStroke();
  938.            ReleaseCapture();
  939.        }
  940.        return 0;
  941.    }
  942.    //break;
  943.  
  944.    //new code
  945. // Modified WM_MOUSEMOVE handler:
  946. // Modify the WM_MOUSEMOVE handler:
  947.    // Modify the WM_MOUSEMOVE case in WindowProc:
  948.    case WM_MOUSEMOVE:
  949.    {
  950.        int x = LOWORD(lParam);
  951.        int y = HIWORD(lParam);
  952.  
  953.        // Update status bar with current coordinates
  954.        UpdateStatus(hwnd);  // Add this line
  955.  
  956.        if (isSpacePressed) {  // Removed the left click check
  957.            RECT clientRect;
  958.            GetClientRect(hwnd, &clientRect);
  959.  
  960.            int deltaX = x - lastMousePos.x;
  961.            int deltaY = y - lastMousePos.y;
  962.  
  963.            scrollX = std::max(0, std::min<int>(virtualWidth - clientRect.right, scrollX - deltaX));
  964.            scrollY = std::max(0, std::min<int>(virtualHeight - clientRect.bottom, scrollY - deltaY));
  965.  
  966.            lastMousePos.x = x;
  967.            lastMousePos.y = y;
  968.            InvalidateRect(hwnd, NULL, FALSE);
  969.        }
  970.        else if (isDrawing && (wParam & MK_LBUTTON)) {
  971.            int canvasX = x + scrollX;
  972.            int canvasY = y + scrollY;
  973.  
  974.            if (canvasX >= 0 && canvasX <= virtualWidth &&
  975.                canvasY >= 0 && canvasY <= virtualHeight) {
  976.  
  977.                AddToStroke(canvasX, canvasY);
  978.                DrawSmoothStroke(hMemoryDC, strokeBuffer, isEraserMode);
  979.  
  980.                HDC screenDC = GetDC(hwnd);
  981.                std::vector<DrawPoint> screenPoints;
  982.                for (const auto& pt : strokeBuffer) {
  983.                    screenPoints.push_back(DrawPoint(pt.x - scrollX, pt.y - scrollY));
  984.                }
  985.                DrawSmoothStroke(screenDC, screenPoints, isEraserMode);
  986.                ReleaseDC(hwnd, screenDC);
  987.            }
  988.        }
  989.        UpdateStatus(hwnd);
  990.        return 0;
  991.    }
  992.    //break;
  993.  
  994.    /*    case WM_MOUSEMOVE:
  995.            if (isDrawing) {
  996.                HDC hdc = GetDC(hwnd);
  997.                DrawBrush(hdc, LOWORD(lParam), HIWORD(lParam));
  998.                ReleaseDC(hwnd, hdc);
  999.            }
  1000.            else if (isErasing) {
  1001.                HDC hdc = GetDC(hwnd);
  1002.                Erase(hdc, LOWORD(lParam), HIWORD(lParam));
  1003.                ReleaseDC(hwnd, hdc);
  1004.            }
  1005.            else if (isClearing) {
  1006.                HDC hdc = GetDC(hwnd);
  1007.                RECT rect;
  1008.                GetClientRect(hwnd, &rect);
  1009.                ClearDrawing(hdc, rect.right, rect.bottom);
  1010.                ReleaseDC(hwnd, hdc);
  1011.                isClearing = false;
  1012.            }
  1013.            break;
  1014.    */
  1015.    case WM_SIZE:
  1016.    {
  1017.        // Handle status bar
  1018.        HWND hStatus = GetDlgItem(hwnd, 0);
  1019.        if (hStatus) {
  1020.            SendMessage(hStatus, WM_SIZE, 0, 0);
  1021.            UpdateStatus(hwnd);  // Update after resize
  1022.        }
  1023.  
  1024.        // Handle window size changes
  1025.        if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) {
  1026.            InvalidateRect(hwnd, NULL, TRUE);
  1027.        }
  1028.  
  1029.        return 0;
  1030.    }
  1031.  
  1032.    //LASTCLASS::
  1033.    /*if (wParam == SIZE_MINIMIZED) {
  1034.        minimizedDrawnBrushstrokes = storedBrushstrokes;
  1035.        minimizedErasedBrushstrokes = storedEraserstrokes;
  1036.    }
  1037.    else if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) {
  1038.        storedBrushstrokes = minimizedDrawnBrushstrokes;
  1039.        storedEraserstrokes = minimizedErasedBrushstrokes;
  1040.  
  1041.        // Redraw the window
  1042.        InvalidateRect(hwnd, NULL, TRUE);
  1043.    }*/
  1044.    //gonnareplace winner!
  1045.    /*if (wParam == SIZE_MINIMIZED) {
  1046.        minimizedDrawnBrushstrokes = storedBrushstrokes;
  1047.        minimizedErasedBrushstrokes = storedEraserstrokes;
  1048.    }
  1049.    else if (wParam == SIZE_RESTORED) {
  1050.        storedBrushstrokes = minimizedDrawnBrushstrokes;
  1051.        storedEraserstrokes = minimizedErasedBrushstrokes;
  1052.        InvalidateRect(hwnd, NULL, TRUE);
  1053.    }*/
  1054.    //start chatgpt new modified code
  1055.    /*if (wParam == SIZE_MINIMIZED) {
  1056.        // Save the drawn and erased brushstrokes when minimizing
  1057.        minimizedDrawnBrushstrokes = storedBrushstrokes;
  1058.        minimizedErasedBrushstrokes = storedEraserstrokes;
  1059.    }
  1060.    else if (wParam == SIZE_RESTORED) {
  1061.        // Restore the minimized brushstrokes when restoring
  1062.        storedBrushstrokes = minimizedDrawnBrushstrokes;
  1063.        storedEraserstrokes = minimizedErasedBrushstrokes;
  1064.        // Trigger a repaint to redraw the brushstrokes
  1065.        InvalidateRect(hwnd, NULL, TRUE);
  1066.    }*/
  1067.    //end chatgpt new modified code
  1068.  
  1069.    //start working but no erase history code (adding brushstruct for eraser logic) fallbackcode
  1070.    /*if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) {
  1071.        RECT rect;
  1072.        GetClientRect(hwnd, &rect);
  1073.        //ClearDrawing(hdc, rect.right, rect.bottom);
  1074.    }*/
  1075.    //end working but no erase history code fallbackcode
  1076.  
  1077.    //new replaced chatgpt
  1078.    /*if (wParam == SIZE_MAXIMIZED) {
  1079.        RECT rect;
  1080.        GetClientRect(hwnd, &rect);
  1081.        ClearDrawing(hdc, rect.right, rect.bottom);
  1082.    }*/
  1083.    /*else if (wParam == SIZE_RESTORED) {
  1084.         RECT rect;
  1085.         GetClientRect(hwnd, &rect);
  1086.         if (isPaintbrushSelected) {
  1087.             // Redraw the stored doodle contents for the Paintbrush tool
  1088.             for (const auto& point : paintbrushDoodlePoints) {
  1089.                 // Use the stored points to redraw the doodle contents for the Paintbrush tool
  1090.                 // Example: Draw a small circle at each point
  1091.                 Ellipse(hdc, point.x - 2, point.y - 2, point.x + 2, point.y + 2);
  1092.             }
  1093.         }
  1094.     }*/
  1095.     //old code
  1096. //new replaced chatgpt
  1097. /*else if (wParam == SIZE_RESTORED) {
  1098.     RECT rect;
  1099.     GetClientRect(hwnd, &rect);
  1100.         // Handle resizing of contents when the window is restored
  1101.         // Add code to restore doodle contents here
  1102.     }
  1103.     else if (wParam == SIZE_MINIMIZED) {
  1104.         // Handle content when the window is minimized
  1105.     }*/
  1106.     //}
  1107.     //break;
  1108.  
  1109.     // Modified WM_PAINT handler:
  1110.    // Modify WM_PAINT to handle the centered view
  1111.    case WM_PAINT:
  1112.    {
  1113.        PAINTSTRUCT ps;
  1114.        HDC hdc = BeginPaint(hwnd, &ps);
  1115.        RECT clientRect;
  1116.        GetClientRect(hwnd, &clientRect);
  1117.        int windowWidth = clientRect.right - clientRect.left;
  1118.        int windowHeight = clientRect.bottom - clientRect.top;
  1119.  
  1120.        HDC memDC = CreateCompatibleDC(hdc);
  1121.        HBITMAP memBitmap = CreateCompatibleBitmap(hdc, windowWidth, windowHeight);
  1122.        HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
  1123.  
  1124.        // Fill with white background
  1125.        HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  1126.        FillRect(memDC, &clientRect, whiteBrush);
  1127.        DeleteObject(whiteBrush);
  1128.  
  1129.        // Draw canvas content first
  1130.        BitBlt(memDC, 0, 0, windowWidth, windowHeight,
  1131.            hMemoryDC, scrollX, scrollY, SRCCOPY);
  1132.  
  1133.        // Draw grid on top if enabled
  1134.        if (showGrid) {
  1135.            if (useAlphaGrid) {
  1136.                DrawGridWithAlpha(memDC, clientRect, scrollX, scrollY);
  1137.            }
  1138.            else {
  1139.                DrawGrid(memDC, clientRect, scrollX, scrollY);
  1140.            }
  1141.        }
  1142.  
  1143.        // Final blit to screen
  1144.        BitBlt(hdc, 0, 0, windowWidth, windowHeight,
  1145.            memDC, 0, 0, SRCCOPY);
  1146.  
  1147.        SelectObject(memDC, oldBitmap);
  1148.        DeleteObject(memBitmap);
  1149.        DeleteDC(memDC);
  1150.        EndPaint(hwnd, &ps);
  1151.        return 0;
  1152.    }
  1153.  
  1154.    // added newly to set Normal Pointer & not Busy Pointer
  1155.    case WM_SETCURSOR:
  1156.    {
  1157.        if (LOWORD(lParam) == HTCLIENT) {  // Only in client area
  1158.            if (isSpacePressed) {
  1159.                SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  1160.                return TRUE;
  1161.            }
  1162.            else if (isPaintbrushSelected || isEraserMode) {
  1163.                SetCursor(LoadCursor(NULL, IDC_CROSS));
  1164.                return TRUE;
  1165.            }
  1166.        }
  1167.        return DefWindowProc(hwnd, uMsg, wParam, lParam);  // Use default cursor for non-client area
  1168.    }
  1169.  
  1170.    // In your mouse wheel handler or zoom control
  1171.    case WM_MOUSEWHEEL:
  1172.    {
  1173.        int delta = GET_WHEEL_DELTA_WPARAM(wParam);
  1174.        if (GetKeyState(VK_CONTROL) & 0x8000) {
  1175.            if (delta > 0)
  1176.                gridZoomFactor *= 1.1f;
  1177.            else
  1178.                gridZoomFactor *= 0.9f;
  1179.            InvalidateRect(hwnd, NULL, FALSE);
  1180.        }
  1181.        return 0;
  1182.    }
  1183.  
  1184.    case WM_DESTROY:
  1185.    {
  1186.        if (hGridDC) {
  1187.            DeleteDC(hGridDC);
  1188.            hGridDC = NULL;
  1189.        }
  1190.        if (hGridBitmap) {
  1191.            DeleteObject(hGridBitmap);
  1192.            hGridBitmap = NULL;
  1193.        }
  1194.        if (hMemoryDC) {
  1195.            if (hOldBitmap) {
  1196.                SelectObject(hMemoryDC, hOldBitmap);
  1197.                hOldBitmap = NULL;
  1198.            }
  1199.            DeleteDC(hMemoryDC);
  1200.            hMemoryDC = NULL;
  1201.        }
  1202.        if (hMemoryBitmap) {
  1203.            DeleteObject(hMemoryBitmap);
  1204.            hMemoryBitmap = NULL;
  1205.        }
  1206.        PostQuitMessage(0);
  1207.        return 0;
  1208.    }
  1209.  
  1210.    default:
  1211.        return DefWindowProc(hwnd, uMsg, wParam, lParam);
  1212.    }
  1213.    return 0;
  1214. }
  1215.  
  1216. // Add this before WinMain
  1217. INITCOMMONCONTROLSEX icex;
  1218.  
  1219. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
  1220.    // Initialize Common Controls
  1221.    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1222.    icex.dwICC = ICC_BAR_CLASSES;
  1223.    InitCommonControlsEx(&icex);
  1224.    
  1225.    const wchar_t CLASS_NAME[] = L"DoodleAppClass";
  1226.  
  1227.    WNDCLASS wc = { };
  1228.  
  1229.    wc.lpfnWndProc = WindowProc;
  1230.    wc.hInstance = hInstance;
  1231.    wc.lpszClassName = CLASS_NAME;
  1232.    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));     // Add this line
  1233.  
  1234.    RegisterClass(&wc);
  1235.  
  1236.    hInst = hInstance;
  1237.  
  1238.    // In WinMain, modify CreateWindowEx:
  1239.    HWND hwnd = CreateWindowEx(
  1240.        0,  // No extra styles needed
  1241.        CLASS_NAME,
  1242.        L"Infinite Canvas Doodle App (P=Brush E=Eraser C=Clear +-=BrushSize Space+Drag=Scroll Home=Center Q=Color G=Grid A=Alpha F1=About)",
  1243.        WS_OVERLAPPEDWINDOW | WS_MAXIMIZE,
  1244.        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  1245.        NULL,
  1246.        NULL,
  1247.        hInstance,
  1248.        NULL
  1249.    );
  1250.  
  1251.    // Enable double buffering using SetWindowLong
  1252.    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_COMPOSITED);
  1253.  
  1254.    //hdc = GetDC(hwnd);
  1255.    if (hwnd == NULL) {
  1256.        return 0;
  1257.    }
  1258.  
  1259.    // Add to WinMain after creating main window
  1260.    HWND hStatus = CreateWindowEx(
  1261.        0,
  1262.        STATUSCLASSNAME,
  1263.        NULL,
  1264.        WS_CHILD | WS_VISIBLE,
  1265.        0, 0, 0, 0,
  1266.        hwnd,
  1267.        NULL,
  1268.        hInstance,
  1269.        NULL
  1270.    );
  1271.  
  1272.    // Initial status update
  1273.    UpdateStatus(hwnd);
  1274.  
  1275.    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
  1276.  
  1277.    //start chatgpt new modified code
  1278.    /*MSG msg = {};
  1279.    while (GetMessage(&msg, NULL, 0, 0)) {
  1280.        TranslateMessage(&msg);
  1281.        DispatchMessage(&msg);
  1282.        if (msg.message == WM_SIZE) {
  1283.            if (msg.wParam == SIZE_MINIMIZED) {
  1284.                // Save the drawn and erased brushstrokes when minimizing
  1285.                std::vector<Brushstroke> minimizedDrawnBrushstrokes = storedBrushstrokes;
  1286.                std::vector<Eraserstroke> minimizedErasedBrushstrokes = storedEraserStrokes;
  1287.            }
  1288.            else if (msg.wParam == SIZE_RESTORED) {
  1289.                // Restore the minimized brushstrokes when restoring
  1290.                storedBrushstrokes = minimizedDrawnBrushstrokes;
  1291.                storedEraserStrokes = minimizedErasedBrushstrokes;
  1292.                // Trigger a repaint to redraw the brushstrokes
  1293.                InvalidateRect(hwnd, NULL, TRUE);
  1294.            }
  1295.        }
  1296.    }*/
  1297.    //end chatgpt new modified code
  1298.  
  1299.    //start working but no erase history code (adding brushstruct for eraser logic) fallbackcode
  1300.    MSG msg = {};
  1301.    while (GetMessage(&msg, NULL, 0, 0)) {
  1302.        TranslateMessage(&msg);
  1303.        DispatchMessage(&msg);
  1304.    }
  1305.    //end working but no erase history code fallbackcode
  1306.  
  1307.    return 0;
  1308. }
Add Comment
Please, Sign In to add comment