Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
katahiromz committed Oct 22, 2023
1 parent b0b6f38 commit 5fea94f
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 151 deletions.
166 changes: 112 additions & 54 deletions canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,88 @@ HITTEST CCanvasWindow::CanvasHitTest(POINT pt)
return getSizeBoxHitTest(pt, &rcBase);
}

VOID CCanvasWindow::getNewZoomRect(CRect& rcView, INT newZoom, CPoint ptTarget)
{
CRect rcImage;
GetImageRect(rcImage);
ImageToCanvas(rcImage);

// Calculate the zoom rectangle
INT oldZoom = toolsModel.GetZoom();
GetClientRect(rcView);
LONG cxView = rcView.right * oldZoom / newZoom, cyView = rcView.bottom * oldZoom / newZoom;
::SetRect(&rcView, ptTarget.x - cxView / 2, ptTarget.y - cyView / 2,
ptTarget.x + cxView / 2, ptTarget.y + cyView / 2);

// Shift the rectangle if necessary
INT dx = 0, dy = 0;
if (rcView.left < rcImage.left)
dx = rcImage.left - rcView.left;
else if (rcImage.right < rcView.right)
dx = rcImage.right - rcView.right;
if (rcView.top < rcImage.top)
dy = rcImage.top - rcView.top;
else if (rcImage.bottom < rcView.bottom)
dy = rcImage.bottom - rcView.bottom;
rcView.OffsetRect(dx, dy);

rcView.IntersectRect(&rcView, &rcImage);
}

VOID CCanvasWindow::zoomTo(INT newZoom, LONG left, LONG top)
{
POINT pt = { left, top };
CanvasToImage(pt);

toolsModel.SetZoom(newZoom);
ImageToCanvas(pt);
pt.x += GetScrollPos(SB_HORZ);
pt.y += GetScrollPos(SB_VERT);

updateScrollRange();
updateScrollPos(pt.x, pt.y);
Invalidate(TRUE);
}

VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
{
// This is the target area we have to draw on
CRect rcCanvasDraw;
rcCanvasDraw.IntersectRect(&rcClient, &rcPaint);

// We use a memory bitmap to reduce flickering
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 on hdcMem0
::FillRect(hdcMem0, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1));
::FillRect(hdcMem0, &rcCanvasDraw, (HBRUSH)(COLOR_APPWORKSPACE + 1));

// Draw the sizeboxes if necessary
RECT rcBase = GetBaseRect();
if (!selectionModel.m_bShow && !::IsWindowVisible(textEditWindow))
drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcPaint);
drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcCanvasDraw);

// Calculate image size
CRect rcImage;
GetImageRect(rcImage);
SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };

// Calculate the target area on the image
CRect rcImageDraw = rcCanvasDraw;
CanvasToImage(rcImageDraw);
rcImageDraw.IntersectRect(&rcImageDraw, &rcImage);

// Consider rounding down by zooming
rcImageDraw.right += 1;
rcImageDraw.bottom += 1;

// 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);
::BitBlt(hdcMem1, rcImageDraw.left, rcImageDraw.top, rcImageDraw.Width(), rcImageDraw.Height(),
imageModel.GetDC(), rcImageDraw.left, rcImageDraw.top, SRCCOPY);

// Draw overlay #1 on hdcMem1
toolsModel.OnDrawOverlayOnImage(hdcMem1);
Expand Down Expand Up @@ -158,17 +215,15 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
DrawXorRect(hdcMem0, &m_rcResizing);

// Transfer the bits (hDC <-- hdcMem0)
::BitBlt(hDC,
rcPaint.left, rcPaint.top,
rcPaint.right - rcPaint.left, rcPaint.bottom - rcPaint.top,
hdcMem0, rcPaint.left, rcPaint.top, SRCCOPY);
::BitBlt(hDC, rcCanvasDraw.left, rcCanvasDraw.top, rcCanvasDraw.Width(), rcCanvasDraw.Height(),
hdcMem0, rcCanvasDraw.left, rcCanvasDraw.top, SRCCOPY);

// Clean up hdcMem0
::SelectObject(hdcMem0, hbm0Old);
::DeleteDC(hdcMem0);
}

VOID CCanvasWindow::updateScrollInfo()
VOID CCanvasWindow::updateScrollRange()
{
CRect rcClient;
GetClientRect(&rcClient);
Expand Down Expand Up @@ -199,16 +254,16 @@ VOID CCanvasWindow::updateScrollInfo()
SetScrollInfo(SB_VERT, &si);
}

VOID CCanvasWindow::resetScrollPos()
VOID CCanvasWindow::updateScrollPos(INT x, INT y)
{
SetScrollPos(SB_HORZ, 0);
SetScrollPos(SB_VERT, 0);
SetScrollPos(SB_HORZ, x);
SetScrollPos(SB_VERT, y);
}

LRESULT CCanvasWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (m_hWnd)
updateScrollInfo();
updateScrollRange();

return 0;
}
Expand All @@ -223,7 +278,7 @@ VOID CCanvasWindow::OnHVScroll(WPARAM wParam, INT fnBar)
{
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
si.nPos = HIWORD(wParam);
si.nPos = (SHORT)HIWORD(wParam);
break;
case SB_LINELEFT:
si.nPos -= 5;
Expand All @@ -238,9 +293,9 @@ VOID CCanvasWindow::OnHVScroll(WPARAM wParam, INT fnBar)
si.nPos += si.nPage;
break;
}
si.nPos = max(min(si.nPos, si.nMax), si.nMin);
SetScrollInfo(fnBar, &si);
updateScrollInfo();
Invalidate(FALSE); // FIXME: Flicker
Invalidate();
}

LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
Expand All @@ -255,10 +310,21 @@ LRESULT CCanvasWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
return 0;
}

LRESULT CCanvasWindow::OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
LRESULT CCanvasWindow::OnButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };

m_nMouseDownMsg = nMsg;
BOOL bLeftButton = (nMsg == WM_LBUTTONDOWN);

if (nMsg == WM_MBUTTONDOWN)
{
m_ptOrig = pt;
SetCapture();
::SetCursor(::LoadCursor(g_hinstExe, MAKEINTRESOURCE(IDC_HANDDRAG)));
return 0;
}

HITTEST hitSelection = SelectionHitTest(pt);
if (hitSelection != HIT_NONE)
{
Expand All @@ -278,7 +344,7 @@ LRESULT CCanvasWindow::OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM wParam
}
else
{
canvasWindow.ClientToScreen(&pt);
ClientToScreen(&pt);
mainWindow.TrackPopupMenu(pt, 0);
}
return 0;
Expand All @@ -292,13 +358,13 @@ LRESULT CCanvasWindow::OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM wParam
case TOOL_BEZIER:
case TOOL_SHAPE:
toolsModel.OnCancelDraw();
canvasWindow.Invalidate();
Invalidate();
break;

case TOOL_FREESEL:
case TOOL_RECTSEL:
toolsModel.OnFinishDraw();
canvasWindow.Invalidate();
Invalidate();
break;

default:
Expand Down Expand Up @@ -331,43 +397,35 @@ LRESULT CCanvasWindow::OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM wParam
return 0;
}

LRESULT CCanvasWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return OnLRButtonDown(TRUE, nMsg, wParam, lParam, bHandled);
}

LRESULT CCanvasWindow::OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return OnLRButtonDown(FALSE, nMsg, wParam, lParam, bHandled);
}

LRESULT CCanvasWindow::OnLRButtonDblClk(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
LRESULT CCanvasWindow::OnButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
CanvasToImage(pt);

m_drawing = FALSE;
ReleaseCapture();
::ReleaseCapture();
m_nMouseDownMsg = 0;

toolsModel.OnButtonDown(bLeftButton, pt.x, pt.y, TRUE);
toolsModel.OnButtonDown(nMsg == WM_LBUTTONDBLCLK, pt.x, pt.y, TRUE);
toolsModel.resetTool();
Invalidate(FALSE);
return 0;
}

LRESULT CCanvasWindow::OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return OnLRButtonDblClk(TRUE, nMsg, wParam, lParam, bHandled);
}

LRESULT CCanvasWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return OnLRButtonDblClk(FALSE, nMsg, wParam, lParam, bHandled);
}

LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };

if (m_nMouseDownMsg == WM_MBUTTONDOWN)
{
INT x = GetScrollPos(SB_HORZ) - (pt.x - m_ptOrig.x);
INT y = GetScrollPos(SB_VERT) - (pt.y - m_ptOrig.y);
SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, x), 0);
SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, y), 0);
m_ptOrig = pt;
return 0;
}

CanvasToImage(pt);

if (toolsModel.GetActiveTool() == TOOL_ZOOM)
Expand Down Expand Up @@ -557,13 +615,16 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
return 0;
}

LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
LRESULT CCanvasWindow::OnButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
CanvasToImage(pt);

::ReleaseCapture();

BOOL bLeftButton = (m_nMouseDownMsg == WM_LBUTTONDOWN);
m_nMouseDownMsg = 0;

if (m_drawing)
{
m_drawing = FALSE;
Expand Down Expand Up @@ -620,21 +681,11 @@ LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam,

m_hitCanvasSizeBox = HIT_NONE;
toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
updateScrollInfo();
updateScrollRange();
Invalidate(TRUE);
return 0;
}

LRESULT CCanvasWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return OnLRButtonUp(TRUE, nMsg, wParam, lParam, bHandled);
}

LRESULT CCanvasWindow::OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return OnLRButtonUp(FALSE, nMsg, wParam, lParam, bHandled);
}

LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (CWaitCursor::IsWaiting())
Expand All @@ -643,6 +694,12 @@ LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
return 0;
}

if (m_nMouseDownMsg == WM_MBUTTONDOWN)
{
::SetCursor(::LoadCursor(g_hinstExe, MAKEINTRESOURCE(IDC_HANDDRAG)));
return 0;
}

POINT pt;
::GetCursorPos(&pt);
ScreenToClient(&pt);
Expand Down Expand Up @@ -705,6 +762,7 @@ LRESULT CCanvasWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
{
// Cancel dragging
::ReleaseCapture();
m_nMouseDownMsg = 0;
m_hitCanvasSizeBox = HIT_NONE;
::SetRectEmpty(&m_rcResizing);
Invalidate(TRUE);
Expand Down
33 changes: 16 additions & 17 deletions canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ class CCanvasWindow : public CWindowImpl<CCanvasWindow>
MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_RBUTTONDOWN, OnRButtonDown)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnRButtonDblClk)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnButtonDown)
MESSAGE_HANDLER(WM_RBUTTONDOWN, OnButtonDown)
MESSAGE_HANDLER(WM_MBUTTONDOWN, OnButtonDown)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnButtonDblClk)
MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnButtonDblClk)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
MESSAGE_HANDLER(WM_LBUTTONUP, OnButtonUp)
MESSAGE_HANDLER(WM_RBUTTONUP, OnButtonUp)
MESSAGE_HANDLER(WM_MBUTTONUP, OnButtonUp)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode)
Expand All @@ -42,15 +44,17 @@ class CCanvasWindow : public CWindowImpl<CCanvasWindow>

VOID cancelDrawing();
VOID finishDrawing();
VOID updateScrollInfo();
VOID resetScrollPos();
VOID updateScrollRange();
VOID updateScrollPos(INT x = 0, INT y = 0);

VOID ImageToCanvas(POINT& pt);
VOID ImageToCanvas(RECT& rc);
VOID CanvasToImage(POINT& pt, BOOL bZoomed = FALSE);
VOID CanvasToImage(RECT& rc, BOOL bZoomed = FALSE);
VOID GetImageRect(RECT& rc);
VOID MoveSelection(INT xDelta, INT yDelta);
VOID getNewZoomRect(CRect& rcView, INT newZoom, CPoint ptTarget);
VOID zoomTo(INT newZoom, LONG left = 0, LONG top = 0);

protected:
HITTEST m_hitSelection;
Expand All @@ -74,22 +78,17 @@ class CCanvasWindow : public CWindowImpl<CCanvasWindow>
LRESULT OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
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);
LRESULT OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
UINT m_nMouseDownMsg = 0;
LRESULT OnButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};
Loading

0 comments on commit 5fea94f

Please sign in to comment.