ReactOS 0.4.17-dev-357-ga8f14ff
canvas.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Providing the canvas window class
5 * COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
6 * Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 */
8
9#include "precomp.h"
10
12
13/* FUNCTIONS ********************************************************/
14
17{
18 const INT diameter = 2 * radius;
19 if (diameter * zoom / DEFAULT_ZOOM <= 2)
20 {
22 return hCursor ? CopyCursor(hCursor) : NULL;
23 }
24
25 const INT crosshair1 = 6, crosshair2 = crosshair1 - 2;
26 const INT width = diameter + 2 * crosshair1, height = diameter + 2 * crosshair1;
27 DWORD hotX = width / 2, hotY = height / 2;
28
29 HDC hdcScreen = ::GetDC(NULL);
30 if (!hdcScreen)
31 return NULL;
32 HDC hdcMem = ::CreateCompatibleDC(hdcScreen);
33 if (!hdcMem)
34 {
35 ::ReleaseDC(NULL, hdcScreen);
36 return NULL;
37 }
38
39 RECT rc = { 0, 0, width, height };
40
41 // Create the AND mask bitmap. This must be monochrome (1bpp):
42 // white bits are transparent, black bits are opaque.
43 HBITMAP hbmMask = ::CreateBitmap(width, height, 1, 1, NULL);
44 if (hbmMask)
45 {
46 HBITMAP hbmOld = (HBITMAP)::SelectObject(hdcMem, hbmMask);
47
48 // Fill with white brush
50
51 if (!is_rubber)
52 {
53 // Draw crosshair with white pen
55 ::MoveToEx(hdcMem, 0, hotY, NULL);
56 ::LineTo(hdcMem, crosshair2, hotY);
57 ::MoveToEx(hdcMem, width - crosshair2, hotY, NULL);
58 ::LineTo(hdcMem, width, hotY);
59 ::MoveToEx(hdcMem, hotX, 0, NULL);
60 ::LineTo(hdcMem, hotX, crosshair2);
61 ::MoveToEx(hdcMem, hotX, height - crosshair2, NULL);
62 ::LineTo(hdcMem, hotX, height);
63 }
64
65 // Draw brush or erase with black color
66 if (is_rubber)
67 Erase(hdcMem, hotX, hotY, hotX, hotY, RGB(0, 0, 0), radius + 1);
68 else
69 Brush(hdcMem, hotX, hotY, hotX, hotY, RGB(0, 0, 0), style, diameter);
70
71 if (is_rubber)
72 InflateRect(&rc, -1, -1);
73
74 ::SelectObject(hdcMem, hbmOld);
75 }
76
77 // Create the color (XOR) bitmap
78 HBITMAP hbmColor = ::CreateCompatibleBitmap(hdcScreen, width, height);
79 if (hbmColor)
80 {
81 HBITMAP hbmOld = (HBITMAP)::SelectObject(hdcMem, hbmColor);
82
83 // Fill with black brush
85
86 if (is_rubber)
87 {
88 // Draw for rubber border
89 INT avg = (GetRValue(color) + GetGValue(color) + GetBValue(color)) / 3;
90 COLORREF color2 = (avg > 255 / 2) ? RGB(0, 0, 0) : RGB(255, 255, 255);
91 Erase(hdcMem, hotX, hotY, hotX, hotY, color2, radius + 1);
92 }
93 else
94 {
95 // Draw crosshair with white pen
97 ::MoveToEx(hdcMem, 0, hotY, NULL);
98 ::LineTo(hdcMem, crosshair2, hotY);
99 ::MoveToEx(hdcMem, width - crosshair2, hotY, NULL);
100 ::LineTo(hdcMem, width, hotY);
101 ::MoveToEx(hdcMem, hotX, 0, NULL);
102 ::LineTo(hdcMem, hotX, crosshair2);
103 ::MoveToEx(hdcMem, hotX, height - crosshair2, NULL);
104 ::LineTo(hdcMem, hotX, height);
105 }
106
107 // Draw brush or erase with color
108 if (is_rubber)
109 Erase(hdcMem, hotX, hotY, hotX, hotY, color, radius);
110 else
111 Brush(hdcMem, hotX, hotY, hotX, hotY, color, style, diameter);
112
113 ::SelectObject(hdcMem, hbmOld);
114 }
115
116 ::ReleaseDC(NULL, hdcScreen);
118
119 if (zoom != DEFAULT_ZOOM)
120 {
121 INT newWidth = width * zoom / DEFAULT_ZOOM;
122 INT newHeight = height * zoom / DEFAULT_ZOOM;
123 HBITMAP hbmMaskNew = CopyMonoImage(hbmMask, newWidth, newHeight, STRETCH_DELETESCANS);
124 HBITMAP hbmColorNew = CopyDIBImage(hbmColor, newWidth, newHeight, STRETCH_DELETESCANS);
125 ::DeleteObject(hbmMask);
126 ::DeleteObject(hbmColor);
127 hbmMask = hbmMaskNew;
128 hbmColor = hbmColorNew;
129 hotX = width * zoom / (2 * DEFAULT_ZOOM);
130 hotY = height * zoom / (2 * DEFAULT_ZOOM);
131 }
132
133 ICONINFO ii = { FALSE, hotX, hotY, hbmMask, hbmColor };
134 HCURSOR hCursor = (HCURSOR)::CreateIconIndirect(&ii);
135
136 ::DeleteObject(hbmMask);
137 ::DeleteObject(hbmColor);
138
139 return hCursor;
140}
141
143{
144 if (m_hCursor &&
145 m_style == style &&
146 m_zoom == zoom &&
147 m_radius == radius &&
148 m_color == color &&
149 m_is_rubber == is_rubber)
150 {
151 return;
152 }
153
154 if (m_hCursor)
156
157 m_hCursor = CreateStyledCursor(style, zoom, radius, color, is_rubber);
158 m_style = style;
159 m_zoom = zoom;
160 m_radius = radius;
161 m_color = color;
162 m_is_rubber = is_rubber;
163}
164
165CCanvasWindow::CCanvasWindow()
166 : m_drawing(FALSE)
167 , m_hitCanvasSizeBox(HIT_NONE)
168 , m_ptOrig { -1, -1 }
169{
170 m_rcResizing.SetRectEmpty();
171}
172
174{
175}
176
178{
179 CRect rcBase;
180 GetImageRect(rcBase);
181 ImageToCanvas(rcBase);
183 return rcBase;
184}
185
187{
188 Zoomed(pt);
191}
192
194{
195 Zoomed(rc);
197}
198
200{
203 UnZoomed(pt);
204}
205
207{
209 UnZoomed(rc);
210}
211
213{
214 rc = { 0, 0, imageModel.GetWidth(), imageModel.GetHeight() };
215}
216
218{
220 return HIT_INNER;
221 RECT rcBase = GetBaseRect();
222 return getSizeBoxHitTest(pt, &rcBase);
223}
224
226{
227 CRect rcImage;
228 GetImageRect(rcImage);
229 ImageToCanvas(rcImage);
230
231 // Calculate the zoom rectangle
232 INT oldZoom = toolsModel.GetZoom();
233 GetClientRect(rcView);
234 LONG cxView = rcView.right * oldZoom / newZoom, cyView = rcView.bottom * oldZoom / newZoom;
235 rcView.SetRect(ptTarget.x - cxView / 2, ptTarget.y - cyView / 2,
236 ptTarget.x + cxView / 2, ptTarget.y + cyView / 2);
237
238 // Shift the rectangle if necessary
239 INT dx = 0, dy = 0;
240 if (rcView.left < rcImage.left)
241 dx = rcImage.left - rcView.left;
242 else if (rcImage.right < rcView.right)
243 dx = rcImage.right - rcView.right;
244 if (rcView.top < rcImage.top)
245 dy = rcImage.top - rcView.top;
246 else if (rcImage.bottom < rcView.bottom)
247 dy = rcImage.bottom - rcView.bottom;
248 rcView.OffsetRect(dx, dy);
249
250 rcView.IntersectRect(&rcView, &rcImage);
251}
252
254{
255 POINT pt = { left, top };
257
258 toolsModel.SetZoom(newZoom);
260 pt.x += GetScrollPos(SB_HORZ);
261 pt.y += GetScrollPos(SB_VERT);
262
264 updateScrollPos(pt.x, pt.y);
265 Invalidate(TRUE);
266}
267
269{
270 // This is the target area we have to draw on
271 CRect rcCanvasDraw;
272 rcCanvasDraw.IntersectRect(&rcClient, &rcPaint);
273
274 // Calculate image size
275 CRect rcImage;
276 GetImageRect(rcImage);
277 SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
278
279 // We use a memory bitmap to reduce flickering
280 HBITMAP hbmCache1 = CreateDIBWithProperties(rcClient.right, rcClient.bottom);
281 if (!hbmCache1)
282 return FALSE; // Out of memory
283 HBITMAP hbmCache2 = CreateDIBWithProperties(sizeImage.cx, sizeImage.cy);
284 if (!hbmCache2)
285 {
286 ::DeleteObject(hbmCache1);
287 return FALSE; // Out of memory
288 }
289
290 HDC hdcMem0 = ::CreateCompatibleDC(hDC);
291 HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, hbmCache1);
292
293 // Fill the background on hdcMem0
294 ::FillRect(hdcMem0, &rcCanvasDraw, (HBRUSH)(COLOR_APPWORKSPACE + 1));
295
296 // Draw the sizeboxes if necessary
297 RECT rcBase = GetBaseRect();
299 drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcCanvasDraw);
300
301 // Calculate the target area on the image
302 CRect rcImageDraw = rcCanvasDraw;
303 CanvasToImage(rcImageDraw);
304 rcImageDraw.IntersectRect(&rcImageDraw, &rcImage);
305
306 // Consider rounding down by zooming
307 rcImageDraw.right += 1;
308 rcImageDraw.bottom += 1;
309
310 // hdcMem1 <-- imageModel
311 HDC hdcMem1 = ::CreateCompatibleDC(hDC);
312 HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, hbmCache2);
313 ::BitBlt(hdcMem1, rcImageDraw.left, rcImageDraw.top, rcImageDraw.Width(), rcImageDraw.Height(),
314 imageModel.GetDC(), rcImageDraw.left, rcImageDraw.top, SRCCOPY);
315
316 // Draw overlay #1 on hdcMem1
318
319 // Transfer the bits with stretch (hdcMem0 <-- hdcMem1)
320 ImageToCanvas(rcImage);
321 ::StretchBlt(hdcMem0, rcImage.left, rcImage.top, rcImage.Width(), rcImage.Height(),
322 hdcMem1, 0, 0, sizeImage.cx, sizeImage.cy, SRCCOPY);
323
324 // Clean up hdcMem1
325 ::SelectObject(hdcMem1, hbm1Old);
326 ::DeleteDC(hdcMem1);
327
328 // Draw the grid on hdcMem0
329 if (g_showGrid && toolsModel.GetZoom() >= 4000)
330 {
331 HPEN oldPen = (HPEN) ::SelectObject(hdcMem0, ::CreatePen(PS_SOLID, 1, RGB(160, 160, 160)));
332 for (INT counter = 0; counter < sizeImage.cy; counter++)
333 {
334 POINT pt0 = { 0, counter }, pt1 = { sizeImage.cx, counter };
335 ImageToCanvas(pt0);
336 ImageToCanvas(pt1);
337 ::MoveToEx(hdcMem0, pt0.x, pt0.y, NULL);
338 ::LineTo(hdcMem0, pt1.x, pt1.y);
339 }
340 for (INT counter = 0; counter < sizeImage.cx; counter++)
341 {
342 POINT pt0 = { counter, 0 }, pt1 = { counter, sizeImage.cy };
343 ImageToCanvas(pt0);
344 ImageToCanvas(pt1);
345 ::MoveToEx(hdcMem0, pt0.x, pt0.y, NULL);
346 ::LineTo(hdcMem0, pt1.x, pt1.y);
347 }
348 ::DeleteObject(::SelectObject(hdcMem0, oldPen));
349 }
350
351 // Draw overlay #2 on hdcMem0
353
354 // Draw new frame on hdcMem0 if any
356 DrawXorRect(hdcMem0, &m_rcResizing);
357
358 // Transfer the bits (hDC <-- hdcMem0)
359 ::BitBlt(hDC, rcCanvasDraw.left, rcCanvasDraw.top, rcCanvasDraw.Width(), rcCanvasDraw.Height(),
360 hdcMem0, rcCanvasDraw.left, rcCanvasDraw.top, SRCCOPY);
361
362 // Clean up hdcMem0
363 ::SelectObject(hdcMem0, hbm0Old);
364 ::DeleteDC(hdcMem0);
365 ::DeleteObject(hbmCache2);
366 ::DeleteObject(hbmCache1);
367
368 return TRUE;
369}
370
372{
373 CRect rcClient;
374 GetClientRect(&rcClient);
375
376 CSize sizePage(rcClient.right, rcClient.bottom);
377 CSize sizeZoomed = { Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()) };
378 CSize sizeWhole = { sizeZoomed.cx + (GRIP_SIZE * 2), sizeZoomed.cy + (GRIP_SIZE * 2) };
379
380 // show/hide the scrollbars
381 ShowScrollBar(SB_HORZ, sizePage.cx < sizeWhole.cx);
382 ShowScrollBar(SB_VERT, sizePage.cy < sizeWhole.cy);
383
384 if (sizePage.cx < sizeWhole.cx || sizePage.cy < sizeWhole.cy)
385 {
386 GetClientRect(&rcClient); // Scrollbars might change, get client rectangle again
387 sizePage = CSize(rcClient.right, rcClient.bottom);
388 }
389
390 SCROLLINFO si = { sizeof(si), SIF_PAGE | SIF_RANGE };
391 si.nMin = 0;
392
393 si.nMax = sizeWhole.cx;
394 si.nPage = sizePage.cx;
396
397 si.nMax = sizeWhole.cy;
398 si.nPage = sizePage.cy;
400}
401
403{
406}
407
409{
410 if (m_hWnd)
412
413 return 0;
414}
415
417{
419 si.cbSize = sizeof(si);
420 si.fMask = SIF_ALL;
421 GetScrollInfo(fnBar, &si);
422
423 switch (LOWORD(wParam))
424 {
425 case SB_THUMBTRACK:
426 case SB_THUMBPOSITION:
427 si.nPos = (SHORT)HIWORD(wParam);
428 break;
429 case SB_LINELEFT: // SB_LINEUP
430 si.nPos -= 15;
431 break;
432 case SB_LINERIGHT: // SB_LINEDOWN
433 si.nPos += 15;
434 break;
435 case SB_PAGELEFT: // SB_PAGEUP
436 si.nPos -= si.nPage;
437 break;
438 case SB_PAGERIGHT: // SB_PAGEDOWN
439 si.nPos += si.nPage;
440 break;
441 }
442 si.nPos = max(min(si.nPos, si.nMax), si.nMin);
443 SetScrollInfo(fnBar, &si);
444 Invalidate();
445}
446
448{
450 return 0;
451}
452
454{
456 return 0;
457}
458
460{
462
463 m_nMouseDownMsg = nMsg;
464 BOOL bLeftButton = (nMsg == WM_LBUTTONDOWN);
465
466 if (nMsg == WM_MBUTTONDOWN)
467 {
468 m_ptOrig = pt;
469 SetCapture();
471 return 0;
472 }
473
474 HITTEST hitSelection = selectionModel.hitTest(pt);
475 if (hitSelection != HIT_NONE)
476 {
477 m_drawing = TRUE;
479 SetCapture();
480 toolsModel.OnButtonDown(bLeftButton, pt.x, pt.y, FALSE);
481 Invalidate();
482 return 0;
483 }
484
485 HITTEST hit = CanvasHitTest(pt);
486 if (hit == HIT_NONE || hit == HIT_BORDER)
487 {
488 switch (toolsModel.GetActiveTool())
489 {
490 case TOOL_BEZIER:
491 case TOOL_SHAPE:
493 Invalidate();
494 break;
495
496 case TOOL_FREESEL:
497 case TOOL_RECTSEL:
499 Invalidate();
500 break;
501
502 default:
503 break;
504 }
505
506 toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
507 return 0;
508 }
509
511
512 if (hit == HIT_INNER)
513 {
514 m_drawing = TRUE;
515 SetCapture();
516 toolsModel.OnButtonDown(bLeftButton, pt.x, pt.y, FALSE);
517 Invalidate();
518 return 0;
519 }
520
521 if (bLeftButton)
522 {
523 m_hitCanvasSizeBox = hit;
524 m_ptOrig = pt;
525 SetCapture();
526 }
527
528 return 0;
529}
530
532{
535
538 m_nMouseDownMsg = 0;
539
542 Invalidate();
543 return 0;
544}
545
547{
549
551 {
552 INT x = GetScrollPos(SB_HORZ) - (pt.x - m_ptOrig.x);
553 INT y = GetScrollPos(SB_VERT) - (pt.y - m_ptOrig.y);
556 m_ptOrig = pt;
557 return 0;
558 }
559
561
563 Invalidate();
564
566 {
567 TRACKMOUSEEVENT tme = { sizeof(tme) };
568 tme.dwFlags = TME_LEAVE;
569 tme.hwndTrack = m_hWnd;
570 tme.dwHoverTime = 0;
571 ::TrackMouseEvent(&tme);
572
573 if (!m_drawing)
574 {
575 CRect rcImage;
576 GetImageRect(rcImage);
577
578 CStringW strCoord;
579 if (rcImage.PtInRect(pt))
580 strCoord.Format(L"%ld, %ld", pt.x, pt.y);
582 }
583 }
584
586 {
588 return 0;
589 }
590
591 if (m_hitCanvasSizeBox == HIT_NONE || ::GetCapture() != m_hWnd)
592 return 0;
593
594 // Dragging now... Calculate the new size
595 INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
596 INT cxDelta = pt.x - m_ptOrig.x;
597 INT cyDelta = pt.y - m_ptOrig.y;
598 switch (m_hitCanvasSizeBox)
599 {
600 case HIT_UPPER_LEFT:
601 cxImage -= cxDelta;
602 cyImage -= cyDelta;
603 break;
604 case HIT_UPPER_CENTER:
605 cyImage -= cyDelta;
606 break;
607 case HIT_UPPER_RIGHT:
608 cxImage += cxDelta;
609 cyImage -= cyDelta;
610 break;
611 case HIT_MIDDLE_LEFT:
612 cxImage -= cxDelta;
613 break;
614 case HIT_MIDDLE_RIGHT:
615 cxImage += cxDelta;
616 break;
617 case HIT_LOWER_LEFT:
618 cxImage -= cxDelta;
619 cyImage += cyDelta;
620 break;
621 case HIT_LOWER_CENTER:
622 cyImage += cyDelta;
623 break;
624 case HIT_LOWER_RIGHT:
625 cxImage += cxDelta;
626 cyImage += cyDelta;
627 break;
628 default:
629 return 0;
630 }
631
632 // Limit bitmap size
633 cxImage = max(1, cxImage);
634 cyImage = max(1, cyImage);
635 cxImage = min(MAXWORD, cxImage);
636 cyImage = min(MAXWORD, cyImage);
637
638 // Display new size
639 CStringW strSize;
640 strSize.Format(L"%d x %d", cxImage, cyImage);
642
643 // Dragging now... Fix the position...
644 CRect rcResizing = { 0, 0, cxImage, cyImage };
645 switch (m_hitCanvasSizeBox)
646 {
647 case HIT_UPPER_LEFT:
648 rcResizing.OffsetRect(cxDelta, cyDelta);
649 break;
650 case HIT_UPPER_CENTER:
651 rcResizing.OffsetRect(0, cyDelta);
652 break;
653 case HIT_UPPER_RIGHT:
654 rcResizing.OffsetRect(0, cyDelta);
655 break;
656 case HIT_MIDDLE_LEFT:
657 rcResizing.OffsetRect(cxDelta, 0);
658 break;
659 case HIT_LOWER_LEFT:
660 rcResizing.OffsetRect(cxDelta, 0);
661 break;
662 default:
663 break;
664 }
665 ImageToCanvas(rcResizing);
666 m_rcResizing = rcResizing;
667 Invalidate(TRUE);
668
669 return 0;
670}
671
673{
676
678
679 BOOL bLeftButton = (m_nMouseDownMsg == WM_LBUTTONDOWN);
680 m_nMouseDownMsg = 0;
681
682 if (m_drawing)
683 {
685 toolsModel.OnButtonUp(bLeftButton, pt.x, pt.y);
686 Invalidate(FALSE);
688 return 0;
689 }
690
691 if (m_hitCanvasSizeBox == HIT_NONE || !bLeftButton)
692 return 0;
693
694 // Resize the image
695 INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
696 INT cxDelta = pt.x - m_ptOrig.x;
697 INT cyDelta = pt.y - m_ptOrig.y;
698 switch (m_hitCanvasSizeBox)
699 {
700 case HIT_UPPER_LEFT:
701 imageModel.Crop(cxImage - cxDelta, cyImage - cyDelta, cxDelta, cyDelta);
702 break;
703 case HIT_UPPER_CENTER:
704 imageModel.Crop(cxImage, cyImage - cyDelta, 0, cyDelta);
705 break;
706 case HIT_UPPER_RIGHT:
707 imageModel.Crop(cxImage + cxDelta, cyImage - cyDelta, 0, cyDelta);
708 break;
709 case HIT_MIDDLE_LEFT:
710 imageModel.Crop(cxImage - cxDelta, cyImage, cxDelta, 0);
711 break;
712 case HIT_MIDDLE_RIGHT:
713 imageModel.Crop(cxImage + cxDelta, cyImage, 0, 0);
714 break;
715 case HIT_LOWER_LEFT:
716 imageModel.Crop(cxImage - cxDelta, cyImage + cyDelta, cxDelta, 0);
717 break;
718 case HIT_LOWER_CENTER:
719 imageModel.Crop(cxImage, cyImage + cyDelta, 0, 0);
720 break;
721 case HIT_LOWER_RIGHT:
722 imageModel.Crop(cxImage + cxDelta, cyImage + cyDelta, 0, 0);
723 break;
724 default:
725 break;
726 }
728
730
732 toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
734 Invalidate(TRUE);
735 return 0;
736}
737
739{
741 {
742 bHandled = FALSE;
743 return 0;
744 }
745
747 {
749 return 0;
750 }
751
752 POINT pt;
755
756 CRect rcClient;
757 GetClientRect(&rcClient);
758
759 if (!rcClient.PtInRect(pt))
760 {
761 bHandled = FALSE;
762 return 0;
763 }
764
765 HITTEST hitSelection = selectionModel.hitTest(pt);
766 if (hitSelection != HIT_NONE)
767 {
768 if (!setCursorOnSizeBox(hitSelection))
770 return 0;
771 }
772
773 CRect rcImage;
774 GetImageRect(rcImage);
775 ImageToCanvas(rcImage);
776
777 if (rcImage.PtInRect(pt))
778 {
779 switch (toolsModel.GetActiveTool())
780 {
781 case TOOL_FILL:
783 break;
784 case TOOL_COLOR:
786 break;
787 case TOOL_ZOOM:
789 break;
790 case TOOL_PEN:
792 break;
793 case TOOL_AIRBRUSH:
795 break;
796 case TOOL_RUBBER:
797 {
803 break;
804 }
805 case TOOL_BRUSH:
806 {
812 break;
813 }
814 default:
816 }
817 return 0;
818 }
819
821 bHandled = FALSE;
822
823 return 0;
824}
825
827{
828 if (wParam == VK_ESCAPE)
829 {
832 m_nMouseDownMsg = 0;
835 Invalidate(TRUE);
836 }
837
838 return 0;
839}
840
842{
843 // Cancel dragging
846 Invalidate(TRUE);
847 return 0;
848}
849
851{
852 return ::SendMessageW(GetParent(), nMsg, wParam, lParam);
853}
854
856{
858 return 0;
859}
860
862{
863 return TRUE; // do nothing => transparent background
864}
865
867{
868 RECT rcClient;
869 GetClientRect(&rcClient);
870
871 static BOOL s_bShowedOutOfMemory = FALSE; // Don't show "Out Of Memory" message multiple time
872
873 PAINTSTRUCT ps;
874 HDC hDC = BeginPaint(&ps);
875
876 if (DoDraw(hDC, rcClient, ps.rcPaint))
877 {
878 s_bShowedOutOfMemory = FALSE;
879 }
880 else if (!s_bShowedOutOfMemory)
881 {
883 s_bShowedOutOfMemory = TRUE;
884 imageModel.ClearHistory(); // Reduce memory usage
885 }
886
887 EndPaint(&ps);
888 return 0;
889}
890
892{
894 toolsModel.OnEndDraw(bCancel);
895 Invalidate(FALSE);
896}
897
899{
903}
904
906{
908 return 0;
909}
static HDC hDC
Definition: 3dtext.c:33
Arabic default style
Definition: afstyles.h:94
#define IDC_ZOOM
Definition: resource.h:16
HWND g_hStatusBar
Definition: main.cpp:23
BOOL g_imageSaved
Definition: main.cpp:21
BOOL g_showGrid
Definition: main.cpp:22
void ShowOutOfMemory(void)
Definition: main.cpp:34
HINSTANCE g_hinstExe
Definition: main.cpp:17
#define DEFAULT_ZOOM
Definition: precomp.h:46
ToolsModel toolsModel
Definition: toolsmodel.cpp:10
#define GRIP_SIZE
Definition: precomp.h:43
SelectionModel selectionModel
HITTEST
Definition: precomp.h:57
@ HIT_NONE
Definition: precomp.h:58
@ HIT_BORDER
Definition: precomp.h:67
@ HIT_LOWER_RIGHT
Definition: precomp.h:66
@ HIT_LOWER_CENTER
Definition: precomp.h:65
@ HIT_UPPER_LEFT
Definition: precomp.h:59
@ HIT_INNER
Definition: precomp.h:68
@ HIT_LOWER_LEFT
Definition: precomp.h:64
@ HIT_UPPER_CENTER
Definition: precomp.h:60
@ HIT_UPPER_RIGHT
Definition: precomp.h:61
@ HIT_MIDDLE_RIGHT
Definition: precomp.h:63
@ HIT_MIDDLE_LEFT
Definition: precomp.h:62
CTextEditWindow textEditWindow
Definition: textedit.cpp:12
#define IDC_FILL
Definition: resource.h:20
#define IDC_PEN
Definition: resource.h:23
#define IDC_COLOR
Definition: resource.h:21
#define IDC_AIRBRUSH
Definition: resource.h:24
#define IDC_HANDDRAG
Definition: resource.h:25
CCanvasWindow canvasWindow
Definition: canvas.cpp:11
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:818
VOID OnHVScroll(WPARAM wParam, INT fnBar)
Definition: canvas.cpp:416
BOOL m_drawing
Definition: canvas.h:76
VOID OnEndDraw(BOOL bCancel)
Definition: canvas.cpp:891
LRESULT OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:861
LRESULT OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:826
CStyledCursor m_hRubberCursor
Definition: canvas.h:93
CStyledCursor m_hBrushCursor
Definition: canvas.h:92
LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:855
LRESULT OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:453
LRESULT OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:738
HITTEST m_hitCanvasSizeBox
Definition: canvas.h:91
LRESULT OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:905
VOID ImageToCanvas(POINT &pt)
Definition: canvas.cpp:186
LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:408
LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:866
LRESULT OnCancelMode(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:841
VOID CanvasToImage(POINT &pt)
Definition: canvas.cpp:199
VOID updateScrollPos(INT x=0, INT y=0)
Definition: canvas.cpp:402
CRect m_rcResizing
Definition: canvas.h:95
UINT m_nMouseDownMsg
Definition: canvas.h:116
virtual ~CCanvasWindow()
Definition: canvas.cpp:173
HITTEST CanvasHitTest(POINT pt)
Definition: canvas.cpp:217
LRESULT OnButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:672
LRESULT OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:447
LRESULT OnButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:531
BOOL DoDraw(HDC hDC, RECT &rcClient, RECT &rcPaint)
Definition: canvas.cpp:268
VOID GetImageRect(RECT &rc)
Definition: canvas.cpp:212
POINT m_ptOrig
Definition: canvas.h:94
VOID updateScrollRange()
Definition: canvas.cpp:371
LRESULT OnButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:459
LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:546
VOID getNewZoomRect(CRect &rcView, INT newZoom, CPoint ptTarget)
Definition: canvas.cpp:225
RECT GetBaseRect()
Definition: canvas.cpp:177
LRESULT OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:898
VOID zoomTo(INT newZoom, LONG left=0, LONG top=0)
Definition: canvas.cpp:253
LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: canvas.cpp:850
void SetRectEmpty() noexcept
Definition: atltypes.h:431
BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2) noexcept
Definition: atltypes.h:346
void InflateRect(int x, int y) noexcept
Definition: atltypes.h:323
void OffsetRect(int x, int y) noexcept
Definition: atltypes.h:403
BOOL PtInRect(POINT point) const noexcept
Definition: atltypes.h:418
void SetRect(int x1, int y1, int x2, int y2) noexcept
Definition: atltypes.h:423
int Width() const noexcept
Definition: atltypes.h:461
int Height() const noexcept
Definition: atltypes.h:318
BOOL IsRectEmpty() const noexcept
Definition: atltypes.h:351
COLORREF m_color
Definition: canvas.h:37
HCURSOR m_hCursor
Definition: canvas.h:33
void SetCursor()
Definition: canvas.h:24
BOOL m_is_rubber
Definition: canvas.h:38
BrushStyle m_style
Definition: canvas.h:34
void SetStyle(BrushStyle style, INT zoom, INT radius, COLORREF color, BOOL is_rubber)
Definition: canvas.cpp:142
static HCURSOR CreateStyledCursor(BrushStyle style, INT zoom, INT radius, COLORREF color, BOOL is_rubber)
Definition: canvas.cpp:16
INT m_zoom
Definition: canvas.h:35
INT m_radius
Definition: canvas.h:36
static BOOL IsWaiting()
Definition: CWaitCursor.h:40
int GetWidth() const
Definition: history.cpp:254
void NotifyImageChanged()
Definition: history.cpp:23
void Crop(int nWidth, int nHeight, int nOffsetX=0, int nOffsetY=0)
Definition: history.cpp:191
int GetHeight() const
Definition: history.cpp:259
HDC GetDC()
Definition: history.cpp:272
void ClearHistory(void)
Definition: history.cpp:114
COLORREF GetBgColor() const
COLORREF GetFgColor() const
HITTEST hitTest(POINT ptCanvas)
void OnDrawOverlayOnCanvas(HDC hdc)
Definition: mouse.cpp:1195
void OnDrawOverlayOnImage(HDC hdc)
Definition: mouse.cpp:1190
void OnEndDraw(BOOL bCancel)
Definition: mouse.cpp:1182
int GetZoom() const
Definition: toolsmodel.cpp:270
BOOL IsSelection() const
Definition: toolsmodel.cpp:41
void resetTool()
Definition: toolsmodel.cpp:312
void DrawWithMouseTool(POINT pt, WPARAM wParam)
Definition: mouse.cpp:1205
BrushStyle GetBrushStyle() const
Definition: toolsmodel.cpp:130
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
Definition: mouse.cpp:1156
void SetZoom(int nZoom)
Definition: toolsmodel.cpp:275
int GetRubberRadius() const
Definition: toolsmodel.cpp:202
TOOLTYPE GetActiveTool() const
Definition: toolsmodel.cpp:142
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
Definition: mouse.cpp:1173
INT GetBrushWidth() const
Definition: toolsmodel.cpp:70
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
HBITMAP CreateDIBWithProperties(int width, int height)
Definition: dib.cpp:32
HBITMAP CopyMonoImage(HBITMAP hbm, INT cx, INT cy, INT stretchMode)
Definition: dib.cpp:87
HBITMAP CopyDIBImage(HBITMAP hbm, INT cx, INT cy, INT stretchMode)
Definition: dib.cpp:113
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define pt(x, y)
Definition: drawing.c:79
void DrawXorRect(HDC hdc, const RECT *prc)
Definition: drawing.cpp:362
void Erase(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG radius)
Definition: drawing.cpp:115
static VOID BitBlt(_In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_reads_bytes_(Height *Stride) PUCHAR Buffer, _In_ ULONG BitsPerPixel, _In_ ULONG Stride)
Definition: common.c:42
#define RGB(r, g, b)
Definition: precomp.h:67
#define GetBValue(quad)
Definition: precomp.h:71
#define GetGValue(quad)
Definition: precomp.h:70
#define GetRValue(quad)
Definition: precomp.h:69
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint color
Definition: glext.h:6243
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
ImageModel imageModel
Definition: history.cpp:11
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
static SYSTEM_INFO si
Definition: virtual.c:39
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define MAXWORD
PaletteModel paletteModel
#define LOWORD(l)
Definition: pedump.c:82
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
#define TME_LEAVE
Definition: commctrl.h:4998
#define SB_SETTEXT
Definition: commctrl.h:1954
BOOL setCursorOnSizeBox(HITTEST hit)
Definition: sizebox.cpp:20
VOID drawSizeBoxes(HDC hdc, LPCRECT prcBase, BOOL bDrawFrame, LPCRECT prcPaint)
Definition: sizebox.cpp:103
HITTEST getSizeBoxHitTest(POINT pt, LPCRECT prcBase)
Definition: sizebox.cpp:80
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
LONG cx
Definition: windef.h:134
LONG cy
Definition: windef.h:135
#define max(a, b)
Definition: svc.c:63
static int UnZoomed(int xy)
Definition: toolsmodel.h:156
@ TOOL_AIRBRUSH
Definition: toolsmodel.h:20
@ TOOL_COLOR
Definition: toolsmodel.h:16
@ TOOL_SHAPE
Definition: toolsmodel.h:25
@ TOOL_RUBBER
Definition: toolsmodel.h:14
@ TOOL_BRUSH
Definition: toolsmodel.h:19
@ TOOL_BEZIER
Definition: toolsmodel.h:23
@ TOOL_FILL
Definition: toolsmodel.h:15
@ TOOL_PEN
Definition: toolsmodel.h:18
@ TOOL_FREESEL
Definition: toolsmodel.h:12
@ TOOL_ZOOM
Definition: toolsmodel.h:17
@ TOOL_RECTSEL
Definition: toolsmodel.h:13
static int Zoomed(int xy)
Definition: toolsmodel.h:151
BrushStyle
Definition: toolsmodel.h:32
@ BrushStyleSquare
Definition: toolsmodel.h:34
const uint16_t * LPCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58
#define HIWORD(l)
Definition: typedefs.h:247
HDC hdcMem
Definition: welcome.c:104
DWORD COLORREF
Definition: windef.h:100
HICON HCURSOR
Definition: windef.h:99
#define GET_Y_LPARAM(lp)
Definition: windowsx.h:300
#define GET_X_LPARAM(lp)
Definition: windowsx.h:299
HGDIOBJ WINAPI GetStockObject(_In_ int)
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
BOOL WINAPI MoveToEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define TRANSPARENT
Definition: wingdi.h:950
BOOL WINAPI StretchBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
#define WHITE_PEN
Definition: wingdi.h:905
#define SRCCOPY
Definition: wingdi.h:333
#define WHITE_BRUSH
Definition: wingdi.h:902
#define NULL_BRUSH
Definition: wingdi.h:901
#define BLACK_BRUSH
Definition: wingdi.h:896
HBITMAP WINAPI CreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:917
BOOL WINAPI DeleteDC(_In_ HDC)
HPEN WINAPI CreatePen(_In_ int, _In_ int, _In_ COLORREF)
BOOL WINAPI LineTo(_In_ HDC, _In_ int, _In_ int)
#define PS_SOLID
Definition: wingdi.h:586
#define STRETCH_DELETESCANS
Definition: wingdi.h:958
HWND WINAPI SetCapture(_In_ HWND hWnd)
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define MAKEWPARAM(l, h)
Definition: winuser.h:4117
#define SB_THUMBTRACK
Definition: winuser.h:573
HICON WINAPI CreateIconIndirect(_In_ PICONINFO)
Definition: cursoricon.c:2975
#define WM_HSCROLL
Definition: winuser.h:1771
BOOL WINAPI DestroyCursor(_In_ HCURSOR)
Definition: cursoricon.c:3083
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2890
#define WM_VSCROLL
Definition: winuser.h:1772
#define SIF_RANGE
Definition: winuser.h:1246
#define SB_PAGERIGHT
Definition: winuser.h:571
#define SB_VERT
Definition: winuser.h:553
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1806
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:3064
HCURSOR WINAPI SetCursor(_In_opt_ HCURSOR)
#define SIF_PAGE
Definition: winuser.h:1244
HWND WINAPI GetCapture(void)
Definition: message.c:2881
#define IDC_SIZEALL
Definition: winuser.h:704
BOOL WINAPI TrackMouseEvent(_Inout_ LPTRACKMOUSEEVENT)
#define CopyCursor(c)
Definition: winuser.h:4389
#define SB_LINERIGHT
Definition: winuser.h:567
#define WM_LBUTTONDOWN
Definition: winuser.h:1804
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2474
int WINAPI SetScrollPos(_In_ HWND, _In_ int, _In_ int, _In_ BOOL)
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define IDC_CROSS
Definition: winuser.h:698
#define SB_LINELEFT
Definition: winuser.h:566
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define COLOR_APPWORKSPACE
Definition: winuser.h:936
#define SIF_ALL
Definition: winuser.h:1243
#define SendMessage
Definition: winuser.h:6009
#define LoadCursor
Definition: winuser.h:5978
HDC WINAPI GetDC(_In_opt_ HWND)
HWND WINAPI GetParent(_In_ HWND)
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
int WINAPI SetScrollInfo(_In_ HWND, _In_ int, _In_ LPCSCROLLINFO, _In_ BOOL)
BOOL WINAPI ShowScrollBar(_In_ HWND, _In_ int, _In_ BOOL)
int WINAPI GetScrollPos(_In_ HWND, _In_ int)
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
BOOL WINAPI GetScrollInfo(_In_ HWND, _In_ int, _Inout_ LPSCROLLINFO)
#define VK_ESCAPE
Definition: winuser.h:2250
BOOL WINAPI IsWindowVisible(_In_ HWND)
#define WM_MBUTTONDOWN
Definition: winuser.h:1810
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define SB_HORZ
Definition: winuser.h:552
#define SB_PAGELEFT
Definition: winuser.h:570
#define SB_THUMBPOSITION
Definition: winuser.h:572
BOOL WINAPI ScreenToClient(_In_ HWND, _Inout_ LPPOINT)