[MSPAINT] Improve Undo/Redo and finishing tool (#4324)

- Fix Undo/Redo mechanism.
- Finish drawing when the tool is to be chanaged and when the file is to be saved.
- Add ToolBase::OnFinishDraw to virtualize finishing drawing.
- Extend bClearRedo parameter to ImageModel::Undo.
- Add ImageModel::DrawSelectionBackground and ImageModel::DeleteSelection methods.
- Fix some WM_PAINT message handling.
CORE-17969
This commit is contained in:
Katayama Hirofumi MZ 2022-01-30 12:05:23 +09:00 committed by GitHub
parent c5b029d0fc
commit 0839711566
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 313 additions and 151 deletions

View file

@ -57,7 +57,7 @@ void ImageModel::CopyPrevious()
imageSaved = FALSE; imageSaved = FALSE;
} }
void ImageModel::Undo() void ImageModel::Undo(BOOL bClearRedo)
{ {
ATLTRACE("%s: %d\n", __FUNCTION__, undoSteps); ATLTRACE("%s: %d\n", __FUNCTION__, undoSteps);
if (undoSteps > 0) if (undoSteps > 0)
@ -68,7 +68,9 @@ void ImageModel::Undo()
currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE; currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE;
SelectObject(hDrawingDC, hBms[currInd]); SelectObject(hDrawingDC, hBms[currInd]);
undoSteps--; undoSteps--;
if (redoSteps < HISTORYSIZE - 1) if (bClearRedo)
redoSteps = 0;
else if (redoSteps < HISTORYSIZE - 1)
redoSteps++; redoSteps++;
if (GetWidth() != oldWidth || GetHeight() != oldHeight) if (GetWidth() != oldWidth || GetHeight() != oldHeight)
NotifyDimensionsChanged(); NotifyDimensionsChanged();
@ -251,3 +253,29 @@ void ImageModel::RotateNTimes90Degrees(int iN)
} }
NotifyImageChanged(); NotifyImageChanged();
} }
void ImageModel::DrawSelectionBackground(COLORREF rgbBG)
{
if (toolsModel.GetActiveTool() == TOOL_FREESEL)
selectionModel.DrawBackgroundPoly(hDrawingDC, rgbBG);
else
selectionModel.DrawBackgroundRect(hDrawingDC, rgbBG);
}
void ImageModel::DeleteSelection()
{
if (selectionWindow.IsWindowVisible())
ResetToPrevious();
CopyPrevious();
if (selectionWindow.IsWindowVisible())
Undo(TRUE);
DrawSelectionBackground(paletteModel.GetBgColor());
selectionWindow.ShowWindow(SW_HIDE);
NotifyImageChanged();
}
void ImageModel::Bound(POINT& pt)
{
pt.x = max(0, min(pt.x, GetWidth()));
pt.y = max(0, min(pt.y, GetHeight()));
}

View file

@ -26,7 +26,7 @@ private:
public: public:
ImageModel(); ImageModel();
void CopyPrevious(void); void CopyPrevious(void);
void Undo(void); void Undo(BOOL bClearRedo = FALSE);
void Redo(void); void Redo(void);
void ResetToPrevious(void); void ResetToPrevious(void);
void ClearHistory(void); void ClearHistory(void);
@ -45,4 +45,7 @@ public:
void FlipHorizontally(); void FlipHorizontally();
void FlipVertically(); void FlipVertically();
void RotateNTimes90Degrees(int iN); void RotateNTimes90Degrees(int iN);
void DrawSelectionBackground(COLORREF rgbBG);
void DeleteSelection();
void Bound(POINT& pt);
}; };

View file

@ -259,7 +259,7 @@ LRESULT CImgAreaWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
} }
else else
{ {
if (drawing || ToolBase::pointSP != 0) if (drawing || ToolBase::pointSP != 0 || selectionWindow.IsWindowVisible())
cancelDrawing(); cancelDrawing();
} }
} }
@ -411,3 +411,10 @@ LRESULT CImgAreaWindow::OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam,
SetBkMode(hdc, TRANSPARENT); SetBkMode(hdc, TRANSPARENT);
return (LRESULT)GetStockObject(NULL_BRUSH); return (LRESULT)GetStockObject(NULL_BRUSH);
} }
void CImgAreaWindow::finishDrawing()
{
toolsModel.OnFinishDraw();
drawing = FALSE;
Invalidate(FALSE);
}

View file

