alien_fx_fiend

Infinite Scrolling Canvas OriginateCenter BugFix MajorRelease

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