From e8c7e300300e9bbc76b37b30dff392df12ef5222 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Sat, 17 Jun 2023 21:15:35 +0900 Subject: [PATCH] [MSPAINT] Establish Undo/Redo management (#5347) - Painting the canvas is done by overlaying the multiple layers. - Drawing each overlay is implemented as polymorphism of OOP. - Refine the Undo/Redo mechanism. - Some adjustments. CORE-17969 --- base/applications/mspaint/canvas.cpp | 134 +++--- base/applications/mspaint/canvas.h | 4 +- base/applications/mspaint/common.h | 1 - base/applications/mspaint/dialogs.cpp | 20 +- base/applications/mspaint/dib.cpp | 38 +- base/applications/mspaint/drawing.cpp | 2 +- base/applications/mspaint/fullscreen.cpp | 4 +- base/applications/mspaint/globalvar.h | 22 +- base/applications/mspaint/history.cpp | 135 +++--- base/applications/mspaint/history.h | 17 +- base/applications/mspaint/main.cpp | 28 +- base/applications/mspaint/miniature.cpp | 2 +- base/applications/mspaint/mouse.cpp | 470 ++++++++++++------- base/applications/mspaint/palette.cpp | 8 +- base/applications/mspaint/palette.h | 2 - base/applications/mspaint/palettemodel.cpp | 2 +- base/applications/mspaint/selectionmodel.cpp | 121 ++--- base/applications/mspaint/selectionmodel.h | 12 +- base/applications/mspaint/textedit.cpp | 4 +- base/applications/mspaint/toolbox.cpp | 29 +- base/applications/mspaint/toolbox.h | 5 + base/applications/mspaint/toolsettings.cpp | 11 +- base/applications/mspaint/toolsmodel.cpp | 15 +- base/applications/mspaint/toolsmodel.h | 31 +- base/applications/mspaint/winproc.cpp | 108 +++-- 25 files changed, 721 insertions(+), 504 deletions(-) diff --git a/base/applications/mspaint/canvas.cpp b/base/applications/mspaint/canvas.cpp index c36bd76faed..68a91b5d250 100644 --- a/base/applications/mspaint/canvas.cpp +++ b/base/applications/mspaint/canvas.cpp @@ -17,15 +17,17 @@ CCanvasWindow::CCanvasWindow() , m_hitSelection(HIT_NONE) , m_whereHit(HIT_NONE) , m_ptOrig { -1, -1 } - , m_hbmCached(NULL) { + m_ahbmCached[0] = m_ahbmCached[1] = NULL; ::SetRectEmpty(&m_rcNew); } CCanvasWindow::~CCanvasWindow() { - if (m_hbmCached) - ::DeleteObject(m_hbmCached); + if (m_ahbmCached[0]) + ::DeleteObject(m_ahbmCached[0]); + if (m_ahbmCached[1]) + ::DeleteObject(m_ahbmCached[1]); } VOID CCanvasWindow::drawZoomFrame(INT mouseX, INT mouseY) @@ -101,78 +103,80 @@ CANVAS_HITTEST CCanvasWindow::CanvasHitTest(POINT pt) VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint) { // We use a memory bitmap to reduce flickering - HDC hdcMem = ::CreateCompatibleDC(hDC); - m_hbmCached = CachedBufferDIB(m_hbmCached, rcClient.right, rcClient.bottom); - HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmCached); + HDC hdcMem0 = ::CreateCompatibleDC(hDC); + m_ahbmCached[0] = CachedBufferDIB(m_ahbmCached[0], rcClient.right, rcClient.bottom); + HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, m_ahbmCached[0]); - // Fill the background - ::FillRect(hdcMem, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1)); + // Fill the background on hdcMem0 + ::FillRect(hdcMem0, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1)); // Draw the sizeboxes if necessary RECT rcBase = GetBaseRect(); if (!selectionModel.m_bShow) - drawSizeBoxes(hdcMem, &rcBase, FALSE, &rcPaint); + drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcPaint); - // Draw the image + // Calculate image size CRect rcImage; GetImageRect(rcImage); - ImageToCanvas(rcImage); SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() }; - StretchBlt(hdcMem, rcImage.left, rcImage.top, rcImage.Width(), rcImage.Height(), - imageModel.GetDC(), 0, 0, sizeImage.cx, sizeImage.cy, SRCCOPY); - // Draw the grid - if (showGrid && toolsModel.GetZoom() >= 4000) + // hdcMem1 <-- imageModel + HDC hdcMem1 = ::CreateCompatibleDC(hDC); + m_ahbmCached[1] = CachedBufferDIB(m_ahbmCached[1], sizeImage.cx, sizeImage.cy); + HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, m_ahbmCached[1]); + BitBlt(hdcMem1, 0, 0, sizeImage.cx, sizeImage.cy, imageModel.GetDC(), 0, 0, SRCCOPY); + + // Draw overlay #1 on hdcMem1 + toolsModel.OnDrawOverlayOnImage(hdcMem1); + + // Transfer the bits with stretch (hdcMem0 <-- hdcMem1) + ImageToCanvas(rcImage); + ::StretchBlt(hdcMem0, rcImage.left, rcImage.top, rcImage.Width(), rcImage.Height(), + hdcMem1, 0, 0, sizeImage.cx, sizeImage.cy, SRCCOPY); + + // Clean up hdcMem1 + ::SelectObject(hdcMem1, hbm1Old); + ::DeleteDC(hdcMem1); + + // Draw the grid on hdcMem0 + if (g_showGrid && toolsModel.GetZoom() >= 4000) { - HPEN oldPen = (HPEN) SelectObject(hdcMem, CreatePen(PS_SOLID, 1, RGB(160, 160, 160))); + HPEN oldPen = (HPEN) ::SelectObject(hdcMem0, ::CreatePen(PS_SOLID, 1, RGB(160, 160, 160))); for (INT counter = 0; counter < sizeImage.cy; counter++) { POINT pt0 = { 0, counter }, pt1 = { sizeImage.cx, counter }; ImageToCanvas(pt0); ImageToCanvas(pt1); - ::MoveToEx(hdcMem, pt0.x, pt0.y, NULL); - ::LineTo(hdcMem, pt1.x, pt1.y); + ::MoveToEx(hdcMem0, pt0.x, pt0.y, NULL); + ::LineTo(hdcMem0, pt1.x, pt1.y); } for (INT counter = 0; counter < sizeImage.cx; counter++) { POINT pt0 = { counter, 0 }, pt1 = { counter, sizeImage.cy }; ImageToCanvas(pt0); ImageToCanvas(pt1); - ::MoveToEx(hdcMem, pt0.x, pt0.y, NULL); - ::LineTo(hdcMem, pt1.x, pt1.y); + ::MoveToEx(hdcMem0, pt0.x, pt0.y, NULL); + ::LineTo(hdcMem0, pt1.x, pt1.y); } - ::DeleteObject(::SelectObject(hdcMem, oldPen)); + ::DeleteObject(::SelectObject(hdcMem0, oldPen)); } - // Draw selection - if (selectionModel.m_bShow) - { - RECT rcSelection = selectionModel.m_rc; - ImageToCanvas(rcSelection); + // Draw overlay #2 on hdcMem0 + toolsModel.OnDrawOverlayOnCanvas(hdcMem0); - ::InflateRect(&rcSelection, GRIP_SIZE, GRIP_SIZE); - drawSizeBoxes(hdcMem, &rcSelection, TRUE, &rcPaint); - ::InflateRect(&rcSelection, -GRIP_SIZE, -GRIP_SIZE); - - INT iSaveDC = ::SaveDC(hdcMem); - ::IntersectClipRect(hdcMem, rcImage.left, rcImage.top, rcImage.right, rcImage.bottom); - selectionModel.DrawSelection(hdcMem, &rcSelection, paletteModel.GetBgColor(), - toolsModel.IsBackgroundTransparent()); - ::RestoreDC(hdcMem, iSaveDC); - } - - // Draw new frame if any + // Draw new frame on hdcMem0 if any if (m_whereHit != HIT_NONE && !::IsRectEmpty(&m_rcNew)) - DrawXorRect(hdcMem, &m_rcNew); + DrawXorRect(hdcMem0, &m_rcNew); - // Transfer the bits + // Transfer the bits (hDC <-- hdcMem0) ::BitBlt(hDC, rcPaint.left, rcPaint.top, rcPaint.right - rcPaint.left, rcPaint.bottom - rcPaint.top, - hdcMem, rcPaint.left, rcPaint.top, SRCCOPY); + hdcMem0, rcPaint.left, rcPaint.top, SRCCOPY); - ::SelectObject(hdcMem, hbmOld); - ::DeleteDC(hdcMem); + // Clean up hdcMem0 + ::SelectObject(hdcMem0, hbm0Old); + ::DeleteDC(hdcMem0); } VOID CCanvasWindow::Update(HWND hwndFrom) @@ -383,15 +387,15 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL { CString strCoord; strCoord.Format(_T("%ld, %ld"), pt.x, pt.y); - SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord); + ::SendMessage(g_hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord); } } if (m_drawing) { // values displayed in statusbar - LONG xRel = pt.x - start.x; - LONG yRel = pt.y - start.y; + LONG xRel = pt.x - g_ptStart.x; + LONG yRel = pt.y - g_ptStart.y; switch (toolsModel.GetActiveTool()) { @@ -400,13 +404,13 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL case TOOL_RECTSEL: case TOOL_TEXT: if (xRel < 0) - xRel = (pt.x < 0) ? -start.x : xRel; + xRel = (pt.x < 0) ? -g_ptStart.x : xRel; else if (pt.x > imageModel.GetWidth()) - xRel = imageModel.GetWidth() - start.x; + xRel = imageModel.GetWidth() - g_ptStart.x; if (yRel < 0) - yRel = (pt.y < 0) ? -start.y : yRel; + yRel = (pt.y < 0) ? -g_ptStart.y : yRel; else if (pt.y > imageModel.GetHeight()) - yRel = imageModel.GetHeight() - start.y; + yRel = imageModel.GetHeight() - g_ptStart.y; break; // while drawing, update cursor coordinates only for tools 3, 7, 8, 9, 14 @@ -418,7 +422,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL { CString strCoord; strCoord.Format(_T("%ld, %ld"), pt.x, pt.y); - SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord); + ::SendMessage(g_hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord); break; } default: @@ -444,7 +448,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL if ((toolsModel.GetActiveTool() >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0)) yRel = xRel; strSize.Format(_T("%ld x %ld"), xRel, yRel); - SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize); + ::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize); } } @@ -458,7 +462,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL if ((toolsModel.GetActiveTool() >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0)) yRel = xRel; strSize.Format(_T("%ld x %ld"), xRel, yRel); - SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize); + ::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize); } } return 0; @@ -514,7 +518,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL // Display new size CString strSize; strSize.Format(_T("%d x %d"), cxImage, cyImage); - SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize); + ::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize); CRect rc = { 0, 0, cxImage, cyImage }; switch (m_whereHit) @@ -556,7 +560,7 @@ LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam, m_drawing = FALSE; toolsModel.OnButtonUp(bLeftButton, pt.x, pt.y); Invalidate(FALSE); - SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) ""); + ::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM)_T("")); return 0; } else if (m_hitSelection != HIT_NONE && bLeftButton) @@ -603,7 +607,7 @@ LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam, } ::SetRectEmpty(&m_rcNew); - imageSaved = FALSE; + g_imageSaved = FALSE; m_whereHit = HIT_NONE; toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions @@ -654,19 +658,19 @@ LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL switch (toolsModel.GetActiveTool()) { case TOOL_FILL: - ::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_FILL))); + ::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_FILL))); break; case TOOL_COLOR: - ::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_COLOR))); + ::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_COLOR))); break; case TOOL_ZOOM: - ::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_ZOOM))); + ::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_ZOOM))); break; case TOOL_PEN: - ::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_PEN))); + ::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_PEN))); break; case TOOL_AIRBRUSH: - ::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_AIRBRUSH))); + ::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_AIRBRUSH))); break; default: ::SetCursor(::LoadCursor(NULL, IDC_CROSS)); @@ -710,7 +714,7 @@ LRESULT CCanvasWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO LRESULT CCanvasWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM)_T("")); + ::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM)_T("")); return 0; } @@ -800,3 +804,9 @@ LRESULT CCanvasWindow::OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, B SetBkMode((HDC)wParam, TRANSPARENT); return (LRESULT)GetStockObject(NULL_BRUSH); } + +LRESULT CCanvasWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + imageModel.NotifyImageChanged(); + return 0; +} diff --git a/base/applications/mspaint/canvas.h b/base/applications/mspaint/canvas.h index d76b3761b9c..40c07689acd 100644 --- a/base/applications/mspaint/canvas.h +++ b/base/applications/mspaint/canvas.h @@ -33,6 +33,7 @@ public: MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode) MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) MESSAGE_HANDLER(WM_CTLCOLOREDIT, OnCtlColorEdit) + MESSAGE_HANDLER(WM_PALETTEMODELCOLORCHANGED, OnPaletteModelColorChanged) END_MSG_MAP() CCanvasWindow(); @@ -55,7 +56,7 @@ protected: CANVAS_HITTEST m_hitSelection; CANVAS_HITTEST m_whereHit; POINT m_ptOrig; // The origin of drag start - HBITMAP m_hbmCached; // The cached buffer bitmap + HBITMAP m_ahbmCached[2]; // The cached buffer bitmaps CRect m_rcNew; CANVAS_HITTEST CanvasHitTest(POINT pt); @@ -87,6 +88,7 @@ protected: LRESULT OnCancelMode(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnLRButtonDblClk(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); diff --git a/base/applications/mspaint/common.h b/base/applications/mspaint/common.h index 4aefbb2dcff..0c99517c599 100644 --- a/base/applications/mspaint/common.h +++ b/base/applications/mspaint/common.h @@ -20,7 +20,6 @@ #define WM_TOOLSMODELSETTINGSCHANGED (WM_APP + 1) #define WM_TOOLSMODELZOOMCHANGED (WM_APP + 2) #define WM_PALETTEMODELCOLORCHANGED (WM_APP + 3) -#define WM_PALETTEMODELPALETTECHANGED (WM_APP + 4) /* this simplifies checking and unchecking menu items */ #define CHECKED_IF(a) ((a) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND)) diff --git a/base/applications/mspaint/dialogs.cpp b/base/applications/mspaint/dialogs.cpp index 7b85b59365e..b08e33974c7 100644 --- a/base/applications/mspaint/dialogs.cpp +++ b/base/applications/mspaint/dialogs.cpp @@ -83,16 +83,16 @@ LRESULT CAttributesDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE); SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE); - if (isAFile) + if (g_isAFile) { TCHAR date[100]; TCHAR temp[100]; - GetDateFormat(LOCALE_USER_DEFAULT, 0, &fileTime, NULL, date, _countof(date)); - GetTimeFormat(LOCALE_USER_DEFAULT, 0, &fileTime, NULL, temp, _countof(temp)); + GetDateFormat(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, date, _countof(date)); + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, temp, _countof(temp)); _tcscat(date, _T(" ")); _tcscat(date, temp); CString strSize; - strSize.Format(IDS_FILESIZE, fileSize); + strSize.Format(IDS_FILESIZE, g_fileSize); SetDlgItemText(IDD_ATTRIBUTESTEXT6, date); SetDlgItemText(IDD_ATTRIBUTESTEXT7, strSize); } @@ -240,9 +240,9 @@ LRESULT CStretchSkewDialog::OnOk(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& CString strrcAngle; BOOL tr1, tr2, tr3, tr4; - strrcIntNumbers.LoadString(hProgInstance, IDS_INTNUMBERS); - strrcPercentage.LoadString(hProgInstance, IDS_PERCENTAGE); - strrcAngle.LoadString(hProgInstance, IDS_ANGLE); + strrcIntNumbers.LoadString(g_hinstExe, IDS_INTNUMBERS); + strrcPercentage.LoadString(g_hinstExe, IDS_PERCENTAGE); + strrcAngle.LoadString(g_hinstExe, IDS_ANGLE); percentage.x = GetDlgItemInt(IDD_STRETCHSKEWEDITHSTRETCH, &tr1, FALSE); percentage.y = GetDlgItemInt(IDD_STRETCHSKEWEDITVSTRETCH, &tr2, FALSE); @@ -347,11 +347,11 @@ void CFontsDialog::InitToolbar() SendMessage(hwndToolbar, TB_SETBUTTONWIDTH, 0, MAKELPARAM(20, 20)); TBADDBITMAP AddBitmap; - AddBitmap.hInst = hProgInstance; + AddBitmap.hInst = g_hinstExe; AddBitmap.nID = IDB_FONTSTOOLBAR; SendMessage(hwndToolbar, TB_ADDBITMAP, 4, (LPARAM)&AddBitmap); - HIMAGELIST himl = ImageList_LoadImage(hProgInstance, MAKEINTRESOURCE(IDB_FONTSTOOLBAR), + HIMAGELIST himl = ImageList_LoadImage(g_hinstExe, MAKEINTRESOURCE(IDB_FONTSTOOLBAR), 16, 8, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION); SendMessage(hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl); @@ -511,7 +511,7 @@ LRESULT CFontsDialog::OnNotify(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH if (pnmhdr->code == TTN_NEEDTEXT) { LPTOOLTIPTEXT pToolTip = reinterpret_cast(lParam); - pToolTip->hinst = hProgInstance; + pToolTip->hinst = g_hinstExe; switch (pnmhdr->idFrom) { case IDM_BOLD: pToolTip->lpszText = MAKEINTRESOURCE(IDS_BOLD); break; diff --git a/base/applications/mspaint/dib.cpp b/base/applications/mspaint/dib.cpp index 1e7477c661e..85472994639 100644 --- a/base/applications/mspaint/dib.cpp +++ b/base/applications/mspaint/dib.cpp @@ -9,10 +9,10 @@ #include "precomp.h" #include -INT fileSize = 0; +INT g_fileSize = 0; float g_xDpi = 96; float g_yDpi = 96; -SYSTEMTIME fileTime; +SYSTEMTIME g_fileTime; /* FUNCTIONS ********************************************************/ @@ -114,15 +114,15 @@ BOOL SaveDIBToFile(HBITMAP hBitmap, LPCTSTR FileName, HDC hDC) // update time and size FILETIME ft; FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); - FileTimeToSystemTime(&ft, &fileTime); - fileSize = find.nFileSizeLow; + FileTimeToSystemTime(&ft, &g_fileTime); + g_fileSize = find.nFileSizeLow; // TODO: update hRes and vRes registrySettings.SetMostRecentFile(FileName); - isAFile = TRUE; - imageSaved = TRUE; + g_isAFile = TRUE; + g_imageSaved = TRUE; return TRUE; } @@ -150,33 +150,33 @@ HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL i g_yDpi = GetDeviceCaps(hScreenDC, LOGPIXELSY); ReleaseDC(NULL, hScreenDC); - ZeroMemory(&fileTime, sizeof(fileTime)); + ZeroMemory(&g_fileTime, sizeof(g_fileTime)); } // update image imageModel.PushImageForUndo(hBitmap); imageModel.ClearHistory(); - // update fileSize - fileSize = dwFileSize; + // update g_fileSize + g_fileSize = dwFileSize; - // update filepathname + // update g_szFileName if (name && name[0]) - GetFullPathName(name, _countof(filepathname), filepathname, NULL); + GetFullPathName(name, _countof(g_szFileName), g_szFileName, NULL); else - LoadString(hProgInstance, IDS_DEFAULTFILENAME, filepathname, _countof(filepathname)); + LoadString(g_hinstExe, IDS_DEFAULTFILENAME, g_szFileName, _countof(g_szFileName)); // set title CString strTitle; - strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname)); + strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName)); mainWindow.SetWindowText(strTitle); // update file info and recent - isAFile = isFile; - if (isAFile) - registrySettings.SetMostRecentFile(filepathname); + g_isAFile = isFile; + if (g_isAFile) + registrySettings.SetMostRecentFile(g_szFileName); - imageSaved = TRUE; + g_imageSaved = TRUE; return hBitmap; } @@ -204,7 +204,7 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile) { FILETIME ft; FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); - FileTimeToSystemTime(&ft, &fileTime); + FileTimeToSystemTime(&ft, &g_fileTime); return SetBitmapAndInfo(NULL, name, dwFileSize, TRUE); } } @@ -233,7 +233,7 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile) { FILETIME ft; FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); - FileTimeToSystemTime(&ft, &fileTime); + FileTimeToSystemTime(&ft, &g_fileTime); SetBitmapAndInfo(hBitmap, name, dwFileSize, TRUE); } diff --git a/base/applications/mspaint/drawing.cpp b/base/applications/mspaint/drawing.cpp index 7bb0d57da60..5b3d1a24f62 100644 --- a/base/applications/mspaint/drawing.cpp +++ b/base/applications/mspaint/drawing.cpp @@ -158,7 +158,7 @@ Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r) { for (LONG dx = -r; dx <= r; dx++) { - if ((dx * dx + dy * dy <= r * r) && (rand() % 4 == 0)) + if ((dx * dx + dy * dy <= r * r) && (rand() % r == 0)) ::SetPixelV(hdc, x + dx, y + dy, color); } } diff --git a/base/applications/mspaint/fullscreen.cpp b/base/applications/mspaint/fullscreen.cpp index 63dd070da6d..5baadac6f02 100644 --- a/base/applications/mspaint/fullscreen.cpp +++ b/base/applications/mspaint/fullscreen.cpp @@ -23,8 +23,8 @@ HWND CFullscreenWindow::DoCreate() LRESULT CFullscreenWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON))); - SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON))); + SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON))); + SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON))); return 0; } diff --git a/base/applications/mspaint/globalvar.h b/base/applications/mspaint/globalvar.h index 4ed2cfc6a12..b38c82e665a 100644 --- a/base/applications/mspaint/globalvar.h +++ b/base/applications/mspaint/globalvar.h @@ -10,18 +10,16 @@ /* VARIABLES declared in main.cpp ***********************************/ -extern BOOL askBeforeEnlarging; +extern BOOL g_askBeforeEnlarging; -extern POINT start; -extern POINT last; +extern POINT g_ptStart, g_ptEnd; -extern HINSTANCE hProgInstance; +extern HINSTANCE g_hinstExe; -extern TCHAR filepathname[MAX_LONG_PATH]; -extern BOOL isAFile; -extern BOOL imageSaved; - -extern BOOL showGrid; +extern TCHAR g_szFileName[MAX_LONG_PATH]; +extern BOOL g_isAFile; +extern BOOL g_imageSaved; +extern BOOL g_showGrid; extern CMainWindow mainWindow; @@ -40,11 +38,11 @@ extern ToolsModel toolsModel; extern SelectionModel selectionModel; extern PaletteModel paletteModel; -extern HWND hStatusBar; +extern HWND g_hStatusBar; extern float g_xDpi; extern float g_yDpi; -extern INT fileSize; -extern SYSTEMTIME fileTime; +extern INT g_fileSize; +extern SYSTEMTIME g_fileTime; extern CFullscreenWindow fullscreenWindow; extern CMiniatureWindow miniature; diff --git a/base/applications/mspaint/history.cpp b/base/applications/mspaint/history.cpp index 92ef896afd0..46a7341ff1c 100644 --- a/base/applications/mspaint/history.cpp +++ b/base/applications/mspaint/history.cpp @@ -22,103 +22,103 @@ void ImageModel::NotifyImageChanged() } ImageModel::ImageModel() - : hDrawingDC(::CreateCompatibleDC(NULL)) - , currInd(0) - , undoSteps(0) - , redoSteps(0) + : m_hDrawingDC(::CreateCompatibleDC(NULL)) + , m_currInd(0) + , m_undoSteps(0) + , m_redoSteps(0) { - ZeroMemory(hBms, sizeof(hBms)); + ZeroMemory(m_hBms, sizeof(m_hBms)); - hBms[0] = CreateDIBWithProperties(1, 1); - ::SelectObject(hDrawingDC, hBms[0]); + m_hBms[0] = CreateColorDIB(1, 1, RGB(255, 255, 255)); + m_hbmOld = ::SelectObject(m_hDrawingDC, m_hBms[0]); - imageSaved = TRUE; + g_imageSaved = TRUE; } ImageModel::~ImageModel() { - ::DeleteDC(hDrawingDC); + ::DeleteDC(m_hDrawingDC); for (size_t i = 0; i < HISTORYSIZE; ++i) { - if (hBms[i]) - ::DeleteObject(hBms[i]); + if (m_hBms[i]) + ::DeleteObject(m_hBms[i]); } } void ImageModel::Undo(BOOL bClearRedo) { - ATLTRACE("%s: %d\n", __FUNCTION__, undoSteps); + ATLTRACE("%s: %d\n", __FUNCTION__, m_undoSteps); if (!CanUndo()) return; - selectionModel.m_bShow = FALSE; + selectionModel.HideSelection(); // Select previous item - currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE; - ::SelectObject(hDrawingDC, hBms[currInd]); + m_currInd = (m_currInd + HISTORYSIZE - 1) % HISTORYSIZE; + ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); - undoSteps--; + m_undoSteps--; if (bClearRedo) - redoSteps = 0; - else if (redoSteps < HISTORYSIZE - 1) - redoSteps++; + m_redoSteps = 0; + else if (m_redoSteps < HISTORYSIZE - 1) + m_redoSteps++; NotifyImageChanged(); } void ImageModel::Redo() { - ATLTRACE("%s: %d\n", __FUNCTION__, redoSteps); + ATLTRACE("%s: %d\n", __FUNCTION__, m_redoSteps); if (!CanRedo()) return; - selectionModel.m_bShow = FALSE; + selectionModel.HideSelection(); // Select next item - currInd = (currInd + 1) % HISTORYSIZE; - ::SelectObject(hDrawingDC, hBms[currInd]); + m_currInd = (m_currInd + 1) % HISTORYSIZE; + ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); - redoSteps--; - if (undoSteps < HISTORYSIZE - 1) - undoSteps++; + m_redoSteps--; + if (m_undoSteps < HISTORYSIZE - 1) + m_undoSteps++; NotifyImageChanged(); } void ImageModel::ResetToPrevious() { - ATLTRACE("%s: %d\n", __FUNCTION__, currInd); + ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd); // Revert current item with previous item - ::DeleteObject(hBms[currInd]); - hBms[currInd] = CopyDIBImage(hBms[(currInd + HISTORYSIZE - 1) % HISTORYSIZE]); - ::SelectObject(hDrawingDC, hBms[currInd]); + ::DeleteObject(m_hBms[m_currInd]); + m_hBms[m_currInd] = CopyDIBImage(m_hBms[(m_currInd + HISTORYSIZE - 1) % HISTORYSIZE]); + ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); NotifyImageChanged(); } void ImageModel::ClearHistory() { - undoSteps = 0; - redoSteps = 0; + m_undoSteps = 0; + m_redoSteps = 0; } void ImageModel::PushImageForUndo(HBITMAP hbm) { - ATLTRACE("%s: %d\n", __FUNCTION__, currInd); + ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd); // Go to the next item with an HBITMAP or current item - ::DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]); - hBms[(currInd + 1) % HISTORYSIZE] = (hbm ? hbm : CopyDIBImage(hBms[currInd])); - currInd = (currInd + 1) % HISTORYSIZE; - ::SelectObject(hDrawingDC, hBms[currInd]); + ::DeleteObject(m_hBms[(m_currInd + 1) % HISTORYSIZE]); + m_hBms[(m_currInd + 1) % HISTORYSIZE] = (hbm ? hbm : CopyDIBImage(m_hBms[m_currInd])); + m_currInd = (m_currInd + 1) % HISTORYSIZE; + ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); - if (undoSteps < HISTORYSIZE - 1) - undoSteps++; - redoSteps = 0; + if (m_undoSteps < HISTORYSIZE - 1) + m_undoSteps++; + m_redoSteps = 0; - imageSaved = FALSE; + g_imageSaved = FALSE; NotifyImageChanged(); } @@ -136,7 +136,7 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY) return; // Select the HBITMAP by memory DC - HDC hdcMem = ::CreateCompatibleDC(hDrawingDC); + HDC hdcMem = ::CreateCompatibleDC(m_hDrawingDC); HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmCropped); // Fill background of the HBITMAP @@ -146,7 +146,7 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY) ::DeleteObject(hbrBack); // Copy the old content - ::BitBlt(hdcMem, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), hDrawingDC, 0, 0, SRCCOPY); + ::BitBlt(hdcMem, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), m_hDrawingDC, 0, 0, SRCCOPY); // Clean up ::SelectObject(hdcMem, hbmOld); @@ -160,12 +160,12 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY) void ImageModel::SaveImage(LPCTSTR lpFileName) { - SaveDIBToFile(hBms[currInd], lpFileName, hDrawingDC); + SaveDIBToFile(m_hBms[m_currInd], lpFileName, m_hDrawingDC); } BOOL ImageModel::IsImageSaved() const { - return imageSaved; + return g_imageSaved; } void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY) @@ -176,17 +176,17 @@ void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSk INT newHeight = oldHeight * nStretchPercentY / 100; if (oldWidth != newWidth || oldHeight != newHeight) { - HBITMAP hbm0 = CopyDIBImage(hBms[currInd], newWidth, newHeight); + HBITMAP hbm0 = CopyDIBImage(m_hBms[m_currInd], newWidth, newHeight); PushImageForUndo(hbm0); } if (nSkewDegX) { - HBITMAP hbm1 = SkewDIB(hDrawingDC, hBms[currInd], nSkewDegX, FALSE); + HBITMAP hbm1 = SkewDIB(m_hDrawingDC, m_hBms[m_currInd], nSkewDegX, FALSE); PushImageForUndo(hbm1); } if (nSkewDegY) { - HBITMAP hbm2 = SkewDIB(hDrawingDC, hBms[currInd], nSkewDegY, TRUE); + HBITMAP hbm2 = SkewDIB(m_hDrawingDC, m_hBms[m_currInd], nSkewDegY, TRUE); PushImageForUndo(hbm2); } NotifyImageChanged(); @@ -194,31 +194,31 @@ void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSk int ImageModel::GetWidth() const { - return GetDIBWidth(hBms[currInd]); + return GetDIBWidth(m_hBms[m_currInd]); } int ImageModel::GetHeight() const { - return GetDIBHeight(hBms[currInd]); + return GetDIBHeight(m_hBms[m_currInd]); } void ImageModel::InvertColors() { RECT rect = {0, 0, GetWidth(), GetHeight()}; PushImageForUndo(); - InvertRect(hDrawingDC, &rect); + InvertRect(m_hDrawingDC, &rect); NotifyImageChanged(); } HDC ImageModel::GetDC() { - return hDrawingDC; + return m_hDrawingDC; } void ImageModel::FlipHorizontally() { PushImageForUndo(); - StretchBlt(hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0, + StretchBlt(m_hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0, GetWidth(), GetHeight(), SRCCOPY); NotifyImageChanged(); } @@ -226,7 +226,7 @@ void ImageModel::FlipHorizontally() void ImageModel::FlipVertically() { PushImageForUndo(); - StretchBlt(hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0, + StretchBlt(m_hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0, GetWidth(), GetHeight(), SRCCOPY); NotifyImageChanged(); } @@ -238,7 +238,7 @@ void ImageModel::RotateNTimes90Degrees(int iN) case 1: case 3: { - HBITMAP hbm = Rotate90DegreeBlt(hDrawingDC, GetWidth(), GetHeight(), iN == 1, FALSE); + HBITMAP hbm = Rotate90DegreeBlt(m_hDrawingDC, GetWidth(), GetHeight(), iN == 1, FALSE); if (hbm) PushImageForUndo(hbm); break; @@ -246,28 +246,25 @@ void ImageModel::RotateNTimes90Degrees(int iN) case 2: { PushImageForUndo(); - StretchBlt(hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(), - hDrawingDC, 0, 0, GetWidth(), GetHeight(), SRCCOPY); + StretchBlt(m_hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(), + m_hDrawingDC, 0, 0, GetWidth(), GetHeight(), SRCCOPY); break; } } NotifyImageChanged(); } -void ImageModel::DeleteSelection() -{ - if (!selectionModel.m_bShow) - return; - - selectionModel.TakeOff(); - selectionModel.m_bShow = FALSE; - selectionModel.ClearColor(); - selectionModel.ClearMask(); - NotifyImageChanged(); -} - void ImageModel::Bound(POINT& pt) const { pt.x = max(0, min(pt.x, GetWidth())); pt.y = max(0, min(pt.y, GetHeight())); } + +HBITMAP ImageModel::CopyBitmap() +{ + // NOTE: An app cannot select a bitmap into more than one device context at a time. + ::SelectObject(m_hDrawingDC, m_hbmOld); // De-select + HBITMAP ret = CopyDIBImage(m_hBms[m_currInd]); + m_hbmOld = ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); // Re-select + return ret; +} diff --git a/base/applications/mspaint/history.h b/base/applications/mspaint/history.h index 00e66950425..2b74f306248 100644 --- a/base/applications/mspaint/history.h +++ b/base/applications/mspaint/history.h @@ -18,8 +18,8 @@ public: virtual ~ImageModel(); HDC GetDC(); - BOOL CanUndo() const { return undoSteps > 0; } - BOOL CanRedo() const { return redoSteps > 0; } + BOOL CanUndo() const { return m_undoSteps > 0; } + BOOL CanRedo() const { return m_redoSteps > 0; } void PushImageForUndo(HBITMAP hbm = NULL); void ResetToPrevious(void); void Undo(BOOL bClearRedo = FALSE); @@ -31,18 +31,19 @@ public: void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX = 0, int nSkewDegY = 0); int GetWidth() const; int GetHeight() const; + HBITMAP CopyBitmap(); void InvertColors(); void FlipHorizontally(); void FlipVertically(); void RotateNTimes90Degrees(int iN); - void DeleteSelection(); void Bound(POINT& pt) const; void NotifyImageChanged(); protected: - HDC hDrawingDC; // The device context for this class - int currInd; // The current index - int undoSteps; // The undo-able count - int redoSteps; // The redo-able count - HBITMAP hBms[HISTORYSIZE]; // A rotation buffer of HBITMAPs + HDC m_hDrawingDC; // The device context for this class + int m_currInd; // The current index in m_hBms + int m_undoSteps; // The undo-able count + int m_redoSteps; // The redo-able count + HBITMAP m_hBms[HISTORYSIZE]; // A rotation buffer of HBITMAPs + HGDIOBJ m_hbmOld; }; diff --git a/base/applications/mspaint/main.cpp b/base/applications/mspaint/main.cpp index 8d328de1e84..b3b6728fd94 100644 --- a/base/applications/mspaint/main.cpp +++ b/base/applications/mspaint/main.cpp @@ -8,15 +8,13 @@ #include "precomp.h" -POINT start; -POINT last; - -BOOL askBeforeEnlarging = FALSE; // TODO: initialize from registry -HINSTANCE hProgInstance = NULL; -TCHAR filepathname[MAX_LONG_PATH] = { 0 }; -BOOL isAFile = FALSE; -BOOL imageSaved = FALSE; -BOOL showGrid = FALSE; +POINT g_ptStart, g_ptEnd; +BOOL g_askBeforeEnlarging = FALSE; // TODO: initialize from registry +HINSTANCE g_hinstExe = NULL; +TCHAR g_szFileName[MAX_LONG_PATH] = { 0 }; +BOOL g_isAFile = FALSE; +BOOL g_imageSaved = FALSE; +BOOL g_showGrid = FALSE; CMainWindow mainWindow; @@ -81,7 +79,7 @@ BOOL CMainWindow::GetOpenFileName(IN OUT LPTSTR pszFile, INT cchMaxFile) { // The "All Files" item text CString strAllPictureFiles; - strAllPictureFiles.LoadString(hProgInstance, IDS_ALLPICTUREFILES); + strAllPictureFiles.LoadString(g_hinstExe, IDS_ALLPICTUREFILES); // Get the import filter CSimpleArray aguidFileTypesI; @@ -92,7 +90,7 @@ BOOL CMainWindow::GetOpenFileName(IN OUT LPTSTR pszFile, INT cchMaxFile) ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = m_hWnd; - ofn.hInstance = hProgInstance; + ofn.hInstance = g_hinstExe; ofn.lpstrFilter = strFilter; ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; ofn.lpstrDefExt = L"png"; @@ -119,7 +117,7 @@ BOOL CMainWindow::GetSaveFileName(IN OUT LPTSTR pszFile, INT cchMaxFile) ZeroMemory(&sfn, sizeof(sfn)); sfn.lStructSize = sizeof(sfn); sfn.hwndOwner = m_hWnd; - sfn.hInstance = hProgInstance; + sfn.hInstance = g_hinstExe; sfn.lpstrFilter = strFilter; sfn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK; sfn.lpfnHook = OFNHookProc; @@ -170,10 +168,10 @@ BOOL CMainWindow::ChooseColor(IN OUT COLORREF *prgbColor) HWND CMainWindow::DoCreate() { - ::LoadString(hProgInstance, IDS_DEFAULTFILENAME, filepathname, _countof(filepathname)); + ::LoadString(g_hinstExe, IDS_DEFAULTFILENAME, g_szFileName, _countof(g_szFileName)); CString strTitle; - strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname)); + strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName)); RECT& rc = registrySettings.WindowPlacement.rcNormalPosition; return Create(HWND_DESKTOP, rc, strTitle, WS_OVERLAPPEDWINDOW, WS_EX_ACCEPTFILES); @@ -188,7 +186,7 @@ _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, INT nC _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif - hProgInstance = hInstance; + g_hinstExe = hInstance; // Initialize common controls library INITCOMMONCONTROLSEX iccx; diff --git a/base/applications/mspaint/miniature.cpp b/base/applications/mspaint/miniature.cpp index b354de983b1..ab10814e5bf 100644 --- a/base/applications/mspaint/miniature.cpp +++ b/base/applications/mspaint/miniature.cpp @@ -38,7 +38,7 @@ HWND CMiniatureWindow::DoCreate(HWND hwndParent) }; TCHAR strTitle[100]; - ::LoadString(hProgInstance, IDS_MINIATURETITLE, strTitle, _countof(strTitle)); + ::LoadString(g_hinstExe, IDS_MINIATURETITLE, strTitle, _countof(strTitle)); DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME; return Create(hwndParent, rc, strTitle, style, WS_EX_PALETTEWINDOW); diff --git a/base/applications/mspaint/mouse.cpp b/base/applications/mspaint/mouse.cpp index 3c0923bec58..97359f0ce68 100644 --- a/base/applications/mspaint/mouse.cpp +++ b/base/applications/mspaint/mouse.cpp @@ -53,25 +53,25 @@ BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1) void updateStartAndLast(LONG x, LONG y) { - start.x = last.x = x; - start.y = last.y = y; + g_ptStart.x = g_ptEnd.x = x; + g_ptStart.y = g_ptEnd.y = y; } void updateLast(LONG x, LONG y) { - last.x = x; - last.y = y; + g_ptEnd.x = x; + g_ptEnd.y = y; } void ToolBase::reset() { pointSP = 0; - start.x = start.y = last.x = last.y = -1; + g_ptStart.x = g_ptStart.y = g_ptEnd.x = g_ptEnd.y = -1; selectionModel.ResetPtStack(); if (selectionModel.m_bShow) { selectionModel.Landing(); - selectionModel.m_bShow = FALSE; + selectionModel.HideSelection(); } } @@ -99,24 +99,54 @@ void ToolBase::endEvent() m_hdc = NULL; } +void ToolBase::OnDrawSelectionOnCanvas(HDC hdc) +{ + if (!selectionModel.m_bShow) + return; + + RECT rcSelection = selectionModel.m_rc; + canvasWindow.ImageToCanvas(rcSelection); + + ::InflateRect(&rcSelection, GRIP_SIZE, GRIP_SIZE); + drawSizeBoxes(hdc, &rcSelection, TRUE); +} + /* TOOLS ********************************************************/ // TOOL_FREESEL struct FreeSelTool : ToolBase { - BOOL m_bLeftButton; + BOOL m_bLeftButton = FALSE; - FreeSelTool() : ToolBase(TOOL_FREESEL), m_bLeftButton(FALSE) + FreeSelTool() : ToolBase(TOOL_FREESEL) { } + void OnDrawOverlayOnImage(HDC hdc) override + { + if (!selectionModel.IsLanded()) + { + selectionModel.DrawBackgroundPoly(hdc, selectionModel.m_rgbBack); + selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent()); + } + + if (canvasWindow.m_drawing) + { + selectionModel.DrawFramePoly(hdc); + } + } + + void OnDrawOverlayOnCanvas(HDC hdc) override + { + OnDrawSelectionOnCanvas(hdc); + } + void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override { selectionModel.Landing(); if (bLeftButton) { - imageModel.PushImageForUndo(); - selectionModel.m_bShow = FALSE; + selectionModel.HideSelection(); selectionModel.ResetPtStack(); POINT pt = { x, y }; selectionModel.PushToPtStack(pt); @@ -131,8 +161,7 @@ struct FreeSelTool : ToolBase POINT pt = { x, y }; imageModel.Bound(pt); selectionModel.PushToPtStack(pt); - imageModel.ResetToPrevious(); - selectionModel.DrawFramePoly(m_hdc); + imageModel.NotifyImageChanged(); } } @@ -140,16 +169,13 @@ struct FreeSelTool : ToolBase { if (bLeftButton) { - imageModel.ResetToPrevious(); if (selectionModel.PtStackSize() > 2) { selectionModel.BuildMaskFromPtStack(); - selectionModel.TakeOff(); selectionModel.m_bShow = TRUE; } else { - imageModel.Undo(TRUE); selectionModel.ResetPtStack(); selectionModel.m_bShow = FALSE; } @@ -159,15 +185,13 @@ struct FreeSelTool : ToolBase void OnFinishDraw() override { - m_bLeftButton = FALSE; + selectionModel.Landing(); ToolBase::OnFinishDraw(); } void OnCancelDraw() override { - if (m_bLeftButton) - imageModel.Undo(TRUE); - m_bLeftButton = FALSE; + selectionModel.HideSelection(); ToolBase::OnCancelDraw(); } }; @@ -175,20 +199,39 @@ struct FreeSelTool : ToolBase // TOOL_RECTSEL struct RectSelTool : ToolBase { - BOOL m_bLeftButton; + BOOL m_bLeftButton = FALSE; - RectSelTool() : ToolBase(TOOL_RECTSEL), m_bLeftButton(FALSE) + RectSelTool() : ToolBase(TOOL_RECTSEL) { } + void OnDrawOverlayOnImage(HDC hdc) override + { + if (!selectionModel.IsLanded()) + { + selectionModel.DrawBackgroundRect(hdc, selectionModel.m_rgbBack); + selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent()); + } + + if (canvasWindow.m_drawing) + { + RECT rc = selectionModel.m_rc; + if (!::IsRectEmpty(&rc)) + RectSel(hdc, rc.left, rc.top, rc.right, rc.bottom); + } + } + + void OnDrawOverlayOnCanvas(HDC hdc) override + { + OnDrawSelectionOnCanvas(hdc); + } + void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override { selectionModel.Landing(); if (bLeftButton) { - imageModel.PushImageForUndo(); - selectionModel.m_bShow = FALSE; - ::SetRectEmpty(&selectionModel.m_rc); + selectionModel.HideSelection(); } m_bLeftButton = bLeftButton; } @@ -197,11 +240,10 @@ struct RectSelTool : ToolBase { if (bLeftButton) { - imageModel.ResetToPrevious(); POINT pt = { x, y }; imageModel.Bound(pt); - selectionModel.SetRectFromPoints(start, pt); - RectSel(m_hdc, start.x, start.y, pt.x, pt.y); + selectionModel.SetRectFromPoints(g_ptStart, pt); + imageModel.NotifyImageChanged(); } } @@ -209,9 +251,9 @@ struct RectSelTool : ToolBase { if (bLeftButton) { - imageModel.ResetToPrevious(); - if (start.x == x && start.y == y) - imageModel.Undo(TRUE); + POINT pt = { x, y }; + imageModel.Bound(pt); + selectionModel.SetRectFromPoints(g_ptStart, pt); selectionModel.m_bShow = !selectionModel.m_rc.IsRectEmpty(); imageModel.NotifyImageChanged(); } @@ -219,22 +261,68 @@ struct RectSelTool : ToolBase void OnFinishDraw() override { - m_bLeftButton = FALSE; + selectionModel.Landing(); ToolBase::OnFinishDraw(); } void OnCancelDraw() override { - if (m_bLeftButton) - imageModel.Undo(TRUE); - m_bLeftButton = FALSE; + selectionModel.HideSelection(); ToolBase::OnCancelDraw(); } }; -struct GenericDrawTool : ToolBase +struct TwoPointDrawTool : ToolBase { - GenericDrawTool(TOOLTYPE type) : ToolBase(type) + BOOL m_bLeftButton = FALSE; + BOOL m_bDrawing = FALSE; + + TwoPointDrawTool(TOOLTYPE type) : ToolBase(type) + { + } + + void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override + { + m_bLeftButton = bLeftButton; + m_bDrawing = TRUE; + g_ptStart.x = g_ptEnd.x = x; + g_ptStart.y = g_ptEnd.y = y; + imageModel.NotifyImageChanged(); + } + + void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override + { + g_ptEnd.x = x; + g_ptEnd.y = y; + imageModel.NotifyImageChanged(); + } + + void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override + { + g_ptEnd.x = x; + g_ptEnd.y = y; + imageModel.PushImageForUndo(); + OnDrawOverlayOnImage(m_hdc); + m_bDrawing = FALSE; + imageModel.NotifyImageChanged(); + } + + void OnFinishDraw() override + { + m_bDrawing = FALSE; + ToolBase::OnFinishDraw(); + } + + void OnCancelDraw() override + { + m_bDrawing = FALSE; + ToolBase::OnCancelDraw(); + } +}; + +struct SmoothDrawTool : ToolBase +{ + SmoothDrawTool(TOOLTYPE type) : ToolBase(type) { } @@ -243,7 +331,9 @@ struct GenericDrawTool : ToolBase void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override { imageModel.PushImageForUndo(); - draw(bLeftButton, x, y); + g_ptStart.x = g_ptEnd.x = x; + g_ptStart.y = g_ptEnd.y = y; + imageModel.NotifyImageChanged(); } void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override @@ -255,7 +345,12 @@ struct GenericDrawTool : ToolBase void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override { draw(bLeftButton, x, y); - imageModel.NotifyImageChanged(); + OnFinishDraw(); + } + + void OnFinishDraw() override + { + ToolBase::OnFinishDraw(); } void OnCancelDraw() override @@ -267,18 +362,20 @@ struct GenericDrawTool : ToolBase }; // TOOL_RUBBER -struct RubberTool : GenericDrawTool +struct RubberTool : SmoothDrawTool { - RubberTool() : GenericDrawTool(TOOL_RUBBER) + RubberTool() : SmoothDrawTool(TOOL_RUBBER) { } void draw(BOOL bLeftButton, LONG x, LONG y) override { if (bLeftButton) - Erase(m_hdc, last.x, last.y, x, y, m_bg, toolsModel.GetRubberRadius()); + Erase(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_bg, toolsModel.GetRubberRadius()); else - Replace(m_hdc, last.x, last.y, x, y, m_fg, m_bg, toolsModel.GetRubberRadius()); + Replace(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_fg, m_bg, toolsModel.GetRubberRadius()); + g_ptEnd.x = x; + g_ptEnd.y = y; } }; @@ -354,38 +451,42 @@ struct ZoomTool : ToolBase }; // TOOL_PEN -struct PenTool : GenericDrawTool +struct PenTool : SmoothDrawTool { - PenTool() : GenericDrawTool(TOOL_PEN) + PenTool() : SmoothDrawTool(TOOL_PEN) { } void draw(BOOL bLeftButton, LONG x, LONG y) override { COLORREF rgb = bLeftButton ? m_fg : m_bg; - Line(m_hdc, last.x, last.y, x, y, rgb, 1); + Line(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, 1); ::SetPixelV(m_hdc, x, y, rgb); + g_ptEnd.x = x; + g_ptEnd.y = y; } }; // TOOL_BRUSH -struct BrushTool : GenericDrawTool +struct BrushTool : SmoothDrawTool { - BrushTool() : GenericDrawTool(TOOL_BRUSH) + BrushTool() : SmoothDrawTool(TOOL_BRUSH) { } void draw(BOOL bLeftButton, LONG x, LONG y) override { COLORREF rgb = bLeftButton ? m_fg : m_bg; - Brush(m_hdc, last.x, last.y, x, y, rgb, toolsModel.GetBrushStyle()); + Brush(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetBrushStyle()); + g_ptEnd.x = x; + g_ptEnd.y = y; } }; // TOOL_AIRBRUSH -struct AirBrushTool : GenericDrawTool +struct AirBrushTool : SmoothDrawTool { - AirBrushTool() : GenericDrawTool(TOOL_AIRBRUSH) + AirBrushTool() : SmoothDrawTool(TOOL_AIRBRUSH) { } @@ -403,13 +504,22 @@ struct TextTool : ToolBase { } + void OnDrawOverlayOnImage(HDC hdc) override + { + if (canvasWindow.m_drawing) + { + RECT rc = selectionModel.m_rc; + if (!::IsRectEmpty(&rc)) + RectSel(hdc, rc.left, rc.top, rc.right, rc.bottom); + } + } + void UpdatePoint(LONG x, LONG y) { - imageModel.ResetToPrevious(); POINT pt = { x, y }; imageModel.Bound(pt); - selectionModel.SetRectFromPoints(start, pt); - RectSel(m_hdc, start.x, start.y, pt.x, pt.y); + selectionModel.SetRectFromPoints(g_ptStart, pt); + imageModel.NotifyImageChanged(); } void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override @@ -417,7 +527,6 @@ struct TextTool : ToolBase if (!textEditWindow.IsWindow()) textEditWindow.Create(canvasWindow); - imageModel.PushImageForUndo(); UpdatePoint(x, y); } @@ -426,30 +535,40 @@ struct TextTool : ToolBase UpdatePoint(x, y); } + void draw(HDC hdc) + { + CString szText; + textEditWindow.GetWindowText(szText); + + RECT rc; + textEditWindow.InvalidateEditRect(); + textEditWindow.GetEditRect(&rc); + ::InflateRect(&rc, -GRIP_SIZE / 2, -GRIP_SIZE / 2); + + // Draw the text + INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1); + imageModel.PushImageForUndo(); + Text(hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText, + textEditWindow.GetFont(), style); + } + + void quit() + { + if (textEditWindow.IsWindow()) + textEditWindow.ShowWindow(SW_HIDE); + selectionModel.HideSelection(); + } + void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override { - imageModel.Undo(TRUE); - POINT pt = { x, y }; imageModel.Bound(pt); - selectionModel.SetRectFromPoints(start, pt); + selectionModel.SetRectFromPoints(g_ptStart, pt); BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow); if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0) { - CString szText; - textEditWindow.GetWindowText(szText); - - RECT rc; - textEditWindow.InvalidateEditRect(); - textEditWindow.GetEditRect(&rc); - ::InflateRect(&rc, -GRIP_SIZE / 2, -GRIP_SIZE / 2); - - // Draw the text - INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1); - imageModel.PushImageForUndo(); - Text(m_hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText, - textEditWindow.GetFont(), style); + draw(m_hdc); if (selectionModel.m_rc.IsRectEmpty()) { @@ -494,201 +613,224 @@ struct TextTool : ToolBase void OnFinishDraw() override { - toolsModel.OnButtonDown(TRUE, -1, -1, TRUE); - toolsModel.OnButtonUp(TRUE, -1, -1); + draw(m_hdc); + quit(); ToolBase::OnFinishDraw(); } + + void OnCancelDraw() override + { + quit(); + ToolBase::OnCancelDraw(); + } }; // TOOL_LINE -struct LineTool : GenericDrawTool +struct LineTool : TwoPointDrawTool { - LineTool() : GenericDrawTool(TOOL_LINE) + LineTool() : TwoPointDrawTool(TOOL_LINE) { } - void draw(BOOL bLeftButton, LONG x, LONG y) override + void OnDrawOverlayOnImage(HDC hdc) override { - imageModel.ResetToPrevious(); + if (!m_bDrawing) + return; if (GetAsyncKeyState(VK_SHIFT) < 0) - roundTo8Directions(start.x, start.y, x, y); - COLORREF rgb = bLeftButton ? m_fg : m_bg; - Line(m_hdc, start.x, start.y, x, y, rgb, toolsModel.GetLineWidth()); + roundTo8Directions(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y); + COLORREF rgb = m_bLeftButton ? m_fg : m_bg; + Line(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, rgb, toolsModel.GetLineWidth()); } }; // TOOL_BEZIER struct BezierTool : ToolBase { - BOOL m_bLeftButton; + BOOL m_bLeftButton = FALSE; + BOOL m_bDrawing = FALSE; - BezierTool() : ToolBase(TOOL_BEZIER), m_bLeftButton(FALSE) + BezierTool() : ToolBase(TOOL_BEZIER) { } - void draw(BOOL bLeftButton) + void OnDrawOverlayOnImage(HDC hdc) { - COLORREF rgb = (bLeftButton ? m_fg : m_bg); + if (!m_bDrawing) + return; + + COLORREF rgb = (m_bLeftButton ? m_fg : m_bg); switch (pointSP) { case 1: - Line(m_hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, rgb, + Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, rgb, toolsModel.GetLineWidth()); break; case 2: - Bezier(m_hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], rgb, toolsModel.GetLineWidth()); + Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], rgb, toolsModel.GetLineWidth()); break; case 3: - Bezier(m_hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], rgb, toolsModel.GetLineWidth()); + Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], rgb, toolsModel.GetLineWidth()); break; } - m_bLeftButton = bLeftButton; } void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override { - pointStack[pointSP].x = x; - pointStack[pointSP].y = y; + m_bLeftButton = bLeftButton; - if (pointSP == 0) + if (!m_bDrawing) { - imageModel.PushImageForUndo(); - pointSP++; + m_bDrawing = TRUE; + pointStack[pointSP].x = pointStack[pointSP + 1].x = x; + pointStack[pointSP].y = pointStack[pointSP + 1].y = y; + ++pointSP; } + else + { + ++pointSP; + pointStack[pointSP].x = x; + pointStack[pointSP].y = y; + } + + imageModel.NotifyImageChanged(); } void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override { - imageModel.ResetToPrevious(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; - draw(bLeftButton); + imageModel.NotifyImageChanged(); } void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override { - imageModel.ResetToPrevious(); - draw(bLeftButton); - pointSP++; - if (pointSP == 4) - pointSP = 0; + pointStack[pointSP].x = x; + pointStack[pointSP].y = y; + if (pointSP >= 3) + { + OnFinishDraw(); + return; + } imageModel.NotifyImageChanged(); } void OnCancelDraw() override { - OnButtonUp(FALSE, 0, 0); - imageModel.Undo(TRUE); + m_bDrawing = FALSE; ToolBase::OnCancelDraw(); } void OnFinishDraw() override { - if (pointSP) - { - imageModel.ResetToPrevious(); - --pointSP; - draw(m_bLeftButton); - } + imageModel.PushImageForUndo(); + OnDrawOverlayOnImage(m_hdc); + m_bDrawing = FALSE; ToolBase::OnFinishDraw(); } }; // TOOL_RECT -struct RectTool : GenericDrawTool +struct RectTool : TwoPointDrawTool { - RectTool() : GenericDrawTool(TOOL_RECT) + RectTool() : TwoPointDrawTool(TOOL_RECT) { } - void draw(BOOL bLeftButton, LONG x, LONG y) override + void OnDrawOverlayOnImage(HDC hdc) override { - imageModel.ResetToPrevious(); + if (!m_bDrawing) + return; if (GetAsyncKeyState(VK_SHIFT) < 0) - regularize(start.x, start.y, x, y); - if (bLeftButton) - Rect(m_hdc, start.x, start.y, x, y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); + regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y); + if (m_bLeftButton) + Rect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); else - Rect(m_hdc, start.x, start.y, x, y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); + Rect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); } }; // TOOL_SHAPE struct ShapeTool : ToolBase { - BOOL m_bLeftButton; + BOOL m_bLeftButton = FALSE; + BOOL m_bClosed = FALSE; - ShapeTool() : ToolBase(TOOL_SHAPE), m_bLeftButton(FALSE) + ShapeTool() : ToolBase(TOOL_SHAPE) { } - void draw(BOOL bLeftButton, LONG x, LONG y, BOOL bClosed = FALSE) + void OnDrawOverlayOnImage(HDC hdc) { - if (pointSP + 1 >= 2) - { - if (bLeftButton) - Poly(m_hdc, pointStack, pointSP + 1, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), bClosed, FALSE); - else - Poly(m_hdc, pointStack, pointSP + 1, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), bClosed, FALSE); - } - m_bLeftButton = bLeftButton; + if (pointSP <= 0) + return; + + if (m_bLeftButton) + Poly(hdc, pointStack, pointSP + 1, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE); + else + Poly(hdc, pointStack, pointSP + 1, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE); } void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override { + m_bLeftButton = bLeftButton; + m_bClosed = FALSE; + pointStack[pointSP].x = x; pointStack[pointSP].y = y; - if (pointSP == 0 && !bDoubleClick) + if (pointSP && bDoubleClick) + { + OnFinishDraw(); + return; + } + + if (pointSP == 0) { - imageModel.PushImageForUndo(); - draw(bLeftButton, x, y); pointSP++; + pointStack[pointSP].x = x; + pointStack[pointSP].y = y; } - else - { - draw(bLeftButton, x, y, bDoubleClick); - imageModel.NotifyImageChanged(); - } + + imageModel.NotifyImageChanged(); } void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override { - imageModel.ResetToPrevious(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; + if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, x, y); - draw(bLeftButton, x, y, FALSE); + + imageModel.NotifyImageChanged(); } void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override { - imageModel.ResetToPrevious(); if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, x, y); + m_bClosed = FALSE; if (nearlyEqualPoints(x, y, pointStack[0].x, pointStack[0].y)) { - pointSP--; - draw(bLeftButton, x, y, TRUE); - pointSP = 0; + OnFinishDraw(); + return; } else { pointSP++; pointStack[pointSP].x = x; pointStack[pointSP].y = y; - draw(bLeftButton, x, y, FALSE); } if (pointSP == _countof(pointStack)) pointSP--; + + imageModel.NotifyImageChanged(); } void OnCancelDraw() override { - imageModel.Undo(TRUE); ToolBase::OnCancelDraw(); } @@ -696,49 +838,57 @@ struct ShapeTool : ToolBase { if (pointSP) { - imageModel.ResetToPrevious(); --pointSP; - draw(m_bLeftButton, -1, -1, TRUE); + m_bClosed = TRUE; + + imageModel.PushImageForUndo(); + OnDrawOverlayOnImage(m_hdc); } + + m_bClosed = FALSE; + pointSP = 0; + ToolBase::OnFinishDraw(); } }; // TOOL_ELLIPSE -struct EllipseTool : GenericDrawTool +struct EllipseTool : TwoPointDrawTool { - EllipseTool() : GenericDrawTool(TOOL_ELLIPSE) + EllipseTool() : TwoPointDrawTool(TOOL_ELLIPSE) { } - void draw(BOOL bLeftButton, LONG x, LONG y) override + void OnDrawOverlayOnImage(HDC hdc) override { - imageModel.ResetToPrevious(); + if (!m_bDrawing) + return; if (GetAsyncKeyState(VK_SHIFT) < 0) - regularize(start.x, start.y, x, y); - if (bLeftButton) - Ellp(m_hdc, start.x, start.y, x, y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); + regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y); + if (m_bLeftButton) + Ellp(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); else - Ellp(m_hdc, start.x, start.y, x, y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); + Ellp(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); } }; // TOOL_RRECT -struct RRectTool : GenericDrawTool +struct RRectTool : TwoPointDrawTool { - RRectTool() : GenericDrawTool(TOOL_RRECT) + RRectTool() : TwoPointDrawTool(TOOL_RRECT) { } - void draw(BOOL bLeftButton, LONG x, LONG y) override + void OnDrawOverlayOnImage(HDC hdc) override { - imageModel.ResetToPrevious(); + if (!m_bDrawing) + return; if (GetAsyncKeyState(VK_SHIFT) < 0) - regularize(start.x, start.y, x, y); - if (bLeftButton) - RRect(m_hdc, start.x, start.y, x, y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); + regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y); + if (m_bLeftButton) + RRect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); else - RRect(m_hdc, start.x, start.y, x, y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); + RRect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); } }; diff --git a/base/applications/mspaint/palette.cpp b/base/applications/mspaint/palette.cpp index f268a982f49..39346fd5e8a 100644 --- a/base/applications/mspaint/palette.cpp +++ b/base/applications/mspaint/palette.cpp @@ -181,13 +181,7 @@ LRESULT CPaletteWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT CPaletteWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - InvalidateRect(NULL, FALSE); - return 0; -} - -LRESULT CPaletteWindow::OnPaletteModelPaletteChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) -{ - InvalidateRect(NULL, FALSE); + Invalidate(FALSE); return 0; } diff --git a/base/applications/mspaint/palette.h b/base/applications/mspaint/palette.h index fe23edda53f..63f3c4caf2b 100644 --- a/base/applications/mspaint/palette.h +++ b/base/applications/mspaint/palette.h @@ -27,7 +27,6 @@ public: MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) MESSAGE_HANDLER(WM_PALETTEMODELCOLORCHANGED, OnPaletteModelColorChanged) - MESSAGE_HANDLER(WM_PALETTEMODELPALETTECHANGED, OnPaletteModelPaletteChanged) END_MSG_MAP() CPaletteWindow(); @@ -45,7 +44,6 @@ protected: LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); - LRESULT OnPaletteModelPaletteChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); protected: INT DoHitTest(INT xPos, INT yPos) const; diff --git a/base/applications/mspaint/palettemodel.cpp b/base/applications/mspaint/palettemodel.cpp index 8d18449fbee..a07825e4762 100644 --- a/base/applications/mspaint/palettemodel.cpp +++ b/base/applications/mspaint/palettemodel.cpp @@ -106,5 +106,5 @@ void PaletteModel::NotifyColorChanged() void PaletteModel::NotifyPaletteChanged() { if (paletteWindow.IsWindow()) - paletteWindow.SendMessage(WM_PALETTEMODELPALETTECHANGED); + paletteWindow.Invalidate(FALSE); } diff --git a/base/applications/mspaint/selectionmodel.cpp b/base/applications/mspaint/selectionmodel.cpp index d70f324d805..9497cef153f 100644 --- a/base/applications/mspaint/selectionmodel.cpp +++ b/base/applications/mspaint/selectionmodel.cpp @@ -21,6 +21,7 @@ SelectionModel::SelectionModel() , m_bShow(FALSE) { ::SetRectEmpty(&m_rc); + ::SetRectEmpty(&m_rcOld); m_ptHit.x = m_ptHit.y = -1; } @@ -57,25 +58,13 @@ void SelectionModel::PushToPtStack(POINT pt) #undef GROW_COUNT } -void SelectionModel::ShiftPtStack(BOOL bPlus) +void SelectionModel::ShiftPtStack(INT dx, INT dy) { - if (bPlus) + for (INT i = 0; i < m_iPtSP; ++i) { - for (INT i = 0; i < m_iPtSP; ++i) - { - POINT& pt = m_ptStack[i]; - pt.x += m_rc.left; - pt.y += m_rc.top; - } - } - else - { - for (INT i = 0; i < m_iPtSP; ++i) - { - POINT& pt = m_ptStack[i]; - pt.x -= m_rc.left; - pt.y -= m_rc.top; - } + POINT& pt = m_ptStack[i]; + pt.x += dx; + pt.y += dy; } } @@ -93,16 +82,16 @@ void SelectionModel::BuildMaskFromPtStack() rc.right += 1; rc.bottom += 1; - m_rc = rc; - - ShiftPtStack(FALSE); + m_rc = m_rcOld = rc; ClearMask(); + ShiftPtStack(-m_rcOld.left, -m_rcOld.top); + HDC hdcMem = ::CreateCompatibleDC(NULL); m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL); HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask); - FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH)); + ::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH)); HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN)); HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH)); ::Polygon(hdcMem, m_ptStack, m_iPtSP); @@ -110,34 +99,39 @@ void SelectionModel::BuildMaskFromPtStack() ::SelectObject(hdcMem, hPenOld); ::SelectObject(hdcMem, hbmOld); ::DeleteDC(hdcMem); + + ShiftPtStack(+m_rcOld.left, +m_rcOld.top); } void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg) { - ShiftPtStack(TRUE); + if (::IsRectEmpty(&m_rcOld)) + return; HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN)); HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg)); ::Polygon(hDCImage, m_ptStack, m_iPtSP); ::DeleteObject(::SelectObject(hDCImage, hbrOld)); ::SelectObject(hDCImage, hPenOld); - - ShiftPtStack(FALSE); } void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg) { - Rect(hDCImage, m_rc.left, m_rc.top, m_rc.right, m_rc.bottom, crBg, crBg, 0, 1); + if (::IsRectEmpty(&m_rcOld)) + return; + + Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1); } -void SelectionModel::DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg, BOOL bBgTransparent) +void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent) { - CRect rc = *prc; + CRect rc = m_rc; if (::IsRectEmpty(&rc)) return; BITMAP bm; - GetObject(m_hbmColor, sizeof(BITMAP), &bm); + if (!GetObject(m_hbmColor, sizeof(BITMAP), &bm)) + return; COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID); @@ -161,23 +155,23 @@ void SelectionModel::GetSelectionContents(HDC hDCImage) ::DeleteDC(hMemDC); } +BOOL SelectionModel::IsLanded() const +{ + return !m_hbmColor; +} + BOOL SelectionModel::TakeOff() { - if (m_hbmColor || ::IsRectEmpty(&m_rc)) + if (!IsLanded() || ::IsRectEmpty(&m_rc)) return FALSE; - HDC hDCImage = imageModel.GetDC(); - GetSelectionContents(hDCImage); + m_rgbBack = paletteModel.GetBgColor(); + GetSelectionContents(imageModel.GetDC()); - if (toolsModel.GetActiveTool() == TOOL_FREESEL) - { - DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor()); - } - else - { + if (toolsModel.GetActiveTool() == TOOL_RECTSEL) ClearMask(); - DrawBackgroundRect(hDCImage, paletteModel.GetBgColor()); - } + + m_rcOld = m_rc; imageModel.NotifyImageChanged(); return TRUE; @@ -185,16 +179,23 @@ BOOL SelectionModel::TakeOff() void SelectionModel::Landing() { - if (!m_hbmColor) + if (IsLanded() && !m_bShow) + { + imageModel.NotifyImageChanged(); return; + } - DrawSelection(imageModel.GetDC(), &m_rc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent()); + m_bShow = FALSE; - ::SetRectEmpty(&m_rc); - ClearMask(); - ClearColor(); + if (!::EqualRect(m_rc, m_rcOld) && !::IsRectEmpty(m_rc) && !::IsRectEmpty(m_rcOld)) + { + imageModel.PushImageForUndo(); - imageModel.PushImageForUndo(); + canvasWindow.m_drawing = FALSE; + toolsModel.OnDrawOverlayOnImage(imageModel.GetDC()); + } + + HideSelection(); } void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y) @@ -349,11 +350,11 @@ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int imageModel.NotifyImageChanged(); } -HBITMAP SelectionModel::GetBitmap() +HBITMAP SelectionModel::CopyBitmap() { if (m_hbmColor == NULL) GetSelectionContents(imageModel.GetDC()); - return m_hbmColor; + return CopyDIBImage(m_hbmColor); } int SelectionModel::PtStackSize() const @@ -435,15 +436,29 @@ void SelectionModel::ClearColor() } } -void SelectionModel::CancelSelection() +void SelectionModel::HideSelection() +{ + m_bShow = FALSE; + ClearColor(); + ClearMask(); + ::SetRectEmpty(&m_rc); + ::SetRectEmpty(&m_rcOld); + + imageModel.NotifyImageChanged(); +} + +void SelectionModel::DeleteSelection() { if (!m_bShow) return; - imageModel.PushImageForUndo(); - if (m_bShow) - imageModel.Undo(TRUE); + TakeOff(); - m_bShow = FALSE; - imageModel.NotifyImageChanged(); + imageModel.PushImageForUndo(); + if (toolsModel.GetActiveTool() == TOOL_FREESEL) + DrawBackgroundPoly(imageModel.GetDC(), paletteModel.GetBgColor()); + else + DrawBackgroundRect(imageModel.GetDC(), paletteModel.GetBgColor()); + + HideSelection(); } diff --git a/base/applications/mspaint/selectionmodel.h b/base/applications/mspaint/selectionmodel.h index 01a21c7bc62..f68a740d18f 100644 --- a/base/applications/mspaint/selectionmodel.h +++ b/base/applications/mspaint/selectionmodel.h @@ -18,9 +18,11 @@ private: int m_iPtSP; public: + COLORREF m_rgbBack = RGB(255, 255, 255); BOOL m_bShow; CRect m_rc; // in image pixel coordinates POINT m_ptHit; // in image pixel coordinates + CRect m_rcOld; // in image pixel coordinates SelectionModel(); ~SelectionModel(); @@ -33,13 +35,16 @@ public: BOOL TakeOff(); void Landing(); + BOOL IsLanded() const; + void HideSelection(); + void DeleteSelection(); - HBITMAP GetBitmap(); + HBITMAP CopyBitmap(); void GetSelectionContents(HDC hDCImage); void DrawFramePoly(HDC hDCImage); void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg); void DrawBackgroundRect(HDC hDCImage, COLORREF crBg); - void DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg = 0, BOOL bBgTransparent = FALSE); + void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE); void InsertFromHBITMAP(HBITMAP hBm, INT x = 0, INT y = 0); // operation @@ -48,7 +53,6 @@ public: void RotateNTimes90Degrees(int iN); void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY); - void CancelSelection(); void Dragging(CANVAS_HITTEST hit, POINT pt); void ClearMask(); void ClearColor(); @@ -57,5 +61,5 @@ private: SelectionModel(const SelectionModel&); SelectionModel& operator=(const SelectionModel&); - void ShiftPtStack(BOOL bPlus); + void ShiftPtStack(INT dx, INT dy); }; diff --git a/base/applications/mspaint/textedit.cpp b/base/applications/mspaint/textedit.cpp index 3b679c61272..bf0ab2ce4fb 100644 --- a/base/applications/mspaint/textedit.cpp +++ b/base/applications/mspaint/textedit.cpp @@ -61,7 +61,7 @@ void CTextEditWindow::FixEditPos(LPCTSTR pszOldText) SelectObject(hDC, m_hFontZoomed); TEXTMETRIC tm; GetTextMetrics(hDC, &tm); - szText += TEXT("x"); // This is a trick to enable the last newlines + szText += TEXT("x"); // This is a trick to enable the g_ptEnd newlines const UINT uFormat = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_EXPANDTABS | DT_WORDBREAK; DrawText(hDC, szText, -1, &rcText, uFormat | DT_CALCRECT); @@ -235,7 +235,7 @@ HWND CTextEditWindow::Create(HWND hwndParent) const DWORD style = ES_LEFT | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | WS_CHILD | WS_THICKFRAME; HWND hwnd = ::CreateWindowEx(0, WC_EDIT, NULL, style, 0, 0, 0, 0, - hwndParent, NULL, hProgInstance, NULL); + hwndParent, NULL, g_hinstExe, NULL); if (hwnd) { #undef SubclassWindow // Don't use this macro diff --git a/base/applications/mspaint/toolbox.cpp b/base/applications/mspaint/toolbox.cpp index 7e772a5bb6c..236ab9a4ba5 100644 --- a/base/applications/mspaint/toolbox.cpp +++ b/base/applications/mspaint/toolbox.cpp @@ -13,6 +13,20 @@ CToolBox toolBoxContainer; /* FUNCTIONS ********************************************************/ +LRESULT CALLBACK +CPaintToolBar::ToolBarWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC oldWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (uMsg == WM_LBUTTONUP) + { + // We have to detect clicking on toolbar even if no change of pressed button + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + INT id = (INT)SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt); + ::PostMessage(::GetParent(hwnd), WM_TOOLBARHIT, id, 0); + } + return ::CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); +} + BOOL CPaintToolBar::DoCreate(HWND hwndParent) { // NOTE: The horizontal line above the toolbar is hidden by CCS_NODIVIDER style. @@ -25,7 +39,7 @@ BOOL CPaintToolBar::DoCreate(HWND hwndParent) HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 16, 0); SendMessage(TB_SETIMAGELIST, 0, (LPARAM)hImageList); - HBITMAP hbmIcons = (HBITMAP)::LoadImage(hProgInstance, MAKEINTRESOURCE(IDB_TOOLBARICONS), + HBITMAP hbmIcons = (HBITMAP)::LoadImage(g_hinstExe, MAKEINTRESOURCE(IDB_TOOLBARICONS), IMAGE_BITMAP, 256, 16, 0); ImageList_AddMasked(hImageList, hbmIcons, RGB(255, 0, 255)); ::DeleteObject(hbmIcons); @@ -38,7 +52,7 @@ BOOL CPaintToolBar::DoCreate(HWND hwndParent) tbbutton.fsStyle = TBSTYLE_CHECKGROUP; for (INT i = 0; i < NUM_TOOLS; i++) { - ::LoadString(hProgInstance, IDS_TOOLTIP1 + i, szToolTip, _countof(szToolTip)); + ::LoadString(g_hinstExe, IDS_TOOLTIP1 + i, szToolTip, _countof(szToolTip)); tbbutton.iString = (INT_PTR)szToolTip; tbbutton.fsState = TBSTATE_ENABLED | ((i % 2 == 1) ? TBSTATE_WRAP : 0); tbbutton.idCommand = ID_FREESEL + i; @@ -49,6 +63,8 @@ BOOL CPaintToolBar::DoCreate(HWND hwndParent) SendMessage(TB_CHECKBUTTON, ID_PEN, MAKELPARAM(TRUE, 0)); SendMessage(TB_SETMAXTEXTROWS, 0, 0); SendMessage(TB_SETBUTTONSIZE, 0, MAKELPARAM(CXY_TB_BUTTON, CXY_TB_BUTTON)); + + SetWindowLongPtr(GWLP_USERDATA, SetWindowLongPtr(GWLP_WNDPROC, (LONG_PTR)ToolBarWndProc)); return TRUE; } @@ -114,7 +130,7 @@ LRESULT CToolBox::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHand LRESULT CToolBox::OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - selectionModel.m_bShow = FALSE; + selectionModel.HideSelection(); toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions // Check the toolbar button @@ -168,3 +184,10 @@ LRESULT CToolBox::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa ::ReleaseCapture(); return 0; } + +LRESULT CToolBox::OnToolBarHit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + // See also: CPaintToolBar::ToolBarWndProc + selectionModel.Landing(); + return 0; +} diff --git a/base/applications/mspaint/toolbox.h b/base/applications/mspaint/toolbox.h index bd0a635636a..33cfe5eb702 100644 --- a/base/applications/mspaint/toolbox.h +++ b/base/applications/mspaint/toolbox.h @@ -15,10 +15,13 @@ #define CX_TOOLBAR (TOOLBAR_COLUMNS * CXY_TB_BUTTON) #define CY_TOOLBAR (TOOLBAR_ROWS * CXY_TB_BUTTON) +#define WM_TOOLBARHIT (WM_APP + 1) + class CPaintToolBar : public CWindow { public: BOOL DoCreate(HWND hwndParent); + static LRESULT CALLBACK ToolBarWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); }; class CToolBox : public CWindowImpl @@ -34,6 +37,7 @@ public: MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) MESSAGE_HANDLER(WM_TOOLSMODELTOOLCHANGED, OnToolsModelToolChanged) + MESSAGE_HANDLER(WM_TOOLBARHIT, OnToolBarHit) END_MSG_MAP() BOOL DoCreate(HWND hwndParent); @@ -48,4 +52,5 @@ private: LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnToolBarHit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); }; diff --git a/base/applications/mspaint/toolsettings.cpp b/base/applications/mspaint/toolsettings.cpp index 323956ba7ca..97008c07563 100644 --- a/base/applications/mspaint/toolsettings.cpp +++ b/base/applications/mspaint/toolsettings.cpp @@ -200,11 +200,14 @@ VOID CToolSettingsWindow::drawAirBrush(HDC hdc, LPCRECT prc) if (bHigh) { ::FillRect(hdc, &rc, ::GetSysColorBrush(COLOR_HIGHLIGHT)); - Airbrush(hdc, x, y, ::GetSysColor(COLOR_HIGHLIGHTTEXT), s_AirRadius[i]); + + for (int k = 0; k < 3; ++k) + Airbrush(hdc, x, y, ::GetSysColor(COLOR_HIGHLIGHTTEXT), s_AirRadius[i]); } else { - Airbrush(hdc, x, y, ::GetSysColor(COLOR_WINDOWTEXT), s_AirRadius[i]); + for (int k = 0; k < 3; ++k) + Airbrush(hdc, x, y, ::GetSysColor(COLOR_WINDOWTEXT), s_AirRadius[i]); } } } @@ -258,9 +261,9 @@ VOID CToolSettingsWindow::drawBox(HDC hdc, LPCRECT prc) LRESULT CToolSettingsWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, WINBOOL& bHandled) { /* preloading the draw transparent/nontransparent icons for later use */ - m_hNontranspIcon = (HICON)LoadImage(hProgInstance, MAKEINTRESOURCE(IDI_NONTRANSPARENT), + m_hNontranspIcon = (HICON)LoadImage(g_hinstExe, MAKEINTRESOURCE(IDI_NONTRANSPARENT), IMAGE_ICON, CX_TRANS_ICON, CY_TRANS_ICON, LR_DEFAULTCOLOR); - m_hTranspIcon = (HICON)LoadImage(hProgInstance, MAKEINTRESOURCE(IDI_TRANSPARENT), + m_hTranspIcon = (HICON)LoadImage(g_hinstExe, MAKEINTRESOURCE(IDI_TRANSPARENT), IMAGE_ICON, CX_TRANS_ICON, CY_TRANS_ICON, LR_DEFAULTCOLOR); RECT trackbarZoomPos = {1, 1, 1 + 40, 1 + 64}; diff --git a/base/applications/mspaint/toolsmodel.cpp b/base/applications/mspaint/toolsmodel.cpp index 822547048f7..76a123513b5 100644 --- a/base/applications/mspaint/toolsmodel.cpp +++ b/base/applications/mspaint/toolsmodel.cpp @@ -28,7 +28,7 @@ ToolsModel::ToolsModel() ToolsModel::~ToolsModel() { - for (size_t i = 0; i < TOOL_MAX + 1; ++i) + for (size_t i = 0; i < _countof(m_tools); ++i) delete m_tools[i]; } @@ -87,9 +87,6 @@ void ToolsModel::SetActiveTool(TOOLTYPE nActiveTool) { OnFinishDraw(); - if (m_activeTool == nActiveTool) - return; - switch (m_activeTool) { case TOOL_FREESEL: @@ -225,6 +222,16 @@ void ToolsModel::OnFinishDraw() m_pToolObject->endEvent(); } +void ToolsModel::OnDrawOverlayOnImage(HDC hdc) +{ + m_pToolObject->OnDrawOverlayOnImage(hdc); +} + +void ToolsModel::OnDrawOverlayOnCanvas(HDC hdc) +{ + m_pToolObject->OnDrawOverlayOnCanvas(hdc); +} + void ToolsModel::resetTool() { m_pToolObject->reset(); diff --git a/base/applications/mspaint/toolsmodel.h b/base/applications/mspaint/toolsmodel.h index da0e06cfa2f..b8c819590a7 100644 --- a/base/applications/mspaint/toolsmodel.h +++ b/base/applications/mspaint/toolsmodel.h @@ -39,34 +39,27 @@ struct ToolBase static INT pointSP; static POINT pointStack[256]; - ToolBase(TOOLTYPE tool) : m_tool(tool), m_hdc(NULL) - { - } + ToolBase(TOOLTYPE tool) : m_tool(tool), m_hdc(NULL) { } + virtual ~ToolBase() { } - virtual ~ToolBase() - { - } - - virtual void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) - { - } - - virtual void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) - { - } - - virtual void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) - { - } + virtual void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) { } + virtual void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) { } + virtual void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) { } virtual void OnCancelDraw(); virtual void OnFinishDraw(); + virtual void OnDrawOverlayOnImage(HDC hdc) { } + virtual void OnDrawOverlayOnCanvas(HDC hdc) { } + void beginEvent(); void endEvent(); void reset(); static ToolBase* createToolObject(TOOLTYPE type); + +protected: + void OnDrawSelectionOnCanvas(HDC hdc); }; class ToolsModel @@ -112,6 +105,8 @@ public: void OnButtonUp(BOOL bLeftButton, LONG x, LONG y); void OnCancelDraw(); void OnFinishDraw(); + void OnDrawOverlayOnImage(HDC hdc); + void OnDrawOverlayOnCanvas(HDC hdc); void resetTool(); void selectAll(); diff --git a/base/applications/mspaint/winproc.cpp b/base/applications/mspaint/winproc.cpp index c3cc041ebe8..29bc32b9327 100644 --- a/base/applications/mspaint/winproc.cpp +++ b/base/applications/mspaint/winproc.cpp @@ -17,7 +17,7 @@ typedef HWND (WINAPI *FN_HtmlHelpW)(HWND, LPCWSTR, UINT, DWORD_PTR); static HINSTANCE s_hHHCTRL_OCX = NULL; // HtmlHelpW needs "hhctrl.ocx" static FN_HtmlHelpW s_pHtmlHelpW = NULL; -HWND hStatusBar = NULL; +HWND g_hStatusBar = NULL; /* FUNCTIONS ********************************************************/ @@ -79,9 +79,9 @@ void CMainWindow::alignChildrenToMainWindow() GetClientRect(&clientRect); RECT rcSpace = clientRect; - if (::IsWindowVisible(hStatusBar)) + if (::IsWindowVisible(g_hStatusBar)) { - ::GetWindowRect(hStatusBar, &rc); + ::GetWindowRect(g_hStatusBar, &rc); rcSpace.bottom -= rc.bottom - rc.top; } @@ -142,18 +142,18 @@ void CMainWindow::saveImage(BOOL overwrite) { canvasWindow.finishDrawing(); - if (isAFile && overwrite) + if (g_isAFile && overwrite) { - imageModel.SaveImage(filepathname); + imageModel.SaveImage(g_szFileName); } - else if (GetSaveFileName(filepathname, _countof(filepathname))) + else if (GetSaveFileName(g_szFileName, _countof(g_szFileName))) { - imageModel.SaveImage(filepathname); + imageModel.SaveImage(g_szFileName); CString strTitle; - strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname)); + strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName)); SetWindowText(strTitle); - isAFile = TRUE; + g_isAFile = TRUE; } } @@ -168,13 +168,13 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window) { BOOL shouldEnlarge = TRUE; - if (askBeforeEnlarging) + if (g_askBeforeEnlarging) { TCHAR programname[20]; TCHAR shouldEnlargePromptText[100]; - LoadString(hProgInstance, IDS_PROGRAMNAME, programname, _countof(programname)); - LoadString(hProgInstance, IDS_ENLARGEPROMPTTEXT, shouldEnlargePromptText, _countof(shouldEnlargePromptText)); + LoadString(g_hinstExe, IDS_PROGRAMNAME, programname, _countof(programname)); + LoadString(g_hinstExe, IDS_ENLARGEPROMPTTEXT, shouldEnlargePromptText, _countof(shouldEnlargePromptText)); switch (MessageBox(shouldEnlargePromptText, programname, MB_YESNOCANCEL | MB_ICONQUESTION)) { @@ -276,14 +276,14 @@ LRESULT CMainWindow::OnDropFiles(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // Loading and setting the window menu from resource - m_hMenu = ::LoadMenu(hProgInstance, MAKEINTRESOURCE(ID_MENU)); + m_hMenu = ::LoadMenu(g_hinstExe, MAKEINTRESOURCE(ID_MENU)); SetMenu(m_hMenu); // Create the status bar DWORD style = SBARS_SIZEGRIP | WS_CHILD | (registrySettings.ShowStatusBar ? WS_VISIBLE : 0); - hStatusBar = ::CreateWindowEx(0, STATUSCLASSNAME, NULL, style, 0, 0, 0, 0, m_hWnd, - NULL, hProgInstance, NULL); - ::SendMessage(hStatusBar, SB_SETMINHEIGHT, 21, 0); + g_hStatusBar = ::CreateWindowEx(0, STATUSCLASSNAME, NULL, style, 0, 0, 0, 0, m_hWnd, + NULL, g_hinstExe, NULL); + ::SendMessage(g_hStatusBar, SB_SETMINHEIGHT, 21, 0); // Create the tool box toolBoxContainer.DoCreate(m_hWnd); @@ -305,8 +305,8 @@ LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa } // Set icon - SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON))); - SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON))); + SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON))); + SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON))); return 0; } @@ -347,7 +347,7 @@ BOOL CMainWindow::ConfirmSave() strProgramName.LoadString(IDS_PROGRAMNAME); CString strSavePromptText; - strSavePromptText.Format(IDS_SAVEPROMPTTEXT, PathFindFileName(filepathname)); + strSavePromptText.Format(IDS_SAVEPROMPTTEXT, PathFindFileName(g_szFileName)); switch (MessageBox(strSavePromptText, strProgramName, MB_YESNOCANCEL | MB_ICONQUESTION)) { @@ -374,7 +374,7 @@ LRESULT CMainWindow::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHan void CMainWindow::ProcessFileMenu(HMENU hPopupMenu) { - LPCTSTR dotext = PathFindExtensionW(filepathname); + LPCTSTR dotext = PathFindExtensionW(g_szFileName); BOOL isBMP = FALSE; if (_tcsicmp(dotext, _T(".bmp")) == 0 || _tcsicmp(dotext, _T(".dib")) == 0 || @@ -383,9 +383,9 @@ void CMainWindow::ProcessFileMenu(HMENU hPopupMenu) isBMP = TRUE; } - EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERPLANE, ENABLED_IF(isAFile && isBMP)); - EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERCENTERED, ENABLED_IF(isAFile && isBMP)); - EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERSTRETCHED, ENABLED_IF(isAFile && isBMP)); + EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERPLANE, ENABLED_IF(g_isAFile && isBMP)); + EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERCENTERED, ENABLED_IF(g_isAFile && isBMP)); + EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERSTRETCHED, ENABLED_IF(g_isAFile && isBMP)); for (INT iItem = 0; iItem < MAX_RECENT_FILES; ++iItem) RemoveMenu(hPopupMenu, IDM_FILE1 + iItem, MF_BYCOMMAND); @@ -445,11 +445,11 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO case 2: /* View menu */ CheckMenuItem(menu, IDM_VIEWTOOLBOX, CHECKED_IF(::IsWindowVisible(toolBoxContainer))); CheckMenuItem(menu, IDM_VIEWCOLORPALETTE, CHECKED_IF(::IsWindowVisible(paletteWindow))); - CheckMenuItem(menu, IDM_VIEWSTATUSBAR, CHECKED_IF(::IsWindowVisible(hStatusBar))); + CheckMenuItem(menu, IDM_VIEWSTATUSBAR, CHECKED_IF(::IsWindowVisible(g_hStatusBar))); CheckMenuItem(menu, IDM_FORMATICONBAR, CHECKED_IF(::IsWindowVisible(fontsDialog))); EnableMenuItem(menu, IDM_FORMATICONBAR, ENABLED_IF(toolsModel.GetActiveTool() == TOOL_TEXT)); - CheckMenuItem(menu, IDM_VIEWSHOWGRID, CHECKED_IF(showGrid)); + CheckMenuItem(menu, IDM_VIEWSHOWGRID, CHECKED_IF(g_showGrid)); CheckMenuItem(menu, IDM_VIEWSHOWMINIATURE, CHECKED_IF(registrySettings.ShowThumbnail)); break; case 3: /* Image menu */ @@ -474,10 +474,10 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO LRESULT CMainWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { int test[] = { LOWORD(lParam) - 260, LOWORD(lParam) - 140, LOWORD(lParam) - 20 }; - if (::IsWindow(hStatusBar)) + if (::IsWindow(g_hStatusBar)) { - ::SendMessage(hStatusBar, WM_SIZE, 0, 0); - ::SendMessage(hStatusBar, SB_SETPARTS, 3, (LPARAM)&test); + ::SendMessage(g_hStatusBar, WM_SIZE, 0, 0); + ::SendMessage(g_hStatusBar, SB_SETPARTS, 3, (LPARAM)&test); } alignChildrenToMainWindow(); return 0; @@ -508,9 +508,11 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH } else if (selectionModel.m_bShow) { - selectionModel.Landing(); - selectionModel.m_bShow = FALSE; - imageModel.NotifyImageChanged(); + selectionModel.HideSelection(); + } + else + { + canvasWindow.cancelDrawing(); } break; @@ -551,11 +553,11 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH { case IDM_HELPINFO: { - HICON paintIcon = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)); + HICON paintIcon = LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON)); TCHAR infotitle[100]; TCHAR infotext[200]; - LoadString(hProgInstance, IDS_INFOTITLE, infotitle, _countof(infotitle)); - LoadString(hProgInstance, IDS_INFOTEXT, infotext, _countof(infotext)); + LoadString(g_hinstExe, IDS_INFOTITLE, infotitle, _countof(infotitle)); + LoadString(g_hinstExe, IDS_INFOTEXT, infotext, _countof(infotext)); ShellAbout(m_hWnd, infotitle, infotext, paintIcon); DeleteObject(paintIcon); break; @@ -620,13 +622,13 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH GlobalFree(pd.hDevNames); break; case IDM_FILEASWALLPAPERPLANE: - RegistrySettings::SetWallpaper(filepathname, RegistrySettings::TILED); + RegistrySettings::SetWallpaper(g_szFileName, RegistrySettings::TILED); break; case IDM_FILEASWALLPAPERCENTERED: - RegistrySettings::SetWallpaper(filepathname, RegistrySettings::CENTERED); + RegistrySettings::SetWallpaper(g_szFileName, RegistrySettings::CENTERED); break; case IDM_FILEASWALLPAPERSTRETCHED: - RegistrySettings::SetWallpaper(filepathname, RegistrySettings::STRETCHED); + RegistrySettings::SetWallpaper(g_szFileName, RegistrySettings::STRETCHED); break; case IDM_FILE1: case IDM_FILE2: @@ -640,7 +642,10 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH } case IDM_EDITUNDO: if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow)) + { + textEditWindow.PostMessage(WM_UNDO, 0, 0); break; + } if (selectionModel.m_bShow) { if (toolsModel.GetActiveTool() == TOOL_RECTSEL || @@ -668,10 +673,19 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH imageModel.Redo(); break; case IDM_EDITCOPY: + // FIXME: We should use CF_DIB in the future if (OpenClipboard()) { EmptyClipboard(); - SetClipboardData(CF_BITMAP, CopyDIBImage(selectionModel.GetBitmap())); + if (selectionModel.m_bShow) + { + selectionModel.TakeOff(); + SetClipboardData(CF_BITMAP, selectionModel.CopyBitmap()); + } + else + { + SetClipboardData(CF_BITMAP, imageModel.CopyBitmap()); + } CloseClipboard(); } break; @@ -695,7 +709,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH { case TOOL_FREESEL: case TOOL_RECTSEL: - imageModel.DeleteSelection(); + selectionModel.DeleteSelection(); break; case TOOL_TEXT: @@ -723,7 +737,11 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH { TCHAR szFileName[MAX_LONG_PATH] = _T(""); if (GetSaveFileName(szFileName, _countof(szFileName))) - SaveDIBToFile(selectionModel.GetBitmap(), szFileName, imageModel.GetDC()); + { + HBITMAP hbm = selectionModel.CopyBitmap(); + SaveDIBToFile(hbm, szFileName, imageModel.GetDC()); + ::DeleteObject(hbm); + } break; } case IDM_EDITPASTEFROM: @@ -827,8 +845,8 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH toolsModel.SetBackgroundTransparent(!toolsModel.IsBackgroundTransparent()); break; case IDM_IMAGECROP: - imageModel.PushImageForUndo(CopyDIBImage(selectionModel.GetBitmap())); - imageModel.DeleteSelection(); + imageModel.PushImageForUndo(selectionModel.CopyBitmap()); + selectionModel.HideSelection(); break; case IDM_VIEWTOOLBOX: @@ -842,8 +860,8 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH alignChildrenToMainWindow(); break; case IDM_VIEWSTATUSBAR: - registrySettings.ShowStatusBar = !::IsWindowVisible(hStatusBar); - ::ShowWindow(hStatusBar, (registrySettings.ShowStatusBar ? SW_SHOWNOACTIVATE : SW_HIDE)); + registrySettings.ShowStatusBar = !::IsWindowVisible(g_hStatusBar); + ::ShowWindow(g_hStatusBar, (registrySettings.ShowStatusBar ? SW_SHOWNOACTIVATE : SW_HIDE)); alignChildrenToMainWindow(); break; case IDM_FORMATICONBAR: @@ -859,7 +877,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH } break; case IDM_VIEWSHOWGRID: - showGrid = !showGrid; + g_showGrid = !g_showGrid; canvasWindow.Invalidate(FALSE); break; case IDM_VIEWSHOWMINIATURE: