[MSPAINT] Make sizeboxes window-less (#5166)

Reduce window controls and integrate to the canvas window.
- The sizeboxes are absorbed by canvasWindow.
- class CSizeboxWindow is deleted.
- Add enum CANVAS_HITTEST.
- Add getSizeBoxRect, getSizeBoxHitTest, and drawSizeBoxes helper functions in sizebox.cpp.
CORE-18867
This commit is contained in:
Katayama Hirofumi MZ 2023-03-19 10:42:10 +09:00 committed by GitHub
parent 728694f60f
commit 6b6a045766
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 420 additions and 288 deletions

View file

@ -9,88 +9,104 @@
/* INCLUDES *********************************************************/ /* INCLUDES *********************************************************/
#include "precomp.h" #include "precomp.h"
#include <atltypes.h>
/* FUNCTIONS ********************************************************/ /* FUNCTIONS ********************************************************/
CCanvasWindow::CCanvasWindow()
: m_whereHit(HIT_NONE)
, m_ptOrig { 0, 0 }
{
}
RECT CCanvasWindow::GetBaseRect()
{
CRect rcBase = { 0, 0, Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()) };
::InflateRect(&rcBase, GRIP_SIZE, GRIP_SIZE);
::OffsetRect(&rcBase, GRIP_SIZE - GetScrollPos(SB_HORZ), GRIP_SIZE - GetScrollPos(SB_VERT));
return rcBase;
}
CANVAS_HITTEST CCanvasWindow::HitTest(POINT pt)
{
RECT rcBase = GetBaseRect();
return getSizeBoxHitTest(pt, &rcBase);
}
VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
{
// We use a memory bitmap to reduce flickering
HDC hdcMem = ::CreateCompatibleDC(hDC);
HBITMAP hbm = ::CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom);
HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbm);
// Fill the background
::FillRect(hdcMem, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1));
// Draw the sizeboxes
RECT rcBase = GetBaseRect();
drawSizeBoxes(hdcMem, &rcBase, FALSE, &rcPaint);
// Transfer the bits
::BitBlt(hDC,
rcPaint.left, rcPaint.top,
rcPaint.right - rcPaint.left, rcPaint.bottom - rcPaint.top,
hdcMem, rcPaint.left, rcPaint.top, SRCCOPY);
::SelectObject(hdcMem, hbmOld);
::DeleteDC(hdcMem);
}
VOID CCanvasWindow::Update(HWND hwndFrom) VOID CCanvasWindow::Update(HWND hwndFrom)
{ {
CRect tempRect; CRect rcClient;
GetClientRect(&tempRect); GetClientRect(&rcClient);
CSize sizeScrollBox(tempRect.Width(), tempRect.Height());
CSize sizePage(rcClient.right, rcClient.bottom);
CSize sizeZoomed = { Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()) }; CSize sizeZoomed = { Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()) };
CSize sizeWhole = { sizeZoomed.cx + (GRIP_SIZE * 2), sizeZoomed.cy + (GRIP_SIZE * 2) }; CSize sizeWhole = { sizeZoomed.cx + (GRIP_SIZE * 2), sizeZoomed.cy + (GRIP_SIZE * 2) };
/* show/hide the scrollbars */ /* show/hide the scrollbars */
ShowScrollBar(SB_HORZ, sizeScrollBox.cx < sizeWhole.cx); ShowScrollBar(SB_HORZ, sizePage.cx < sizeWhole.cx);
ShowScrollBar(SB_VERT, sizeScrollBox.cy < sizeWhole.cy); ShowScrollBar(SB_VERT, sizePage.cy < sizeWhole.cy);
if (sizeScrollBox.cx < sizeWhole.cx || sizeScrollBox.cy < sizeWhole.cy) if (sizePage.cx < sizeWhole.cx || sizePage.cy < sizeWhole.cy)
{ {
GetClientRect(&tempRect); GetClientRect(&rcClient); // Scrollbars might change, get client rectangle again
sizeScrollBox = CSize(tempRect.Width(), tempRect.Height()); sizePage = CSize(rcClient.right, rcClient.bottom);
} }
SCROLLINFO si = { sizeof(si), SIF_PAGE | SIF_RANGE }; SCROLLINFO si = { sizeof(si), SIF_PAGE | SIF_RANGE };
si.nMin = 0; si.nMin = 0;
si.nMax = sizeWhole.cx; si.nMax = sizeWhole.cx;
si.nPage = sizeScrollBox.cx; si.nPage = sizePage.cx;
SetScrollInfo(SB_HORZ, &si); SetScrollInfo(SB_HORZ, &si);
si.nMax = sizeWhole.cy; si.nMax = sizeWhole.cy;
si.nPage = sizeScrollBox.cy; si.nPage = sizePage.cy;
SetScrollInfo(SB_VERT, &si); SetScrollInfo(SB_VERT, &si);
INT dx = -GetScrollPos(SB_HORZ);
INT dy = -GetScrollPos(SB_VERT);
if (sizeboxLeftTop.IsWindow())
{
sizeboxLeftTop.MoveWindow(dx, dy, GRIP_SIZE, GRIP_SIZE, TRUE);
sizeboxCenterTop.MoveWindow(dx + GRIP_SIZE + (sizeZoomed.cx - GRIP_SIZE) / 2,
dy,
GRIP_SIZE, GRIP_SIZE, TRUE);
sizeboxRightTop.MoveWindow(dx + GRIP_SIZE + sizeZoomed.cx,
dy,
GRIP_SIZE, GRIP_SIZE, TRUE);
sizeboxLeftCenter.MoveWindow(dx,
dy + GRIP_SIZE + (sizeZoomed.cy - GRIP_SIZE) / 2,
GRIP_SIZE, GRIP_SIZE, TRUE);
sizeboxRightCenter.MoveWindow(dx + GRIP_SIZE + sizeZoomed.cx,
dy + GRIP_SIZE + (sizeZoomed.cy - GRIP_SIZE) / 2,
GRIP_SIZE, GRIP_SIZE, TRUE);
sizeboxLeftBottom.MoveWindow(dx,
dy + GRIP_SIZE + sizeZoomed.cy,
GRIP_SIZE, GRIP_SIZE, TRUE);
sizeboxCenterBottom.MoveWindow(dx + GRIP_SIZE + (sizeZoomed.cx - GRIP_SIZE) / 2,
dy + GRIP_SIZE + sizeZoomed.cy,
GRIP_SIZE, GRIP_SIZE, TRUE);
sizeboxRightBottom.MoveWindow(dx + GRIP_SIZE + sizeZoomed.cx,
dy + GRIP_SIZE + sizeZoomed.cy,
GRIP_SIZE, GRIP_SIZE, TRUE);
}
if (imageArea.IsWindow() && hwndFrom != imageArea.m_hWnd) if (imageArea.IsWindow() && hwndFrom != imageArea.m_hWnd)
{
INT dx = -GetScrollPos(SB_HORZ), dy = -GetScrollPos(SB_VERT);
imageArea.MoveWindow(dx + GRIP_SIZE, dy + GRIP_SIZE, sizeZoomed.cx, sizeZoomed.cy, TRUE); imageArea.MoveWindow(dx + GRIP_SIZE, dy + GRIP_SIZE, sizeZoomed.cx, sizeZoomed.cy, TRUE);
}
} }
LRESULT CCanvasWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CCanvasWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if (m_hWnd) if (m_hWnd)
{
Update(m_hWnd); Update(m_hWnd);
}
return 0; return 0;
} }
LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) VOID CCanvasWindow::OnHVScroll(WPARAM wParam, INT fnBar)
{ {
SCROLLINFO si; SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO); si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL; si.fMask = SIF_ALL;
GetScrollInfo(SB_HORZ, &si); GetScrollInfo(fnBar, &si);
switch (LOWORD(wParam)) switch (LOWORD(wParam))
{ {
case SB_THUMBTRACK: case SB_THUMBTRACK:
@ -110,59 +126,193 @@ LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
si.nPos += si.nPage; si.nPos += si.nPage;
break; break;
} }
SetScrollInfo(SB_HORZ, &si); SetScrollInfo(fnBar, &si);
Update(m_hWnd); Update(m_hWnd);
Invalidate(FALSE); // FIXME: Flicker
}
LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
OnHVScroll(wParam, SB_HORZ);
return 0; return 0;
} }
LRESULT CCanvasWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CCanvasWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
SCROLLINFO si; OnHVScroll(wParam, SB_VERT);
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
GetScrollInfo(SB_VERT, &si);
switch (LOWORD(wParam))
{
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
si.nPos = HIWORD(wParam);
break;
case SB_LINEUP:
si.nPos -= 5;
break;
case SB_LINEDOWN:
si.nPos += 5;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
}
SetScrollInfo(SB_VERT, &si);
Update(m_hWnd);
return 0; return 0;
} }
LRESULT CCanvasWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CCanvasWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
switch (toolsModel.GetActiveTool()) POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
CANVAS_HITTEST hit = HitTest(pt);
if (hit == HIT_NONE || hit == HIT_BORDER)
{ {
case TOOL_BEZIER: if (toolsModel.GetActiveTool() == TOOL_BEZIER ||
case TOOL_SHAPE: toolsModel.GetActiveTool() == TOOL_SHAPE)
{
if (ToolBase::pointSP != 0) if (ToolBase::pointSP != 0)
{ {
toolsModel.OnCancelDraw(); toolsModel.OnCancelDraw();
imageArea.Invalidate(); imageArea.Invalidate();
} }
break; }
toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
return 0;
}
if (hit == HIT_INNER)
{
// TODO: In the future, we handle the events of the window-less image area.
return 0;
}
// Start dragging
m_whereHit = hit;
m_ptOrig = pt;
SetCapture();
return 0;
}
LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (m_whereHit == HIT_NONE || ::GetCapture() != m_hWnd)
return 0;
// Dragging now... Calculate the new size
INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
INT cxDelta = UnZoomed(GET_X_LPARAM(lParam) - m_ptOrig.x);
INT cyDelta = UnZoomed(GET_Y_LPARAM(lParam) - m_ptOrig.y);
switch (m_whereHit)
{
case HIT_UPPER_LEFT:
cxImage -= cxDelta;
cyImage -= cyDelta;
break;
case HIT_UPPER_CENTER:
cyImage -= cyDelta;
break;
case HIT_UPPER_RIGHT:
cxImage += cxDelta;
cyImage -= cyDelta;
break;
case HIT_MIDDLE_LEFT:
cxImage -= cxDelta;
break;
case HIT_MIDDLE_RIGHT:
cxImage += cxDelta;
break;
case HIT_LOWER_LEFT:
cxImage -= cxDelta;
cyImage += cyDelta;
break;
case HIT_LOWER_CENTER:
cyImage += cyDelta;
break;
case HIT_LOWER_RIGHT:
cxImage += cxDelta;
cyImage += cyDelta;
break;
default:
return 0;
}
// Limit bitmap size
cxImage = max(1, cxImage);
cyImage = max(1, cyImage);
cxImage = min(MAXWORD, cxImage);
cyImage = min(MAXWORD, cyImage);
// Display new size
CString strSize;
strSize.Format(_T("%d x %d"), cxImage, cyImage);
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
return 0;
}
LRESULT CCanvasWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
::ReleaseCapture();
if (m_whereHit == HIT_NONE)
return 0;
// Resize the image
INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
INT cxDelta = UnZoomed(GET_X_LPARAM(lParam) - m_ptOrig.x);
INT cyDelta = UnZoomed(GET_Y_LPARAM(lParam) - m_ptOrig.y);
switch (m_whereHit)
{
case HIT_UPPER_LEFT:
imageModel.Crop(cxImage - cxDelta, cyImage - cyDelta, cxDelta, cyDelta);
break;
case HIT_UPPER_CENTER:
imageModel.Crop(cxImage, cyImage - cyDelta, 0, cyDelta);
break;
case HIT_UPPER_RIGHT:
imageModel.Crop(cxImage + cxDelta, cyImage - cyDelta, 0, cyDelta);
break;
case HIT_MIDDLE_LEFT:
imageModel.Crop(cxImage - cxDelta, cyImage, cxDelta, 0);
break;
case HIT_MIDDLE_RIGHT:
imageModel.Crop(cxImage + cxDelta, cyImage, 0, 0);
break;
case HIT_LOWER_LEFT:
imageModel.Crop(cxImage - cxDelta, cyImage + cyDelta, cxDelta, 0);
break;
case HIT_LOWER_CENTER:
imageModel.Crop(cxImage, cyImage + cyDelta, 0, 0);
break;
case HIT_LOWER_RIGHT:
imageModel.Crop(cxImage + cxDelta, cyImage + cyDelta, 0, 0);
break;
default: default:
break; break;
} }
// Finish dragging
m_whereHit = HIT_NONE;
toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
Update(NULL);
Invalidate(TRUE);
return 0;
}
LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt;
::GetCursorPos(&pt);
ScreenToClient(&pt);
if (!setCursorOnSizeBox(HitTest(pt)))
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
return 0;
}
LRESULT CCanvasWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (wParam == VK_ESCAPE && ::GetCapture() == m_hWnd)
{
// Cancel dragging
m_whereHit = HIT_NONE;
::ReleaseCapture();
}
return 0;
}
LRESULT CCanvasWindow::OnCancelMode(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// Cancel dragging
m_whereHit = HIT_NONE;
Invalidate(TRUE);
return 0; return 0;
} }
@ -170,3 +320,26 @@ LRESULT CCanvasWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
{ {
return ::SendMessage(GetParent(), nMsg, wParam, lParam); return ::SendMessage(GetParent(), nMsg, wParam, lParam);
} }
LRESULT CCanvasWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM)_T(""));
return 0;
}
LRESULT CCanvasWindow::OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return TRUE; // do nothing => transparent background
}
LRESULT CCanvasWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RECT rcClient;
GetClientRect(&rcClient);
PAINTSTRUCT ps;
HDC hDC = BeginPaint(&ps);
DoDraw(hDC, rcClient, ps.rcPaint);
EndPaint(&ps);
return 0;
}

View file

@ -15,18 +15,44 @@ public:
BEGIN_MSG_MAP(CCanvasWindow) BEGIN_MSG_MAP(CCanvasWindow)
MESSAGE_HANDLER(WM_SIZE, OnSize) MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_HSCROLL, OnHScroll) MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
MESSAGE_HANDLER(WM_VSCROLL, OnVScroll) MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel) MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode)
MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
END_MSG_MAP() END_MSG_MAP()
CCanvasWindow();
VOID Update(HWND hwndFrom); VOID Update(HWND hwndFrom);
protected: protected:
CANVAS_HITTEST m_whereHit;
POINT m_ptOrig; // The origin of drag start
CANVAS_HITTEST HitTest(POINT pt);
RECT GetBaseRect();
VOID DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint);
VOID OnHVScroll(WPARAM wParam, INT fnBar);
LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 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 OnLButtonDown(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 OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMouseWheel(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);
}; };

View file

@ -245,34 +245,6 @@ RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2)
SetROP2(hdc, oldRop); SetROP2(hdc, oldRop);
} }
void
SelectionFrame(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF system_selection_color)
{
HBRUSH oldBrush;
LOGBRUSH logbrush;
HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_DOT, 1, system_selection_color));
logbrush.lbStyle = BS_HOLLOW;
logbrush.lbColor = 0;
logbrush.lbHatch = 0;
oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
Rectangle(hdc, x1, y1, x2, y2); /* SEL BOX FRAME */
DeleteObject(SelectObject(hdc, oldBrush));
DeleteObject(SelectObject(hdc, oldPen));
oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, system_selection_color));
oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(system_selection_color));
Rectangle(hdc, x1 - 1, y1 - 1, x1 + 2, y1 + 2);
Rectangle(hdc, x2 - 2, y1 - 1, x2 + 2, y1 + 2);
Rectangle(hdc, x1 - 1, y2 - 2, x1 + 2, y2 + 1);
Rectangle(hdc, x2 - 2, y2 - 2, x2 + 2, y2 + 1);
Rectangle(hdc, (x1 + x2) / 2 - 1, y1 - 1, (x1 + x2) / 2 + 2, y1 + 2);
Rectangle(hdc, (x1 + x2) / 2 - 1, y2 - 2, (x1 + x2) / 2 + 2, y2 + 1);
Rectangle(hdc, x1 - 1, (y1 + y2) / 2 - 1, x1 + 2, (y1 + y2) / 2 + 2);
Rectangle(hdc, x2 - 2, (y1 + y2) / 2 - 1, x2 + 1, (y1 + y2) / 2 + 2);
DeleteObject(SelectObject(hdc, oldBrush));
DeleteObject(SelectObject(hdc, oldPen));
}
void void
Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style) Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style)
{ {

View file

@ -32,8 +32,6 @@ void Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG sty
void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2); void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2);
void SelectionFrame(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF system_selection_color);
void Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style); void Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style);
extern BOOL extern BOOL

View file

@ -70,14 +70,6 @@ extern CPaletteWindow paletteWindow;
extern CCanvasWindow canvasWindow; extern CCanvasWindow canvasWindow;
extern CSelectionWindow selectionWindow; extern CSelectionWindow selectionWindow;
extern CImgAreaWindow imageArea; extern CImgAreaWindow imageArea;
extern CSizeboxWindow sizeboxLeftTop;
extern CSizeboxWindow sizeboxCenterTop;
extern CSizeboxWindow sizeboxRightTop;
extern CSizeboxWindow sizeboxLeftCenter;
extern CSizeboxWindow sizeboxRightCenter;
extern CSizeboxWindow sizeboxLeftBottom;
extern CSizeboxWindow sizeboxCenterBottom;
extern CSizeboxWindow sizeboxRightBottom;
extern CTextEditWindow textEditWindow; extern CTextEditWindow textEditWindow;
/* VARIABLES declared in dialogs.cpp ********************************/ /* VARIABLES declared in dialogs.cpp ********************************/

View file

@ -57,14 +57,6 @@ CPaletteWindow paletteWindow;
CCanvasWindow canvasWindow; CCanvasWindow canvasWindow;
CSelectionWindow selectionWindow; CSelectionWindow selectionWindow;
CImgAreaWindow imageArea; CImgAreaWindow imageArea;
CSizeboxWindow sizeboxLeftTop;
CSizeboxWindow sizeboxCenterTop;
CSizeboxWindow sizeboxRightTop;
CSizeboxWindow sizeboxLeftCenter;
CSizeboxWindow sizeboxRightCenter;
CSizeboxWindow sizeboxLeftBottom;
CSizeboxWindow sizeboxCenterBottom;
CSizeboxWindow sizeboxRightBottom;
CTextEditWindow textEditWindow; CTextEditWindow textEditWindow;
// get file name extension from filter string // get file name extension from filter string
@ -289,16 +281,6 @@ _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument
} }
} }
/* creating the size boxes */
RECT sizeboxPos = {0, 0, GRIP_SIZE, GRIP_SIZE};
sizeboxLeftTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
sizeboxCenterTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
sizeboxRightTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
sizeboxLeftCenter.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
sizeboxRightCenter.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
sizeboxLeftBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
sizeboxCenterBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
sizeboxRightBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
/* placing the size boxes around the image */ /* placing the size boxes around the image */
imageArea.SendMessage(WM_SIZE, 0, 0); imageArea.SendMessage(WM_SIZE, 0, 0);

View file

@ -19,9 +19,13 @@ POINT ToolBase::pointStack[256] = { { 0 } };
void void
placeSelWin() placeSelWin()
{ {
selectionWindow.MoveWindow(Zoomed(selectionModel.GetDestRectLeft()), Zoomed(selectionModel.GetDestRectTop()), CRect rc;
Zoomed(selectionModel.GetDestRectWidth()) + 2 * GRIP_SIZE, rc.left = Zoomed(selectionModel.GetDestRectLeft());
Zoomed(selectionModel.GetDestRectHeight()) + 2 * GRIP_SIZE, TRUE); rc.top = Zoomed(selectionModel.GetDestRectTop());
rc.right = rc.left + Zoomed(selectionModel.GetDestRectWidth());
rc.bottom = rc.top + Zoomed(selectionModel.GetDestRectHeight());
::InflateRect(&rc, GRIP_SIZE, GRIP_SIZE);
selectionWindow.MoveWindow(rc.left, rc.top, rc.Width(), rc.Height(), TRUE);
selectionWindow.BringWindowToTop(); selectionWindow.BringWindowToTop();
imageArea.InvalidateRect(NULL, FALSE); imageArea.InvalidateRect(NULL, FALSE);
} }
@ -712,11 +716,6 @@ struct ShapeTool : ToolBase
imageModel.ResetToPrevious(); imageModel.ResetToPrevious();
--pointSP; --pointSP;
draw(m_bLeftButton, -1, -1, TRUE); draw(m_bLeftButton, -1, -1, TRUE);
pointSP = 0;
}
else
{
imageModel.Undo(TRUE);
} }
ToolBase::OnFinishDraw(); ToolBase::OnFinishDraw();
} }

