alien_fx_fiend

Infinite Canvas ZoomFix+StatBarFlicker+AltF4 v5

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