@ -17,6 +17,10 @@ public:
{ {
} }
BOOL drawing;
void cancelDrawing();
void finishDrawing();
DECLARE_WND_CLASS_EX(_T("ImgAreaWindow"), CS_DBLCLKS, COLOR_BTNFACE) DECLARE_WND_CLASS_EX(_T("ImgAreaWindow"), CS_DBLCLKS, COLOR_BTNFACE)
BEGIN_MSG_MAP(CImgAreaWindow) BEGIN_MSG_MAP(CImgAreaWindow)
@ -40,8 +44,6 @@ public:
MESSAGE_HANDLER(WM_CTLCOLOREDIT, OnCtlColorEdit) MESSAGE_HANDLER(WM_CTLCOLOREDIT, OnCtlColorEdit)
END_MSG_MAP() END_MSG_MAP()
BOOL drawing;
private: private:
LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnEraseBkGnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnEraseBkGnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
@ -63,5 +65,4 @@ private:
LRESULT OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
void drawZoomFrame(int mouseX, int mouseY); void drawZoomFrame(int mouseX, int mouseY);
void cancelDrawing();
}; };

View file

@ -76,6 +76,10 @@ void updateLast(LONG x, LONG y)
void ToolBase::reset() void ToolBase::reset()
{ {
pointSP = 0; pointSP = 0;
start.x = start.y = last.x = last.y = -1;
selectionModel.ResetPtStack();
if (selectionWindow.IsWindow())
selectionWindow.ShowWindow(SW_HIDE);
} }
void ToolBase::OnCancelDraw() void ToolBase::OnCancelDraw()
@ -83,6 +87,11 @@ void ToolBase::OnCancelDraw()
reset(); reset();
} }
void ToolBase::OnFinishDraw()
{
reset();
}
void ToolBase::beginEvent() void ToolBase::beginEvent()
{ {
m_hdc = imageModel.GetDC(); m_hdc = imageModel.GetDC();
@ -100,48 +109,75 @@ void ToolBase::endEvent()
// TOOL_FREESEL // TOOL_FREESEL
struct FreeSelTool : ToolBase struct FreeSelTool : ToolBase
{ {
FreeSelTool() : ToolBase(TOOL_FREESEL) BOOL m_bLeftButton;
FreeSelTool() : ToolBase(TOOL_FREESEL), m_bLeftButton(FALSE)
{ {
} }
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
{
if (bLeftButton)
{ {
imageModel.CopyPrevious(); imageModel.CopyPrevious();
selectionWindow.ShowWindow(SW_HIDE); selectionWindow.ShowWindow(SW_HIDE);
selectionModel.ResetPtStack(); selectionModel.ResetPtStack();
selectionModel.PushToPtStack(x, y); selectionModel.PushToPtStack(x, y);
} }
m_bLeftButton = bLeftButton;
}
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) void OnMouseMove(BOOL bLeftButton, LONG x, LONG y)
{ {
if (selectionModel.PtStackSize() == 1) if (bLeftButton)
imageModel.CopyPrevious(); {
selectionModel.PushToPtStack(max(0, min(x, imageModel.GetWidth())), max(0, min(y, imageModel.GetHeight()))); POINT pt = { x, y };
imageModel.Bound(pt);
selectionModel.PushToPtStack(pt.x, pt.y);
imageModel.ResetToPrevious(); imageModel.ResetToPrevious();
selectionModel.DrawFramePoly(m_hdc); selectionModel.DrawFramePoly(m_hdc);
} }
}
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) void OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
{ {
selectionModel.CalculateBoundingBoxAndContents(m_hdc); if (bLeftButton)
if (selectionModel.PtStackSize() > 1)
{ {
selectionModel.DrawBackgroundPoly(m_hdc, m_bg); imageModel.ResetToPrevious();
imageModel.CopyPrevious(); if (selectionModel.PtStackSize() > 2)
{
selectionModel.DrawSelection(m_hdc); selectionModel.CalculateBoundingBoxAndContents(m_hdc);
placeSelWin(); placeSelWin();
selectionWindow.ShowWindow(SW_SHOW); selectionWindow.IsMoved(FALSE);
ForceRefreshSelectionContents(); selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
} }
else
{
imageModel.Undo(TRUE);
selectionWindow.IsMoved(FALSE);
selectionModel.ResetPtStack(); selectionModel.ResetPtStack();
selectionWindow.ShowWindow(SW_HIDE);
}
}
}
void OnFinishDraw()
{
if (m_bLeftButton)
{
selectionWindow.IsMoved(FALSE);
selectionWindow.ForceRefreshSelectionContents();
}
m_bLeftButton = FALSE;
ToolBase::OnFinishDraw();
} }
void OnCancelDraw() void OnCancelDraw()
{ {
imageModel.ResetToPrevious(); if (m_bLeftButton)
selectionModel.ResetPtStack(); imageModel.Undo(TRUE);
m_bLeftButton = FALSE;
selectionWindow.IsMoved(FALSE);
ToolBase::OnCancelDraw(); ToolBase::OnCancelDraw();
} }
}; };
@ -149,31 +185,32 @@ struct FreeSelTool : ToolBase
// TOOL_RECTSEL // TOOL_RECTSEL
struct RectSelTool : ToolBase struct RectSelTool : ToolBase
{ {
RectSelTool() : ToolBase(TOOL_RECTSEL) BOOL m_bLeftButton;
RectSelTool() : ToolBase(TOOL_RECTSEL), m_bLeftButton(FALSE)
{ {
} }
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
{ {
imageModel.CopyPrevious();
if (bLeftButton) if (bLeftButton)
{ {
imageModel.CopyPrevious(); imageModel.CopyPrevious();
selectionWindow.ShowWindow(SW_HIDE); selectionWindow.ShowWindow(SW_HIDE);
selectionModel.SetSrcRectSizeToZero(); selectionModel.SetSrcRectSizeToZero();
} }
m_bLeftButton = bLeftButton;
} }
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) void OnMouseMove(BOOL bLeftButton, LONG x, LONG y)
{ {
POINT temp;
if (bLeftButton) if (bLeftButton)
{ {
imageModel.ResetToPrevious(); imageModel.ResetToPrevious();
temp.x = max(0, min(x, imageModel.GetWidth())); POINT pt = { x, y };
temp.y = max(0, min(y, imageModel.GetHeight())); imageModel.Bound(pt);
selectionModel.SetSrcAndDestRectFromPoints(start, temp); selectionModel.SetSrcAndDestRectFromPoints(start, pt);
RectSel(m_hdc, start.x, start.y, temp.x, temp.y); RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
} }
} }
@ -182,25 +219,35 @@ struct RectSelTool : ToolBase
if (bLeftButton) if (bLeftButton)
{ {
imageModel.ResetToPrevious(); imageModel.ResetToPrevious();
if (selectionModel.IsSrcRectSizeNonzero()) if (start.x == x && start.y == y)
{ imageModel.Undo(TRUE);
selectionModel.CalculateContents(m_hdc); selectionModel.CalculateContents(m_hdc);
selectionModel.DrawBackgroundRect(m_hdc, m_bg);
imageModel.CopyPrevious();
selectionModel.DrawSelection(m_hdc);
placeSelWin(); placeSelWin();
selectionWindow.ShowWindow(SW_SHOW); selectionWindow.IsMoved(FALSE);
ForceRefreshSelectionContents(); if (selectionModel.IsSrcRectSizeNonzero())
selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
else
selectionWindow.ShowWindow(SW_HIDE);
} }
} }
void OnFinishDraw()
{
if (m_bLeftButton)
{
selectionWindow.IsMoved(FALSE);
selectionWindow.ForceRefreshSelectionContents();
}
m_bLeftButton = FALSE;
ToolBase::OnFinishDraw();
} }
void OnCancelDraw() void OnCancelDraw()
{ {
imageModel.ResetToPrevious(); if (m_bLeftButton)
selectionModel.ResetPtStack(); imageModel.Undo(TRUE);
m_bLeftButton = FALSE;
selectionWindow.IsMoved(FALSE);
ToolBase::OnCancelDraw(); ToolBase::OnCancelDraw();
} }
}; };
@ -232,8 +279,7 @@ struct GenericDrawTool : ToolBase
void OnCancelDraw() void OnCancelDraw()
{ {
OnButtonUp(FALSE, 0, 0); OnButtonUp(FALSE, 0, 0);
imageModel.Undo(); imageModel.Undo(TRUE);
selectionModel.ResetPtStack();
ToolBase::OnCancelDraw(); ToolBase::OnCancelDraw();
} }
}; };
@ -275,20 +321,29 @@ struct ColorTool : ToolBase
{ {
} }
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) void fetchColor(BOOL bLeftButton, LONG x, LONG y)
{ {
COLORREF tempColor; COLORREF rgbColor;
if (0 <= x && x < imageModel.GetWidth() && 0 <= y && y < imageModel.GetHeight()) if (0 <= x && x < imageModel.GetWidth() && 0 <= y && y < imageModel.GetHeight())
tempColor = GetPixel(m_hdc, x, y); rgbColor = GetPixel(m_hdc, x, y);
else else
tempColor = RGB(255, 255, 255); // Outside is white rgbColor = RGB(255, 255, 255); // Outside is white
if (bLeftButton) if (bLeftButton)
paletteModel.SetFgColor(tempColor); paletteModel.SetFgColor(rgbColor);
else else
paletteModel.SetBgColor(tempColor); paletteModel.SetBgColor(rgbColor);
}
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y)
{
fetchColor(bLeftButton, x, y);
}
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
{
fetchColor(bLeftButton, x, y);
toolsModel.SetActiveTool(toolsModel.GetOldActiveTool()); toolsModel.SetActiveTool(toolsModel.GetOldActiveTool());
} }
}; };
@ -368,12 +423,11 @@ struct TextTool : ToolBase
void UpdatePoint(LONG x, LONG y) void UpdatePoint(LONG x, LONG y)
{ {
POINT temp;
imageModel.ResetToPrevious(); imageModel.ResetToPrevious();
temp.x = max(0, min(x, imageModel.GetWidth())); POINT pt = { x, y };
temp.y = max(0, min(y, imageModel.GetHeight())); imageModel.Bound(pt);
selectionModel.SetSrcAndDestRectFromPoints(start, temp); selectionModel.SetSrcAndDestRectFromPoints(start, pt);
RectSel(m_hdc, start.x, start.y, temp.x, temp.y); RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
} }
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
@ -392,7 +446,7 @@ struct TextTool : ToolBase
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) void OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
{ {
imageModel.ResetToPrevious(); imageModel.Undo(TRUE);
BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow); BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow);
if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0) if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0)
@ -405,6 +459,7 @@ struct TextTool : ToolBase
textEditWindow.GetEditRect(&rc); textEditWindow.GetEditRect(&rc);
INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1); INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1);
imageModel.CopyPrevious();
Text(m_hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText, Text(m_hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText,
textEditWindow.GetFont(), style); textEditWindow.GetFont(), style);
} }
@ -451,13 +506,12 @@ struct TextTool : ToolBase
} }
} }
void OnCancelDraw() void OnFinishDraw()
{ {
imageModel.ResetToPrevious(); toolsModel.OnButtonDown(TRUE, -1, -1, TRUE);
selectionModel.ResetPtStack(); toolsModel.OnButtonUp(TRUE, -1, -1);
textEditWindow.SetWindowText(NULL); selectionWindow.IsMoved(FALSE);
textEditWindow.ShowWindow(SW_HIDE); ToolBase::OnFinishDraw();
ToolBase::OnCancelDraw();
} }
}; };
@ -481,7 +535,9 @@ struct LineTool : GenericDrawTool
// TOOL_BEZIER // TOOL_BEZIER
struct BezierTool : ToolBase struct BezierTool : ToolBase
{ {
BezierTool() : ToolBase(TOOL_BEZIER) BOOL m_bLeftButton;
BezierTool() : ToolBase(TOOL_BEZIER), m_bLeftButton(FALSE)
{ {
} }
@ -501,6 +557,7 @@ struct BezierTool : ToolBase
Bezier(m_hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], rgb, toolsModel.GetLineWidth()); Bezier(m_hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], rgb, toolsModel.GetLineWidth());
break; break;
} }
m_bLeftButton = bLeftButton;
} }
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
@ -535,10 +592,20 @@ struct BezierTool : ToolBase
void OnCancelDraw() void OnCancelDraw()
{ {
OnButtonUp(FALSE, 0, 0); OnButtonUp(FALSE, 0, 0);
imageModel.Undo(); imageModel.Undo(TRUE);
selectionModel.ResetPtStack();
ToolBase::OnCancelDraw(); ToolBase::OnCancelDraw();
} }
void OnFinishDraw()
{
if (pointSP)
{
imageModel.ResetToPrevious();
--pointSP;
draw(m_bLeftButton);
}
ToolBase::OnFinishDraw();
}
}; };
// TOOL_RECT // TOOL_RECT
@ -563,7 +630,9 @@ struct RectTool : GenericDrawTool
// TOOL_SHAPE // TOOL_SHAPE
struct ShapeTool : ToolBase struct ShapeTool : ToolBase
{ {
ShapeTool() : ToolBase(TOOL_SHAPE) BOOL m_bLeftButton;
ShapeTool() : ToolBase(TOOL_SHAPE), m_bLeftButton(FALSE)
{ {
} }
@ -576,6 +645,7 @@ struct ShapeTool : ToolBase
else else
Poly(m_hdc, pointStack, pointSP + 1, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), bClosed, FALSE); Poly(m_hdc, pointStack, pointSP + 1, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), bClosed, FALSE);
} }
m_bLeftButton = bLeftButton;
} }
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
@ -631,10 +701,25 @@ struct ShapeTool : ToolBase
void OnCancelDraw() void OnCancelDraw()
{ {
imageModel.ResetToPrevious(); imageModel.Undo(TRUE);
selectionModel.ResetPtStack();
ToolBase::OnCancelDraw(); ToolBase::OnCancelDraw();
} }
void OnFinishDraw()
{
if (pointSP)
{
imageModel.ResetToPrevious();
--pointSP;
draw(m_bLeftButton, -1, -1, TRUE);
pointSP = 0;
}
else
{
imageModel.Undo(TRUE);
}
ToolBase::OnFinishDraw();
}
}; };
// TOOL_ELLIPSE // TOOL_ELLIPSE

View file

@ -19,9 +19,9 @@ LRESULT CPaletteWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& b
HBRUSH oldBrush; HBRUSH oldBrush;
int i, a, b; int i, a, b;
DefWindowProc(WM_PAINT, wParam, lParam); PAINTSTRUCT ps;
HDC hDC = BeginPaint(&ps);
HDC hDC = GetDC();
for(b = 2; b < 30; b++) for(b = 2; b < 30; b++)
for(a = 2; a < 29; a++) for(a = 2; a < 29; a++)
if ((a + b) % 2 == 1) if ((a + b) % 2 == 1)
@ -54,7 +54,7 @@ LRESULT CPaletteWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& b
DeleteObject(SelectObject(hDC, oldBrush)); DeleteObject(SelectObject(hDC, oldBrush));
DeleteObject(SelectObject(hDC, oldPen)); DeleteObject(SelectObject(hDC, oldPen));
} }
ReleaseDC(hDC); EndPaint(&ps);
return 0; return 0;
} }

View file

@ -54,14 +54,13 @@ ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
return TRUE; return TRUE;
} }
void void CSelectionWindow::ForceRefreshSelectionContents()
ForceRefreshSelectionContents()
{ {
if (::IsWindowVisible(selectionWindow)) if (::IsWindowVisible(selectionWindow))
{ {
selectionWindow.SendMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(0, 0)); imageModel.ResetToPrevious();
selectionWindow.SendMessage(WM_MOUSEMOVE, 0, MAKELPARAM(0, 0)); imageModel.DrawSelectionBackground(m_rgbBack);
selectionWindow.SendMessage(WM_LBUTTONUP, 0, MAKELPARAM(0, 0)); selectionModel.DrawSelection(imageModel.GetDC(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
} }
} }
@ -90,16 +89,16 @@ int CSelectionWindow::IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeig
LRESULT CSelectionWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CSelectionWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
DefWindowProc(WM_PAINT, wParam, lParam); PAINTSTRUCT ps;
HDC hDC = BeginPaint(&ps);
if (!m_bMoving) if (!m_bMoving)
{ {
HDC hDC = GetDC();
SelectionFrame(hDC, 1, 1, SelectionFrame(hDC, 1, 1,
Zoomed(selectionModel.GetDestRectWidth()) + (GRIP_SIZE * 2) - 1, Zoomed(selectionModel.GetDestRectWidth()) + (GRIP_SIZE * 2) - 1,
Zoomed(selectionModel.GetDestRectHeight()) + (GRIP_SIZE * 2) - 1, Zoomed(selectionModel.GetDestRectHeight()) + (GRIP_SIZE * 2) - 1,
GetSysColor(COLOR_HIGHLIGHT)); GetSysColor(COLOR_HIGHLIGHT));
ReleaseDC(hDC);
} }
EndPaint(&ps);
return 0; return 0;
} }
@ -145,6 +144,7 @@ LRESULT CSelectionWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam,
scrlClientWindow.SendMessage(WM_PAINT, 0, 0); scrlClientWindow.SendMessage(WM_PAINT, 0, 0);
imageArea.InvalidateRect(NULL, FALSE); imageArea.InvalidateRect(NULL, FALSE);
imageArea.SendMessage(WM_PAINT, 0, 0); imageArea.SendMessage(WM_PAINT, 0, 0);
m_rgbBack = paletteModel.GetBgColor();
return 0; return 0;
} }
@ -153,6 +153,7 @@ LRESULT CSelectionWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, B
if (m_bMoving) if (m_bMoving)
{ {
imageModel.ResetToPrevious(); imageModel.ResetToPrevious();
imageModel.DrawSelectionBackground(m_rgbBack);
m_ptFrac.x += GET_X_LPARAM(lParam) - m_ptPos.x; m_ptFrac.x += GET_X_LPARAM(lParam) - m_ptPos.x;
m_ptFrac.y += GET_Y_LPARAM(lParam) - m_ptPos.y; m_ptFrac.y += GET_Y_LPARAM(lParam) - m_ptPos.y;
m_ptDelta.x += UnZoomed(m_ptFrac.x); m_ptDelta.x += UnZoomed(m_ptFrac.x);
@ -173,17 +174,10 @@ LRESULT CSelectionWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, B
strSize.Format(_T("%ld x %ld"), selectionModel.GetDestRectWidth(), selectionModel.GetDestRectHeight()); strSize.Format(_T("%ld x %ld"), selectionModel.GetDestRectWidth(), selectionModel.GetDestRectHeight());
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize); SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
if (toolsModel.GetActiveTool() == TOOL_TEXT)
{
selectionModel.DrawTextToolText(imageModel.GetDC(), paletteModel.GetFgColor(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
}
else
{
if (m_iAction != ACTION_MOVE) if (m_iAction != ACTION_MOVE)
selectionModel.DrawSelectionStretched(imageModel.GetDC()); selectionModel.DrawSelectionStretched(imageModel.GetDC());
else else
selectionModel.DrawSelection(imageModel.GetDC(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent()); selectionModel.DrawSelection(imageModel.GetDC(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
}
imageArea.InvalidateRect(NULL, FALSE); imageArea.InvalidateRect(NULL, FALSE);
imageArea.SendMessage(WM_PAINT, 0, 0); imageArea.SendMessage(WM_PAINT, 0, 0);
m_ptPos.x = GET_X_LPARAM(lParam); m_ptPos.x = GET_X_LPARAM(lParam);
@ -203,26 +197,26 @@ LRESULT CSelectionWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, B
return 0; return 0;
} }
LRESULT CSelectionWindow::OnMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
m_bMoved = TRUE;
return 0;
}
LRESULT CSelectionWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CSelectionWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if (m_bMoving) if (m_bMoving)
{ {
m_bMoving = FALSE; m_bMoving = FALSE;
ReleaseCapture(); ReleaseCapture();
if (m_iAction != ACTION_MOVE) if (m_iAction != ACTION_MOVE && toolsModel.GetActiveTool() != TOOL_TEXT)
{
if (toolsModel.GetActiveTool() == TOOL_TEXT)
{
// FIXME: What to do?
}
else
{ {
imageModel.Undo();
imageModel.DrawSelectionBackground(m_rgbBack);
selectionModel.ScaleContentsToFit(); selectionModel.ScaleContentsToFit();
} imageModel.CopyPrevious();
} }
placeSelWin(); placeSelWin();
ShowWindow(SW_HIDE);
ShowWindow(SW_SHOW);
} }
return 0; return 0;
} }
@ -234,10 +228,10 @@ LRESULT CSelectionWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lPar
m_bMoving = FALSE; m_bMoving = FALSE;
if (m_iAction == ACTION_MOVE) if (m_iAction == ACTION_MOVE)
{ {
// FIXME: dirty hack if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
imageArea.cancelDrawing();
else
placeSelWin(); placeSelWin();
imageModel.Undo();
imageModel.Undo();
} }
else else
{ {
@ -262,23 +256,16 @@ LRESULT CSelectionWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
LRESULT CSelectionWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CSelectionWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if (toolsModel.GetActiveTool() == TOOL_TEXT)
ForceRefreshSelectionContents();
return 0; return 0;
} }
LRESULT CSelectionWindow::OnToolsModelSettingsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CSelectionWindow::OnToolsModelSettingsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if (toolsModel.GetActiveTool() == TOOL_FREESEL ||
toolsModel.GetActiveTool() == TOOL_RECTSEL ||
toolsModel.GetActiveTool() == TOOL_TEXT)
ForceRefreshSelectionContents();
return 0; return 0;
} }
LRESULT CSelectionWindow::OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CSelectionWindow::OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
ForceRefreshSelectionContents();
return 0; return 0;
} }

