mirror of
https://github.com/reactos/reactos.git
synced 2024-12-03 00:13:32 +08:00
[MSPAINT] Improve Undo/Redo handling of selection (#6035)
Consistent behavior of the application. - Add ShiftPtStack and BuildMaskFromPtStack helper functions. - Move some codes of selectionModel to mouse.cpp. CORE-19226
This commit is contained in:
parent
ab0119c61f
commit
b8598e095d
@ -648,9 +648,9 @@ LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
||||
|
||||
LRESULT CCanvasWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
if (wParam == VK_ESCAPE && ::GetCapture() == m_hWnd)
|
||||
if (wParam == VK_ESCAPE)
|
||||
{
|
||||
cancelDrawing();
|
||||
OnEndDraw(TRUE);
|
||||
::ReleaseCapture();
|
||||
m_nMouseDownMsg = 0;
|
||||
m_hitCanvasSizeBox = HIT_NONE;
|
||||
@ -698,19 +698,10 @@ LRESULT CCanvasWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::cancelDrawing()
|
||||
VOID CCanvasWindow::OnEndDraw(BOOL bCancel)
|
||||
{
|
||||
selectionModel.ClearColorImage();
|
||||
selectionModel.ClearMaskImage();
|
||||
m_drawing = FALSE;
|
||||
toolsModel.OnEndDraw(TRUE);
|
||||
Invalidate(FALSE);
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::finishDrawing()
|
||||
{
|
||||
toolsModel.OnEndDraw(FALSE);
|
||||
m_drawing = FALSE;
|
||||
toolsModel.OnEndDraw(bCancel);
|
||||
Invalidate(FALSE);
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,7 @@ public:
|
||||
|
||||
BOOL m_drawing;
|
||||
|
||||
VOID cancelDrawing();
|
||||
VOID finishDrawing();
|
||||
VOID OnEndDraw(BOOL bCancel);
|
||||
VOID updateScrollRange();
|
||||
VOID updateScrollPos(INT x = 0, INT y = 0);
|
||||
|
||||
|
@ -164,8 +164,13 @@ void ImageModel::PushImageForUndo(const RECT& rcPartial)
|
||||
part.m_bPartial = TRUE;
|
||||
part.m_rcPart = rcPartial;
|
||||
|
||||
CRect rcImage = { 0, 0, GetWidth(), GetHeight() };
|
||||
CRect& rc = part.m_rcPart;
|
||||
if (!rc.IntersectRect(rc, rcImage))
|
||||
rc.SetRect(-1, -1, 0, 0);
|
||||
|
||||
HBITMAP hbmMaster = LockBitmap();
|
||||
part.m_hbmImage = getSubImage(hbmMaster, rcPartial);
|
||||
part.m_hbmImage = getSubImage(hbmMaster, rc);
|
||||
UnlockBitmap(hbmMaster);
|
||||
|
||||
PushDone();
|
||||
@ -351,16 +356,3 @@ void ImageModel::UnlockBitmap(HBITMAP hbmLocked)
|
||||
m_hbmMaster = hbmLocked;
|
||||
m_hbmOld = ::SelectObject(m_hDrawingDC, m_hbmMaster); // Re-select
|
||||
}
|
||||
|
||||
void ImageModel::SelectionClone(BOOL bUndoable)
|
||||
{
|
||||
if (!selectionModel.m_bShow || selectionModel.m_rc.IsRectEmpty())
|
||||
return;
|
||||
|
||||
if (bUndoable)
|
||||
PushImageForUndo();
|
||||
|
||||
selectionModel.DrawSelection(m_hDrawingDC, paletteModel.GetBgColor(),
|
||||
toolsModel.IsBackgroundTransparent());
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ public:
|
||||
void NotifyImageChanged();
|
||||
BOOL IsBlackAndWhite();
|
||||
void PushBlackAndWhite();
|
||||
void SelectionClone(BOOL bUndoable = TRUE);
|
||||
|
||||
protected:
|
||||
HDC m_hDrawingDC; // The device context for this class
|
||||
|
@ -406,7 +406,7 @@ void CMainWindow::alignChildrenToMainWindow()
|
||||
|
||||
void CMainWindow::saveImage(BOOL overwrite)
|
||||
{
|
||||
canvasWindow.finishDrawing();
|
||||
canvasWindow.OnEndDraw(FALSE);
|
||||
|
||||
// Is the extension not supported?
|
||||
PWCHAR pchDotExt = PathFindExtensionW(g_szFileName);
|
||||
@ -606,7 +606,7 @@ LRESULT CMainWindow::OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
||||
|
||||
BOOL CMainWindow::ConfirmSave()
|
||||
{
|
||||
canvasWindow.finishDrawing();
|
||||
canvasWindow.OnEndDraw(FALSE);
|
||||
|
||||
if (imageModel.IsImageSaved())
|
||||
return TRUE;
|
||||
@ -693,8 +693,6 @@ BOOL CMainWindow::CanUndo() const
|
||||
return (BOOL)textEditWindow.SendMessage(EM_CANUNDO);
|
||||
if (selectionModel.m_bShow && toolsModel.IsSelection())
|
||||
return TRUE;
|
||||
if (ToolBase::s_pointSP != 0)
|
||||
return TRUE;
|
||||
return imageModel.CanUndo();
|
||||
}
|
||||
|
||||
@ -702,8 +700,6 @@ BOOL CMainWindow::CanRedo() const
|
||||
{
|
||||
if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
|
||||
return FALSE; // There is no "WM_REDO" in EDIT control
|
||||
if (ToolBase::s_pointSP != 0)
|
||||
return TRUE;
|
||||
return imageModel.CanRedo();
|
||||
}
|
||||
|
||||
@ -802,29 +798,11 @@ LRESULT CMainWindow::OnGetMinMaxInfo(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
|
||||
|
||||
LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
HWND hwndCapture;
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_ESCAPE:
|
||||
hwndCapture = GetCapture();
|
||||
if (hwndCapture)
|
||||
{
|
||||
if (canvasWindow.m_hWnd == hwndCapture ||
|
||||
fullscreenWindow.m_hWnd == hwndCapture)
|
||||
{
|
||||
::SendMessageW(hwndCapture, nMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
else if (selectionModel.m_bShow)
|
||||
{
|
||||
selectionModel.HideSelection();
|
||||
}
|
||||
else
|
||||
{
|
||||
canvasWindow.cancelDrawing();
|
||||
}
|
||||
canvasWindow.PostMessage(nMsg, wParam, lParam);
|
||||
break;
|
||||
|
||||
case VK_LEFT:
|
||||
selectionModel.moveSelection(-1, 0);
|
||||
break;
|
||||
@ -932,7 +910,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
||||
GlobalFree(pd.hDevNames);
|
||||
break;
|
||||
case IDM_FILESEND:
|
||||
canvasWindow.finishDrawing();
|
||||
canvasWindow.OnEndDraw(FALSE);
|
||||
if (!OpenMailer(m_hWnd, g_szFileName))
|
||||
{
|
||||
ShowError(IDS_CANTSENDMAIL);
|
||||
@ -963,7 +941,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
||||
textEditWindow.PostMessage(WM_UNDO, 0, 0);
|
||||
break;
|
||||
}
|
||||
canvasWindow.finishDrawing();
|
||||
canvasWindow.OnEndDraw(FALSE);
|
||||
imageModel.Undo();
|
||||
break;
|
||||
case IDM_EDITREDO:
|
||||
@ -972,7 +950,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
||||
// There is no "WM_REDO" in EDIT control
|
||||
break;
|
||||
}
|
||||
canvasWindow.finishDrawing();
|
||||
canvasWindow.OnEndDraw(FALSE);
|
||||
imageModel.Redo();
|
||||
break;
|
||||
case IDM_EDITCOPY:
|
||||
@ -1087,7 +1065,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
||||
break;
|
||||
|
||||
case TOOL_TEXT:
|
||||
canvasWindow.cancelDrawing();
|
||||
canvasWindow.OnEndDraw(TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -9,9 +9,11 @@
|
||||
#include "precomp.h"
|
||||
#include <atlalloc.h>
|
||||
|
||||
SIZE_T ToolBase::s_pointSP = 0;
|
||||
static SIZE_T s_maxPointSP = 0;
|
||||
static CHeapPtr<POINT, CLocalAllocator> s_pointStack;
|
||||
static SIZE_T s_pointSP = 0;
|
||||
static CHeapPtr<POINT, CLocalAllocator> s_pointsAllocated;
|
||||
static POINT s_staticPointStack[512]; // 512 is enough
|
||||
static SIZE_T s_maxPointSP = _countof(s_staticPointStack);
|
||||
static LPPOINT s_pointStack = s_staticPointStack;
|
||||
static POINT g_ptStart, g_ptEnd;
|
||||
|
||||
/* FUNCTIONS ********************************************************/
|
||||
@ -69,13 +71,50 @@ void getBoundaryOfPtStack(RECT& rcBoundary, INT cPoints, const POINT *pPoints)
|
||||
rcBoundary = rc;
|
||||
}
|
||||
|
||||
void ShiftPtStack(INT dx, INT dy)
|
||||
{
|
||||
for (SIZE_T i = 0; i < s_pointSP; ++i)
|
||||
{
|
||||
POINT& pt = s_pointStack[i];
|
||||
pt.x += dx;
|
||||
pt.y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
void BuildMaskFromPtStack()
|
||||
{
|
||||
CRect rc;
|
||||
getBoundaryOfPtStack(rc, s_pointSP, s_pointStack);
|
||||
|
||||
ShiftPtStack(-rc.left, -rc.top);
|
||||
|
||||
HDC hdcMem = ::CreateCompatibleDC(NULL);
|
||||
HBITMAP hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
|
||||
HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmMask);
|
||||
::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
|
||||
HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
|
||||
HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
|
||||
::Polygon(hdcMem, s_pointStack, s_pointSP);
|
||||
::SelectObject(hdcMem, hbrOld);
|
||||
::SelectObject(hdcMem, hPenOld);
|
||||
::SelectObject(hdcMem, hbmOld);
|
||||
::DeleteDC(hdcMem);
|
||||
|
||||
selectionModel.setMask(rc, hbmMask);
|
||||
}
|
||||
|
||||
void ToolBase::reset()
|
||||
{
|
||||
if (s_pointStack != s_staticPointStack)
|
||||
{
|
||||
s_pointsAllocated.Free();
|
||||
s_pointStack = s_staticPointStack;
|
||||
s_maxPointSP = _countof(s_staticPointStack);
|
||||
}
|
||||
|
||||
s_pointSP = 0;
|
||||
g_ptEnd = g_ptStart = { -1, -1 };
|
||||
|
||||
selectionModel.ResetPtStack();
|
||||
|
||||
if (selectionModel.m_bShow)
|
||||
{
|
||||
selectionModel.Landing();
|
||||
@ -103,16 +142,20 @@ void ToolBase::endEvent()
|
||||
|
||||
void ToolBase::pushToPtStack(LONG x, LONG y)
|
||||
{
|
||||
if (s_pointSP >= s_maxPointSP)
|
||||
if (s_pointSP + 1 >= s_maxPointSP)
|
||||
{
|
||||
SIZE_T newMax = s_maxPointSP + 512;
|
||||
SIZE_T cbNew = newMax * sizeof(POINT);
|
||||
if (!s_pointStack.ReallocateBytes(cbNew))
|
||||
if (!s_pointsAllocated.ReallocateBytes(cbNew))
|
||||
{
|
||||
ATLTRACE("%d, %d, %d\n", (INT)s_pointSP, (INT)s_maxPointSP, (INT)cbNew);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_pointStack == s_staticPointStack)
|
||||
CopyMemory(s_pointsAllocated, s_staticPointStack, s_pointSP * sizeof(POINT));
|
||||
|
||||
s_pointStack = s_pointsAllocated;
|
||||
s_maxPointSP = newMax;
|
||||
}
|
||||
|
||||
@ -327,12 +370,13 @@ struct SmoothDrawTool : ToolBase
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectionBaseTool : SmoothDrawTool
|
||||
struct SelectionBaseTool : ToolBase
|
||||
{
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
BOOL m_bCtrlKey = FALSE;
|
||||
BOOL m_bShiftKey = FALSE;
|
||||
BOOL m_bDrawing = FALSE;
|
||||
BOOL m_bNoDrawBack = FALSE;
|
||||
HITTEST m_hitSelection = HIT_NONE;
|
||||
|
||||
BOOL isRectSelect() const
|
||||
@ -342,13 +386,19 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
if (!selectionModel.IsLanded())
|
||||
selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
|
||||
if (selectionModel.IsLanded() || !selectionModel.m_bShow)
|
||||
return;
|
||||
|
||||
if (!m_bNoDrawBack)
|
||||
selectionModel.DrawBackground(hdc, selectionModel.m_rgbBack);
|
||||
|
||||
selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnCanvas(HDC hdc) override
|
||||
{
|
||||
selectionModel.drawFrameOnCanvas(hdc);
|
||||
if (m_bDrawing || selectionModel.m_bShow)
|
||||
selectionModel.drawFrameOnCanvas(hdc);
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
@ -374,12 +424,14 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
if (hit != HIT_NONE) // Dragging of selection started?
|
||||
{
|
||||
if (m_bCtrlKey || m_bShiftKey)
|
||||
imageModel.SelectionClone();
|
||||
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
|
||||
}
|
||||
m_hitSelection = hit;
|
||||
selectionModel.m_ptHit = pt;
|
||||
selectionModel.TakeOff();
|
||||
|
||||
m_bNoDrawBack |= (m_bCtrlKey || m_bShiftKey);
|
||||
imageModel.NotifyImageChanged();
|
||||
return;
|
||||
}
|
||||
@ -394,8 +446,8 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionModel.ResetPtStack();
|
||||
selectionModel.PushToPtStack(pt);
|
||||
s_pointSP = 0;
|
||||
pushToPtStack(pt.x, pt.y);
|
||||
}
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
@ -411,18 +463,22 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
if (m_hitSelection != HIT_NONE) // Now dragging selection?
|
||||
{
|
||||
if (m_bShiftKey)
|
||||
imageModel.SelectionClone(m_bShiftKey);
|
||||
toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
|
||||
|
||||
selectionModel.Dragging(m_hitSelection, pt);
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (isRectSelect() && ::GetKeyState(VK_SHIFT) < 0)
|
||||
regularize(g_ptStart.x, g_ptStart.y, pt.x, pt.y);
|
||||
|
||||
imageModel.Clamp(pt);
|
||||
|
||||
if (isRectSelect())
|
||||
selectionModel.SetRectFromPoints(g_ptStart, pt);
|
||||
else
|
||||
selectionModel.PushToPtStack(pt);
|
||||
pushToPtStack(pt.x, pt.y);
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
@ -438,13 +494,20 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
|
||||
if (m_hitSelection != HIT_NONE) // Dragging of selection ended?
|
||||
{
|
||||
if (m_bShiftKey)
|
||||
toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
|
||||
|
||||
selectionModel.Dragging(m_hitSelection, pt);
|
||||
m_hitSelection = HIT_NONE;
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (isRectSelect() && ::GetKeyState(VK_SHIFT) < 0)
|
||||
regularize(g_ptStart.x, g_ptStart.y, pt.x, pt.y);
|
||||
|
||||
imageModel.Clamp(pt);
|
||||
|
||||
if (isRectSelect())
|
||||
{
|
||||
selectionModel.SetRectFromPoints(g_ptStart, pt);
|
||||
@ -452,18 +515,19 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectionModel.PtStackSize() > 2)
|
||||
if (s_pointSP > 2)
|
||||
{
|
||||
selectionModel.BuildMaskFromPtStack();
|
||||
BuildMaskFromPtStack();
|
||||
selectionModel.m_bShow = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionModel.ResetPtStack();
|
||||
s_pointSP = 0;
|
||||
selectionModel.m_bShow = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
m_bNoDrawBack = FALSE;
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
@ -475,6 +539,7 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
else
|
||||
selectionModel.Landing();
|
||||
|
||||
m_bDrawing = FALSE;
|
||||
m_hitSelection = HIT_NONE;
|
||||
ToolBase::OnEndDraw(bCancel);
|
||||
}
|
||||
@ -488,34 +553,21 @@ struct SelectionBaseTool : SmoothDrawTool
|
||||
// TOOL_FREESEL
|
||||
struct FreeSelTool : SelectionBaseTool
|
||||
{
|
||||
void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
|
||||
{
|
||||
if (m_bShiftKey && !m_bCtrlKey)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
SelectionBaseTool::OnDrawOverlayOnImage(hdc);
|
||||
|
||||
if (!selectionModel.m_bShow && m_bDrawing)
|
||||
selectionModel.DrawFramePoly(hdc);
|
||||
{
|
||||
/* Draw the freehand selection inverted/xored */
|
||||
Poly(hdc, s_pointStack, s_pointSP, 0, 0, 2, 0, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_RECTSEL
|
||||
struct RectSelTool : SelectionBaseTool
|
||||
{
|
||||
void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
|
||||
{
|
||||
if (m_bShiftKey && !m_bCtrlKey)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
SelectionBaseTool::OnDrawOverlayOnImage(hdc);
|
||||
|
@ -15,8 +15,6 @@ SelectionModel selectionModel;
|
||||
SelectionModel::SelectionModel()
|
||||
: m_hbmColor(NULL)
|
||||
, m_hbmMask(NULL)
|
||||
, m_ptStack(NULL)
|
||||
, m_iPtSP(0)
|
||||
, m_rgbBack(RGB(255, 255, 255))
|
||||
, m_bShow(FALSE)
|
||||
, m_bContentChanged(FALSE)
|
||||
@ -30,69 +28,6 @@ SelectionModel::~SelectionModel()
|
||||
{
|
||||
ClearColorImage();
|
||||
ClearMaskImage();
|
||||
ResetPtStack();
|
||||
}
|
||||
|
||||
void SelectionModel::ResetPtStack()
|
||||
{
|
||||
if (m_ptStack)
|
||||
{
|
||||
free(m_ptStack);
|
||||
m_ptStack = NULL;
|
||||
}
|
||||
m_iPtSP = 0;
|
||||
}
|
||||
|
||||
void SelectionModel::PushToPtStack(POINT pt)
|
||||
{
|
||||
#define GROW_COUNT 256
|
||||
if (m_iPtSP % GROW_COUNT == 0)
|
||||
{
|
||||
INT nNewCount = m_iPtSP + GROW_COUNT;
|
||||
LPPOINT pptNew = (LPPOINT)realloc(m_ptStack, sizeof(POINT) * nNewCount);
|
||||
if (pptNew == NULL)
|
||||
return;
|
||||
m_ptStack = pptNew;
|
||||
}
|
||||
m_ptStack[m_iPtSP] = pt;
|
||||
m_iPtSP++;
|
||||
#undef GROW_COUNT
|
||||
}
|
||||
|
||||
void SelectionModel::ShiftPtStack(INT dx, INT dy)
|
||||
{
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
POINT& pt = m_ptStack[i];
|
||||
pt.x += dx;
|
||||
pt.y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
void SelectionModel::BuildMaskFromPtStack()
|
||||
{
|
||||
CRect rc;
|
||||
getBoundaryOfPtStack(rc, m_iPtSP, m_ptStack);
|
||||
|
||||
m_rc = m_rcOld = rc;
|
||||
|
||||
ClearMaskImage();
|
||||
|
||||
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));
|
||||
HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
|
||||
HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
|
||||
::Polygon(hdcMem, m_ptStack, m_iPtSP);
|
||||
::SelectObject(hdcMem, hbrOld);
|
||||
::SelectObject(hdcMem, hPenOld);
|
||||
::SelectObject(hdcMem, hbmOld);
|
||||
::DeleteDC(hdcMem);
|
||||
|
||||
ShiftPtStack(+m_rcOld.left, +m_rcOld.top);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
|
||||
@ -100,11 +35,11 @@ void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
|
||||
if (m_rcOld.IsRectEmpty())
|
||||
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);
|
||||
HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::GetStockObject(DC_BRUSH));
|
||||
::SetDCBrushColor(hDCImage, crBg);
|
||||
::MaskBlt(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.Width(), m_rcOld.Height(),
|
||||
hDCImage, m_rcOld.left, m_rcOld.top, m_hbmMask, 0, 0, MAKEROP4(PATCOPY, SRCCOPY));
|
||||
::SelectObject(hDCImage, hbrOld);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
|
||||
@ -115,12 +50,12 @@ void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
|
||||
Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawBackground(HDC hDCImage)
|
||||
void SelectionModel::DrawBackground(HDC hDCImage, COLORREF crBg)
|
||||
{
|
||||
if (toolsModel.GetActiveTool() == TOOL_FREESEL)
|
||||
DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor());
|
||||
DrawBackgroundPoly(hDCImage, crBg);
|
||||
else
|
||||
DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
|
||||
DrawBackgroundRect(hDCImage, crBg);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
|
||||
@ -143,6 +78,15 @@ void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTranspar
|
||||
DeleteDC(hMemDC);
|
||||
}
|
||||
|
||||
void SelectionModel::setMask(const CRect& rc, HBITMAP hbmMask)
|
||||
{
|
||||
if (m_hbmMask)
|
||||
::DeleteObject(m_hbmMask);
|
||||
|
||||
m_hbmMask = hbmMask;
|
||||
m_rc = m_rcOld = rc;
|
||||
}
|
||||
|
||||
HBITMAP SelectionModel::GetSelectionContents()
|
||||
{
|
||||
if (m_hbmColor)
|
||||
@ -178,17 +122,6 @@ BOOL SelectionModel::TakeOff()
|
||||
// Save the selection area
|
||||
m_rcOld = m_rc;
|
||||
|
||||
if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
selectionModel.DrawBackgroundRect(imageModel.GetDC(), selectionModel.m_rgbBack);
|
||||
}
|
||||
else if (toolsModel.GetActiveTool() == TOOL_FREESEL)
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
selectionModel.DrawBackgroundPoly(imageModel.GetDC(), selectionModel.m_rgbBack);
|
||||
}
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
@ -201,12 +134,12 @@ void SelectionModel::Landing()
|
||||
return;
|
||||
}
|
||||
|
||||
m_bShow = FALSE;
|
||||
|
||||
if (m_bContentChanged ||
|
||||
(!m_rc.EqualRect(m_rcOld) && !m_rc.IsRectEmpty() && !m_rcOld.IsRectEmpty()))
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
CRect rc;
|
||||
rc.UnionRect(m_rc, m_rcOld);
|
||||
imageModel.PushImageForUndo(rc);
|
||||
|
||||
canvasWindow.m_drawing = FALSE;
|
||||
toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
|
||||
@ -397,17 +330,6 @@ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int
|
||||
NotifyContentChanged();
|
||||
}
|
||||
|
||||
int SelectionModel::PtStackSize() const
|
||||
{
|
||||
return m_iPtSP;
|
||||
}
|
||||
|
||||
void SelectionModel::DrawFramePoly(HDC hDCImage)
|
||||
{
|
||||
/* draw the freehand selection inverted/xored */
|
||||
Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE);
|
||||
}
|
||||
|
||||
void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
|
||||
{
|
||||
m_rc = CRect(ptFrom, ptTo);
|
||||
@ -491,7 +413,7 @@ void SelectionModel::DeleteSelection()
|
||||
|
||||
TakeOff();
|
||||
imageModel.PushImageForUndo();
|
||||
DrawBackground(imageModel.GetDC());
|
||||
DrawBackground(imageModel.GetDC(), paletteModel.GetBgColor());
|
||||
|
||||
HideSelection();
|
||||
}
|
||||
|
@ -13,8 +13,6 @@ class SelectionModel
|
||||
private:
|
||||
HBITMAP m_hbmColor;
|
||||
HBITMAP m_hbmMask;
|
||||
POINT *m_ptStack;
|
||||
int m_iPtSP;
|
||||
|
||||
public:
|
||||
COLORREF m_rgbBack;
|
||||
@ -27,11 +25,8 @@ public:
|
||||
SelectionModel();
|
||||
~SelectionModel();
|
||||
|
||||
void ResetPtStack();
|
||||
void PushToPtStack(POINT pt);
|
||||
int PtStackSize() const;
|
||||
void SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo);
|
||||
void BuildMaskFromPtStack();
|
||||
void setMask(const CRect& rc, HBITMAP hbmMask);
|
||||
|
||||
BOOL TakeOff();
|
||||
void Landing();
|
||||
@ -43,8 +38,7 @@ public:
|
||||
void moveSelection(INT xDelta, INT yDelta);
|
||||
|
||||
HBITMAP GetSelectionContents();
|
||||
void DrawFramePoly(HDC hDCImage);
|
||||
void DrawBackground(HDC hDCImage);
|
||||
void DrawBackground(HDC hDCImage, COLORREF crBg);
|
||||
void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg);
|
||||
void DrawBackgroundRect(HDC hDCImage, COLORREF crBg);
|
||||
void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
|
||||
|
@ -209,6 +209,9 @@ SIZE ToolsModel::GetToolSize() const
|
||||
{
|
||||
case TOOL_FREESEL:
|
||||
case TOOL_RECTSEL:
|
||||
size.cx = selectionModel.m_rc.Width();
|
||||
size.cy = selectionModel.m_rc.Height();
|
||||
break;
|
||||
case TOOL_COLOR:
|
||||
case TOOL_ZOOM:
|
||||
case TOOL_TEXT:
|
||||
|
@ -42,7 +42,6 @@ struct ToolBase
|
||||
{
|
||||
HDC m_hdc;
|
||||
COLORREF m_fg, m_bg;
|
||||
static SIZE_T s_pointSP;
|
||||
|
||||
ToolBase() : m_hdc(NULL) { }
|
||||
virtual ~ToolBase() { }
|
||||
|
Loading…
Reference in New Issue
Block a user