View file

@ -19,6 +19,7 @@
#include <atlpath.h> #include <atlpath.h>
#include <atlstr.h> #include <atlstr.h>
#include <atlwin.h> #include <atlwin.h>
#include <atltypes.h>
#include <windowsx.h> #include <windowsx.h>
#include <commdlg.h> #include <commdlg.h>
#include <commctrl.h> #include <commctrl.h>
@ -38,8 +39,22 @@
#define WM_IMAGEMODELIMAGECHANGED (WM_APP + 6) #define WM_IMAGEMODELIMAGECHANGED (WM_APP + 6)
#define WM_SELECTIONMODELREFRESHNEEDED (WM_APP + 7) #define WM_SELECTIONMODELREFRESHNEEDED (WM_APP + 7)
enum CANVAS_HITTEST // hit
{
HIT_NONE = 0, // Nothing hit or outside
HIT_UPPER_LEFT,
HIT_UPPER_CENTER,
HIT_UPPER_RIGHT,
HIT_MIDDLE_LEFT,
HIT_MIDDLE_RIGHT,
HIT_LOWER_LEFT,
HIT_LOWER_CENTER,
HIT_LOWER_RIGHT,
HIT_BORDER,
HIT_INNER,
};
#include "resource.h" #include "resource.h"
#include "canvas.h"
#include "drawing.h" #include "drawing.h"
#include "dib.h" #include "dib.h"
#include "fullscreen.h" #include "fullscreen.h"
@ -53,6 +68,7 @@
#include "selection.h" #include "selection.h"
#include "selectionmodel.h" #include "selectionmodel.h"
#include "sizebox.h" #include "sizebox.h"
#include "canvas.h"
#include "textedit.h" #include "textedit.h"
#include "toolbox.h" #include "toolbox.h"
#include "toolsettings.h" #include "toolsettings.h"

View file

@ -33,24 +33,6 @@ void CSelectionWindow::ForceRefreshSelectionContents()
int CSelectionWindow::IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight) int CSelectionWindow::IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight)
{ {
POINT pt = { iXPos, iYPos };
HWND hwndChild = ChildWindowFromPointEx(pt, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
if (hwndChild == sizeboxLeftTop)
return ACTION_RESIZE_TOP_LEFT;
if (hwndChild == sizeboxCenterTop)
return ACTION_RESIZE_TOP;
if (hwndChild == sizeboxRightTop)
return ACTION_RESIZE_TOP_RIGHT;
if (hwndChild == sizeboxRightCenter)
return ACTION_RESIZE_RIGHT;
if (hwndChild == sizeboxLeftCenter)
return ACTION_RESIZE_LEFT;
if (hwndChild == sizeboxCenterBottom)
return ACTION_RESIZE_BOTTOM;
if (hwndChild == sizeboxRightBottom)
return ACTION_RESIZE_BOTTOM_RIGHT;
if (hwndChild == sizeboxLeftBottom)
return ACTION_RESIZE_BOTTOM_LEFT;
return 0; return 0;
} }
@ -60,10 +42,9 @@ LRESULT CSelectionWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
HDC hDC = BeginPaint(&ps); HDC hDC = BeginPaint(&ps);
if (!m_bMoving) if (!m_bMoving)
{ {
SelectionFrame(hDC, 1, 1, RECT rcClient;
Zoomed(selectionModel.GetDestRectWidth()) + (GRIP_SIZE * 2) - 1, GetClientRect(&rcClient);
Zoomed(selectionModel.GetDestRectHeight()) + (GRIP_SIZE * 2) - 1, drawSizeBoxes(hDC, &rcClient, TRUE, &ps.rcPaint);
GetSysColor(COLOR_HIGHLIGHT));
} }
EndPaint(&ps); EndPaint(&ps);
return 0; return 0;
@ -93,7 +74,16 @@ LRESULT CSelectionWindow::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lPar
LRESULT CSelectionWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CSelectionWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
SetCursor(LoadCursor(NULL, IDC_SIZEALL)); RECT rcClient;
GetClientRect(&rcClient);
POINT pt;
::GetCursorPos(&pt);
ScreenToClient(&pt);
if (!setCursorOnSizeBox(getSizeBoxHitTest(pt, &rcClient)))
::SetCursor(::LoadCursor(NULL, IDC_SIZEALL));
return 0; return 0;
} }

View file

@ -7,117 +7,125 @@
* Katayama Hirofumi MZ * Katayama Hirofumi MZ
*/ */
/* INCLUDES *********************************************************/
#include "precomp.h" #include "precomp.h"
static LPCWSTR s_cursor_shapes[] =
{
IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
IDC_SIZEWE, IDC_SIZEWE,
IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE,
};
/* FUNCTIONS ********************************************************/ /* FUNCTIONS ********************************************************/
static BOOL resizing = FALSE; BOOL setCursorOnSizeBox(CANVAS_HITTEST hit)
static short xOrig;
static short yOrig;
LRESULT CSizeboxWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if ((m_hWnd == sizeboxLeftTop.m_hWnd) || (m_hWnd == sizeboxRightBottom.m_hWnd)) if (HIT_UPPER_LEFT <= hit && hit <= HIT_LOWER_RIGHT)
SetCursor(LoadCursor(NULL, IDC_SIZENWSE));
if ((m_hWnd == sizeboxLeftBottom.m_hWnd) || (m_hWnd == sizeboxRightTop.m_hWnd))
SetCursor(LoadCursor(NULL, IDC_SIZENESW));
if ((m_hWnd == sizeboxLeftCenter.m_hWnd) || (m_hWnd == sizeboxRightCenter.m_hWnd))
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
if ((m_hWnd == sizeboxCenterTop.m_hWnd) || (m_hWnd == sizeboxCenterBottom.m_hWnd))
SetCursor(LoadCursor(NULL, IDC_SIZENS));
return 0;
}
LRESULT CSizeboxWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
resizing = TRUE;
xOrig = GET_X_LPARAM(lParam);
yOrig = GET_Y_LPARAM(lParam);
SetCapture();
return 0;
}
LRESULT CSizeboxWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (resizing)
{ {
CString strSize; ::SetCursor(::LoadCursor(NULL, s_cursor_shapes[hit - HIT_UPPER_LEFT]));
short xRel; return TRUE;
short yRel;
int imgXRes = imageModel.GetWidth();
int imgYRes = imageModel.GetHeight();
xRel = UnZoomed(GET_X_LPARAM(lParam) - xOrig);
yRel = UnZoomed(GET_Y_LPARAM(lParam) - yOrig);
if (m_hWnd == sizeboxLeftTop.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes - xRel, imgYRes - yRel);
if (m_hWnd == sizeboxCenterTop.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes, imgYRes - yRel);
if (m_hWnd == sizeboxRightTop.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes + xRel, imgYRes - yRel);
if (m_hWnd == sizeboxLeftCenter.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes - xRel, imgYRes);
if (m_hWnd == sizeboxRightCenter.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes + xRel, imgYRes);
if (m_hWnd == sizeboxLeftBottom.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes - xRel, imgYRes + yRel);
if (m_hWnd == sizeboxCenterBottom.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes, imgYRes + yRel);
if (m_hWnd == sizeboxRightBottom.m_hWnd)
strSize.Format(_T("%d x %d"), imgXRes + xRel, imgYRes + yRel);
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
} }
return 0; return FALSE;
} }
LRESULT CSizeboxWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) BOOL getSizeBoxRect(LPRECT prc, CANVAS_HITTEST hit, LPCRECT prcBase)
{ {
if (resizing) switch (hit)
{ {
short xRel; case HIT_UPPER_LEFT:
short yRel; prc->left = prcBase->left;
int imgXRes = imageModel.GetWidth(); prc->top = prcBase->top;
int imgYRes = imageModel.GetHeight(); break;
xRel = (GET_X_LPARAM(lParam) - xOrig) * 1000 / toolsModel.GetZoom(); case HIT_UPPER_CENTER:
yRel = (GET_Y_LPARAM(lParam) - yOrig) * 1000 / toolsModel.GetZoom(); prc->left = (prcBase->left + prcBase->right - GRIP_SIZE) / 2;
if (m_hWnd == sizeboxLeftTop) prc->top = prcBase->top;
imageModel.Crop(imgXRes - xRel, imgYRes - yRel, xRel, yRel); break;
if (m_hWnd == sizeboxCenterTop.m_hWnd) case HIT_UPPER_RIGHT:
imageModel.Crop(imgXRes, imgYRes - yRel, 0, yRel); prc->left = prcBase->right - GRIP_SIZE;
if (m_hWnd == sizeboxRightTop.m_hWnd) prc->top = prcBase->top;
imageModel.Crop(imgXRes + xRel, imgYRes - yRel, 0, yRel); break;
if (m_hWnd == sizeboxLeftCenter.m_hWnd) case HIT_MIDDLE_LEFT:
imageModel.Crop(imgXRes - xRel, imgYRes, xRel, 0); prc->left = prcBase->left;
if (m_hWnd == sizeboxRightCenter.m_hWnd) prc->top = (prcBase->top + prcBase->bottom - GRIP_SIZE) / 2;
imageModel.Crop(imgXRes + xRel, imgYRes, 0, 0); break;
if (m_hWnd == sizeboxLeftBottom.m_hWnd) case HIT_MIDDLE_RIGHT:
imageModel.Crop(imgXRes - xRel, imgYRes + yRel, xRel, 0); prc->left = prcBase->right - GRIP_SIZE;
if (m_hWnd == sizeboxCenterBottom.m_hWnd) prc->top = (prcBase->top + prcBase->bottom - GRIP_SIZE) / 2;
imageModel.Crop(imgXRes, imgYRes + yRel, 0, 0); break;
if (m_hWnd == sizeboxRightBottom.m_hWnd) case HIT_LOWER_LEFT:
imageModel.Crop(imgXRes + xRel, imgYRes + yRel, 0, 0); prc->left = prcBase->left;
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) _T("")); prc->top = prcBase->bottom - GRIP_SIZE;
break;
case HIT_LOWER_CENTER:
prc->left = (prcBase->left + prcBase->right - GRIP_SIZE) / 2;
prc->top = prcBase->bottom - GRIP_SIZE;
break;
case HIT_LOWER_RIGHT:
prc->left = prcBase->right - GRIP_SIZE;
prc->top = prcBase->bottom - GRIP_SIZE;
break;
case HIT_INNER:
*prc = *prcBase;
::InflateRect(prc, -GRIP_SIZE, -GRIP_SIZE);
return TRUE;
default:
::SetRectEmpty(prc);
return FALSE;
} }
resizing = FALSE;
ReleaseCapture(); prc->right = prc->left + GRIP_SIZE;
return 0; prc->bottom = prc->top + GRIP_SIZE;
return TRUE;
} }
LRESULT CSizeboxWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) CANVAS_HITTEST getSizeBoxHitTest(POINT pt, LPCRECT prcBase)
{ {
resizing = FALSE; RECT rc;
return 0;
}
LRESULT CSizeboxWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) if (!::PtInRect(prcBase, pt))
{ return HIT_NONE;
if (wParam == VK_ESCAPE)
rc = *prcBase;
::InflateRect(&rc, -GRIP_SIZE, -GRIP_SIZE);
if (::PtInRect(&rc, pt))
return HIT_INNER;
for (INT i = HIT_UPPER_LEFT; i <= HIT_LOWER_RIGHT; ++i)
{ {
if (GetCapture() == m_hWnd) CANVAS_HITTEST hit = (CANVAS_HITTEST)i;
{ getSizeBoxRect(&rc, hit, prcBase);
ReleaseCapture(); if (::PtInRect(&rc, pt))
} return hit;
}
return HIT_BORDER;
}
VOID drawSizeBoxes(HDC hdc, LPCRECT prcBase, BOOL bDrawFrame, LPCRECT prcPaint)
{
CRect rc, rcIntersect;
if (prcPaint && !::IntersectRect(&rcIntersect, prcPaint, prcBase))
return;
if (bDrawFrame)
{
rc = *prcBase;
::InflateRect(&rc, -GRIP_SIZE / 2, -GRIP_SIZE / 2);
LOGBRUSH logBrush = { BS_HOLLOW, 0, 0 };
COLORREF rgbHighlight = ::GetSysColor(COLOR_HIGHLIGHT);
HGDIOBJ oldPen = ::SelectObject(hdc, ::CreatePen(PS_DOT, 1, rgbHighlight));
HGDIOBJ oldBrush = ::SelectObject(hdc, ::CreateBrushIndirect(&logBrush));
::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
::DeleteObject(::SelectObject(hdc, oldBrush));
::DeleteObject(::SelectObject(hdc, oldPen));
}
for (INT i = HIT_UPPER_LEFT; i <= HIT_LOWER_RIGHT; ++i)
{
getSizeBoxRect(&rc, (CANVAS_HITTEST)i, prcBase);
if (!prcPaint || ::IntersectRect(&rcIntersect, &rc, prcPaint))
::FillRect(hdc, &rc, (HBRUSH)(COLOR_HIGHLIGHT + 1));
} }
return 0;
} }

View file

@ -9,24 +9,7 @@
#pragma once #pragma once
class CSizeboxWindow : public CWindowImpl<CSizeboxWindow> BOOL setCursorOnSizeBox(CANVAS_HITTEST hit);
{ BOOL getSizeBoxRect(LPRECT prc, CANVAS_HITTEST hit, LPCRECT prcBase);
public: CANVAS_HITTEST getSizeBoxHitTest(POINT pt, LPCRECT prcBase);
DECLARE_WND_CLASS_EX(_T("Sizebox"), CS_DBLCLKS, COLOR_HIGHLIGHT) VOID drawSizeBoxes(HDC hdc, LPCRECT prcBase, BOOL bDrawFrame = FALSE, LPCRECT prcPaint = NULL);
BEGIN_MSG_MAP(CSizeboxWindow)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
END_MSG_MAP()
LRESULT OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnLButtonUp(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);
};

View file

@ -437,17 +437,10 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
HWND hwndCapture = GetCapture(); HWND hwndCapture = GetCapture();
if (hwndCapture) if (hwndCapture)
{ {
if (selectionWindow.m_hWnd == hwndCapture || if (canvasWindow.m_hWnd == hwndCapture ||
selectionWindow.m_hWnd == hwndCapture ||
imageArea.m_hWnd == hwndCapture || imageArea.m_hWnd == hwndCapture ||
fullscreenWindow.m_hWnd == hwndCapture || fullscreenWindow.m_hWnd == hwndCapture)
sizeboxLeftTop.m_hWnd == hwndCapture ||
sizeboxCenterTop.m_hWnd == hwndCapture ||
sizeboxRightTop.m_hWnd == hwndCapture ||
sizeboxLeftCenter.m_hWnd == hwndCapture ||
sizeboxRightCenter.m_hWnd == hwndCapture ||
sizeboxLeftBottom.m_hWnd == hwndCapture ||
sizeboxCenterBottom.m_hWnd == hwndCapture ||
sizeboxRightBottom.m_hWnd == hwndCapture)
{ {
SendMessage(hwndCapture, nMsg, wParam, lParam); SendMessage(hwndCapture, nMsg, wParam, lParam);
} }