View file

@ -12,6 +12,15 @@
class CSelectionWindow : public CWindowImpl<CSelectionWindow> class CSelectionWindow : public CWindowImpl<CSelectionWindow>
{ {
public: public:
CSelectionWindow() : m_bMoved(FALSE)
{
}
BOOL IsMoved() const { return m_bMoved; }
void IsMoved(BOOL bMoved) { m_bMoved = bMoved; }
void ForceRefreshSelectionContents();
DECLARE_WND_CLASS_EX(_T("Selection"), CS_DBLCLKS, COLOR_BTNFACE) DECLARE_WND_CLASS_EX(_T("Selection"), CS_DBLCLKS, COLOR_BTNFACE)
BEGIN_MSG_MAP(CSelectionWindow) BEGIN_MSG_MAP(CSelectionWindow)
@ -24,6 +33,7 @@ public:
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel) MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_MOVE, OnMove)
MESSAGE_HANDLER(WM_PALETTEMODELCOLORCHANGED, OnPaletteModelColorChanged) MESSAGE_HANDLER(WM_PALETTEMODELCOLORCHANGED, OnPaletteModelColorChanged)
MESSAGE_HANDLER(WM_TOOLSMODELSETTINGSCHANGED, OnToolsModelSettingsChanged) MESSAGE_HANDLER(WM_TOOLSMODELSETTINGSCHANGED, OnToolsModelSettingsChanged)
MESSAGE_HANDLER(WM_TOOLSMODELZOOMCHANGED, OnToolsModelZoomChanged) MESSAGE_HANDLER(WM_TOOLSMODELZOOMCHANGED, OnToolsModelZoomChanged)
@ -47,14 +57,17 @@ public:
LRESULT OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
private: private:
static const LPCTSTR m_lpszCursorLUT[9]; static const LPCTSTR m_lpszCursorLUT[9];
BOOL m_bMoved;
BOOL m_bMoving; BOOL m_bMoving;
int m_iAction; int m_iAction;
POINT m_ptPos; POINT m_ptPos;
POINT m_ptFrac; POINT m_ptFrac;
POINT m_ptDelta; POINT m_ptDelta;
COLORREF m_rgbBack;
int IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight); int IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight);
}; };

View file

@ -337,11 +337,6 @@ LONG SelectionModel::GetDestRectTop() const
return m_rcDest.top; return m_rcDest.top;
} }
void SelectionModel::DrawTextToolText(HDC hDCImage, COLORREF crFg, COLORREF crBg, BOOL bBgTransparent)
{
Text(hDCImage, m_rcDest.left, m_rcDest.top, m_rcDest.right, m_rcDest.bottom, crFg, crBg, textToolText, hfontTextFont, bBgTransparent);
}
void SelectionModel::NotifyRefreshNeeded() void SelectionModel::NotifyRefreshNeeded()
{ {
selectionWindow.SendMessage(WM_SELECTIONMODELREFRESHNEEDED); selectionWindow.SendMessage(WM_SELECTIONMODELREFRESHNEEDED);

View file

@ -66,7 +66,6 @@ public:
LONG GetDestRectLeft() const; LONG GetDestRectLeft() const;
LONG GetDestRectTop() const; LONG GetDestRectTop() const;
void GetRect(LPRECT prc) const; void GetRect(LPRECT prc) const;
void DrawTextToolText(HDC hDCImage, COLORREF crFg, COLORREF crBg, BOOL bBgTransparent = FALSE);
private: private:
SelectionModel(const SelectionModel&); SelectionModel(const SelectionModel&);

View file

@ -33,12 +33,11 @@ LRESULT CToolSettingsWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam,
LRESULT CToolSettingsWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CToolSettingsWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
PAINTSTRUCT ps;
RECT rect1 = { 0, 0, 42, 66 }; RECT rect1 = { 0, 0, 42, 66 };
RECT rect2 = { 0, 70, 42, 136 }; RECT rect2 = { 0, 70, 42, 136 };
DefWindowProc(WM_PAINT, wParam, lParam); HDC hdc = BeginPaint(&ps);
HDC hdc = GetDC();
DrawEdge(hdc, &rect1, BDR_SUNKENOUTER, (toolsModel.GetActiveTool() == TOOL_ZOOM) ? BF_RECT : BF_RECT | BF_MIDDLE); DrawEdge(hdc, &rect1, BDR_SUNKENOUTER, (toolsModel.GetActiveTool() == TOOL_ZOOM) ? BF_RECT : BF_RECT | BF_MIDDLE);
DrawEdge(hdc, &rect2, (toolsModel.GetActiveTool() >= TOOL_RECT) ? BDR_SUNKENOUTER : 0, BF_RECT | BF_MIDDLE); DrawEdge(hdc, &rect2, (toolsModel.GetActiveTool() >= TOOL_RECT) ? BDR_SUNKENOUTER : 0, BF_RECT | BF_MIDDLE);
switch (toolsModel.GetActiveTool()) switch (toolsModel.GetActiveTool())
@ -181,7 +180,7 @@ LRESULT CToolSettingsWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
case TOOL_PEN: case TOOL_PEN:
break; break;
} }
ReleaseDC(hdc); EndPaint(&ps);
return 0; return 0;
} }

View file

@ -85,6 +85,11 @@ TOOLTYPE ToolsModel::GetOldActiveTool() const
void ToolsModel::SetActiveTool(TOOLTYPE nActiveTool) void ToolsModel::SetActiveTool(TOOLTYPE nActiveTool)
{ {
OnFinishDraw();
if (m_activeTool == nActiveTool)
return;
switch (m_activeTool) switch (m_activeTool)
{ {
case TOOL_FREESEL: case TOOL_FREESEL:
@ -92,15 +97,7 @@ void ToolsModel::SetActiveTool(TOOLTYPE nActiveTool)
case TOOL_RUBBER: case TOOL_RUBBER:
case TOOL_COLOR: case TOOL_COLOR:
case TOOL_ZOOM: case TOOL_ZOOM:
break;
case TOOL_TEXT: case TOOL_TEXT:
if (nActiveTool != TOOL_TEXT)
{
// Finish the text
OnButtonDown(TRUE, -1, -1, TRUE);
OnButtonUp(TRUE, -1, -1);
}
break; break;
default: default:
@ -171,7 +168,9 @@ void ToolsModel::NotifyToolChanged()
void ToolsModel::NotifyToolSettingsChanged() void ToolsModel::NotifyToolSettingsChanged()
{ {
if (toolSettingsWindow.IsWindow())
toolSettingsWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED); toolSettingsWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
if (selectionWindow.IsWindow())
selectionWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED); selectionWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
if (textEditWindow.IsWindow()) if (textEditWindow.IsWindow())
textEditWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED); textEditWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
@ -179,6 +178,7 @@ void ToolsModel::NotifyToolSettingsChanged()
void ToolsModel::NotifyZoomChanged() void ToolsModel::NotifyZoomChanged()
{ {
if (toolSettingsWindow.IsWindow())
toolSettingsWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED); toolSettingsWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
if (textEditWindow.IsWindow()) if (textEditWindow.IsWindow())
textEditWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED); textEditWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
@ -212,11 +212,20 @@ void ToolsModel::OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
void ToolsModel::OnCancelDraw() void ToolsModel::OnCancelDraw()
{ {
ATLTRACE("ToolsModel::OnCancelDraw()\n");
m_pToolObject->beginEvent(); m_pToolObject->beginEvent();
m_pToolObject->OnCancelDraw(); m_pToolObject->OnCancelDraw();
m_pToolObject->endEvent(); m_pToolObject->endEvent();
} }
void ToolsModel::OnFinishDraw()
{
ATLTRACE("ToolsModel::OnFinishDraw()\n");
m_pToolObject->beginEvent();
m_pToolObject->OnFinishDraw();
m_pToolObject->endEvent();
}
void ToolsModel::resetTool() void ToolsModel::resetTool()
{ {
m_pToolObject->reset(); m_pToolObject->reset();

View file

@ -60,6 +60,7 @@ struct ToolBase
} }
virtual void OnCancelDraw(); virtual void OnCancelDraw();
virtual void OnFinishDraw();
void beginEvent(); void beginEvent();
void endEvent(); void endEvent();
@ -110,6 +111,7 @@ public:
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y); void OnMouseMove(BOOL bLeftButton, LONG x, LONG y);
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y); void OnButtonUp(BOOL bLeftButton, LONG x, LONG y);
void OnCancelDraw(); void OnCancelDraw();
void OnFinishDraw();
void resetTool(); void resetTool();
void selectAll(); void selectAll();

View file

@ -89,6 +89,8 @@ void CMainWindow::alignChildrenToMainWindow()
void CMainWindow::saveImage(BOOL overwrite) void CMainWindow::saveImage(BOOL overwrite)
{ {
imageArea.finishDrawing();
if (isAFile && overwrite) if (isAFile && overwrite)
{ {
imageModel.SaveImage(filepathname); imageModel.SaveImage(filepathname);
@ -156,7 +158,7 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window)
placeSelWin(); placeSelWin();
selectionWindow.ShowWindow(SW_SHOW); selectionWindow.ShowWindow(SW_SHOW);
ForceRefreshSelectionContents(); selectionWindow.ForceRefreshSelectionContents();
} }
LRESULT CMainWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CMainWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@ -238,6 +240,8 @@ LRESULT CMainWindow::OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
BOOL CMainWindow::ConfirmSave() BOOL CMainWindow::ConfirmSave()
{ {
imageArea.finishDrawing();
if (imageModel.IsImageSaved()) if (imageModel.IsImageSaved())
return TRUE; return TRUE;
@ -407,14 +411,7 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
} }
else else
{ {
switch (toolsModel.GetActiveTool())
{
case TOOL_SHAPE: case TOOL_BEZIER:
imageArea.SendMessage(nMsg, wParam, lParam); imageArea.SendMessage(nMsg, wParam, lParam);
break;
default:
break;
}
} }
} }
return 0; return 0;
@ -430,6 +427,13 @@ LRESULT CMainWindow::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lParam, B
LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
// Disable commands while dragging mouse
if (imageArea.drawing && ::GetCapture())
{
ATLTRACE("locking!\n");
return 0;
}
switch (LOWORD(wParam)) switch (LOWORD(wParam))
{ {
case IDM_HELPINFO: case IDM_HELPINFO:
@ -531,12 +535,31 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
case IDM_EDITUNDO: case IDM_EDITUNDO:
if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow)) if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
break; break;
if (selectionWindow.IsWindowVisible())
{
if (toolsModel.GetActiveTool() == TOOL_RECTSEL ||
toolsModel.GetActiveTool() == TOOL_FREESEL)
{
imageArea.cancelDrawing();
break;
}
}
if (ToolBase::pointSP != 0) // drawing something?
{
imageArea.cancelDrawing();
break;
}
imageModel.Undo(); imageModel.Undo();
imageArea.Invalidate(FALSE); imageArea.Invalidate(FALSE);
break; break;
case IDM_EDITREDO: case IDM_EDITREDO:
if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow)) if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
break; break;
if (ToolBase::pointSP != 0) // drawing something?
{
imageArea.finishDrawing();
break;
}
imageModel.Redo(); imageModel.Redo();
imageArea.Invalidate(FALSE); imageArea.Invalidate(FALSE);
break; break;
@ -562,8 +585,19 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
break; break;
case IDM_EDITDELETESELECTION: case IDM_EDITDELETESELECTION:
{ {
/* remove selection window and already painted content using undo */ switch (toolsModel.GetActiveTool())
imageModel.Undo(); {
case TOOL_FREESEL:
case TOOL_RECTSEL:
imageModel.DeleteSelection();
break;
case TOOL_TEXT:
imageArea.cancelDrawing();
break;
default:
break;
}
break; break;
} }
case IDM_EDITSELECTALL: case IDM_EDITSELECTALL: