Advertisement
alien_fx_fiend

Memory DC PaintCanvas Projectv2

Jul 12th, 2024
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.35 KB | None | 0 0
  1. #include <vector>
  2. #include <windows.h>
  3. using namespace std;
  4. struct Brushstroke;
  5. struct Eraserstroke;
  6. void DrawBrush(HDC hdc, int x, int y);
  7. void Erase(HDC hdc, int x, int y);
  8. void ClearDrawing(HDC hdc, int width, int height);
  9. void DrawSmoothBrush(HDC hdc, int x, int y);
  10. bool isPaintbrushSelected = true;
  11. POINT previousPoint;
  12. HDC hdc, memDC;
  13. HBITMAP memBitmap;
  14. HWND hWnd;
  15. struct Brushstroke {
  16.     int x;
  17.     int y;
  18.     int size;
  19.     COLORREF color;
  20. };
  21. struct Eraserstroke {
  22.     int x;
  23.     int y;
  24.     int size;
  25.     COLORREF color;
  26. };
  27. std::vector<Brushstroke> storedBrushstrokes;
  28. std::vector<Eraserstroke> storedEraserstrokes;
  29. void RedrawStrokes() {
  30.     for (const auto& brushstroke : storedBrushstrokes) {
  31.         HGDIOBJ originalBrush = SelectObject(memDC, CreateSolidBrush(brushstroke.color));
  32.         HGDIOBJ originalPen = SelectObject(memDC, GetStockObject(NULL_PEN));
  33.         Ellipse(memDC, brushstroke.x - brushstroke.size, brushstroke.y - brushstroke.size,
  34.             brushstroke.x + brushstroke.size, brushstroke.y + brushstroke.size);
  35.         DeleteObject(SelectObject(memDC, originalBrush));
  36.         DeleteObject(SelectObject(memDC, originalPen));
  37.     }
  38.     for (const auto& erasepoint : storedEraserstrokes) {
  39.         HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  40.         SelectObject(memDC, GetStockObject(NULL_PEN));
  41.         SelectObject(memDC, hBrush);
  42.         Ellipse(memDC, erasepoint.x - erasepoint.size, erasepoint.y - erasepoint.size,
  43.             erasepoint.x + erasepoint.size, erasepoint.y + erasepoint.size);
  44.         DeleteObject(hBrush);
  45.     }
  46. }
  47. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  48. HINSTANCE hInst;
  49. bool isDrawing = false;
  50. bool isErasing = false;
  51. bool isClearing = false;
  52. bool isEraserSelected = false;
  53. int brushSize = 10;
  54. void DrawBrush(HDC hdc, int x, int y) {
  55.     HGDIOBJ originalBrush = SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
  56.     HGDIOBJ originalPen = SelectObject(hdc, GetStockObject(NULL_PEN));
  57.     Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  58.     DeleteObject(SelectObject(hdc, originalBrush));
  59.     DeleteObject(SelectObject(hdc, originalPen));
  60. }
  61. void Erase(HDC hdc, int x, int y) {
  62.     HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  63.     SelectObject(hdc, GetStockObject(NULL_PEN));
  64.     SelectObject(hdc, hBrush);
  65.     Ellipse(hdc, x - brushSize, y - brushSize, x + brushSize, y + brushSize);
  66.     DeleteObject(hBrush);
  67. }
  68. void ClearDrawing(HDC hdc, int width, int height) {
  69.     RECT rect = { 0, 0, width, height };
  70.     HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  71.     FillRect(hdc, &rect, hBrush);
  72.     DeleteObject(hBrush);
  73.     storedBrushstrokes.clear();
  74.     storedEraserstrokes.clear();
  75. }
  76. void DrawSmoothBrush(HDC hdc, int x, int y) {
  77.     if (isDrawing && (isPaintbrushSelected || isEraserSelected)) {
  78.         int numPoints = 3;
  79.         POINT currentPoint = { x, y };
  80.         for (int i = 1; i <= numPoints; i++) {
  81.             float t = (float)i / (float)numPoints;
  82.             int smoothX = (int)(previousPoint.x + t * (currentPoint.x - previousPoint.x));
  83.             int smoothY = (int)(previousPoint.y + t * (currentPoint.y - previousPoint.y));
  84.             if (isPaintbrushSelected) {
  85.                 DrawBrush(hdc, smoothX, smoothY);
  86.                 Brushstroke newBrushstroke;
  87.                 newBrushstroke.x = smoothX;
  88.                 newBrushstroke.y = smoothY;
  89.                 newBrushstroke.size = brushSize;
  90.                 newBrushstroke.color = RGB(255, 0, 0);
  91.                 storedBrushstrokes.push_back(newBrushstroke);
  92.             }
  93.             else if (isEraserSelected) {
  94.                 Erase(hdc, smoothX, smoothY);
  95.                 Eraserstroke newEraserstroke;
  96.                 newEraserstroke.x = smoothX;
  97.                 newEraserstroke.y = smoothY;
  98.                 newEraserstroke.size = brushSize;
  99.                 newEraserstroke.color = RGB(255, 255, 255);
  100.                 storedEraserstrokes.push_back(newEraserstroke);
  101.             }
  102.         }
  103.         previousPoint = currentPoint;
  104.     }
  105. }
  106. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  107.     switch (uMsg) {
  108.     case WM_CREATE:
  109.     {
  110.         RECT rect;
  111.         GetClientRect(hwnd, &rect);
  112.         HDC hdc = GetDC(hwnd);
  113.         memDC = CreateCompatibleDC(hdc);
  114.         memBitmap = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
  115.         SelectObject(memDC, memBitmap);
  116.         ReleaseDC(hwnd, hdc);
  117.         HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  118.         FillRect(memDC, &rect, hBrush);
  119.         DeleteObject(hBrush);
  120.         isPaintbrushSelected = true;
  121.     }
  122.     break;
  123.     case WM_KEYDOWN:
  124.         if (wParam == VK_ADD) {
  125.             brushSize += 5;
  126.         }
  127.         else if (wParam == VK_SUBTRACT) {
  128.             if (brushSize > 5) {
  129.                 brushSize -= 5;
  130.             }
  131.         }
  132.         else if (wParam == 0x43) {
  133.             if (!(GetKeyState(VK_CONTROL) & 0x8000)) {
  134.                 isClearing = true;
  135.             }
  136.         }
  137.         else if (wParam == 0x50) {
  138.             isPaintbrushSelected = true;
  139.             isEraserSelected = false;
  140.         }
  141.         else if (wParam == 0x45) {
  142.             isEraserSelected = true;
  143.             isPaintbrushSelected = false;
  144.         }
  145.         break;
  146.     case WM_LBUTTONDOWN:
  147.         if (isPaintbrushSelected || isEraserSelected) {
  148.             previousPoint.x = LOWORD(lParam);
  149.             previousPoint.y = HIWORD(lParam);
  150.         }
  151.         isDrawing = true;
  152.         break;
  153.     case WM_LBUTTONUP:
  154.         isDrawing = false;
  155.         break;
  156.     case WM_MOUSEMOVE:
  157.         if (isDrawing && isPaintbrushSelected) {
  158.             int x = LOWORD(lParam);
  159.             int y = HIWORD(lParam);
  160.             DrawSmoothBrush(memDC, x, y);
  161.             InvalidateRect(hwnd, NULL, FALSE);
  162.             Brushstroke newBrushstroke;
  163.             newBrushstroke.x = x;
  164.             newBrushstroke.y = y;
  165.             newBrushstroke.size = brushSize;
  166.             newBrushstroke.color = RGB(255, 0, 0);
  167.             storedBrushstrokes.push_back(newBrushstroke);
  168.         }
  169.         else if (isDrawing && isEraserSelected) {
  170.             int x = LOWORD(lParam);
  171.             int y = HIWORD(lParam);
  172.             Erase(memDC, x, y);
  173.             InvalidateRect(hwnd, NULL, FALSE);
  174.             Eraserstroke newEraserStroke;
  175.             newEraserStroke.x = x;
  176.             newEraserStroke.y = y;
  177.             newEraserStroke.size = brushSize;
  178.             newEraserStroke.color = RGB(255, 255, 255);
  179.             storedEraserstrokes.push_back(newEraserStroke);
  180.         }
  181.         else if (isClearing) {
  182.             HDC hdc = GetDC(hwnd);
  183.             RECT rect;
  184.             GetClientRect(hwnd, &rect);
  185.             ClearDrawing(hdc, rect.right, rect.bottom);
  186.             ReleaseDC(hwnd, hdc);
  187.             isClearing = false;
  188.         }
  189.         break;
  190.     case WM_SIZE:
  191.     {
  192.         static bool isMinimized = false;
  193.         if (wParam == SIZE_MINIMIZED)
  194.         {
  195.             isMinimized = true;
  196.         }
  197.         else if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)
  198.         {
  199.             if (isMinimized)
  200.             {
  201.                 isMinimized = false;
  202.             }
  203.             InvalidateRect(hwnd, NULL, TRUE);
  204.         }
  205.         RECT rect;
  206.         GetClientRect(hwnd, &rect);
  207.         if (memDC)
  208.         {
  209.             DeleteDC(memDC);
  210.             DeleteObject(memBitmap);
  211.         }
  212.         HDC hdc = GetDC(hwnd);
  213.         memDC = CreateCompatibleDC(hdc);
  214.         memBitmap = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
  215.         SelectObject(memDC, memBitmap);
  216.         ReleaseDC(hwnd, hdc);
  217.         HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
  218.         FillRect(memDC, &rect, hBrush);
  219.         DeleteObject(hBrush);
  220.         RedrawStrokes();
  221.     }
  222.     break;
  223.     case WM_PAINT:
  224.     {
  225.         PAINTSTRUCT ps;
  226.         HDC hdc = BeginPaint(hwnd, &ps);
  227.         BitBlt(hdc, 0, 0, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, memDC, 0, 0, SRCCOPY);
  228.         EndPaint(hwnd, &ps);
  229.     }
  230.     break;
  231.     case WM_SETCURSOR:
  232.         if (LOWORD(lParam) == HTCLIENT) {
  233.             SetCursor(LoadCursor(NULL, IDC_ARROW));
  234.             return TRUE;
  235.         }
  236.         break;
  237.     case WM_DESTROY:
  238.         DeleteDC(memDC);
  239.         DeleteObject(memBitmap);
  240.         PostQuitMessage(0);
  241.         return 0;
  242.     default:
  243.         return DefWindowProc(hwnd, uMsg, wParam, lParam);
  244.     }
  245.     return 0;
  246. }
  247. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  248.     const wchar_t CLASS_NAME[] = L"DoodleAppClass";
  249.     WNDCLASS wc = { };
  250.     wc.lpfnWndProc = WindowProc;
  251.     wc.hInstance = hInstance;
  252.     wc.lpszClassName = CLASS_NAME;
  253.     RegisterClass(&wc);
  254.     hInst = hInstance;
  255.     HWND hwnd = CreateWindowEx(
  256.         0,
  257.         CLASS_NAME,
  258.         L"Doodle App",
  259.         WS_OVERLAPPEDWINDOW | WS_MAXIMIZE,
  260.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  261.         NULL,
  262.         NULL,
  263.         hInstance,
  264.         NULL
  265.     );
  266.     hdc = GetDC(hwnd);
  267.     if (hwnd == NULL) {
  268.         return 0;
  269.     }
  270.     ShowWindow(hwnd, SW_SHOWMAXIMIZED);
  271.     MSG msg = {};
  272.     while (GetMessage(&msg, NULL, 0, 0)) {
  273.         TranslateMessage(&msg);
  274.         DispatchMessage(&msg);
  275.     }
  276.     return 0;
  277. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement