mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 04:23:32 +00:00
[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:
parent
728694f60f
commit
6b6a045766
12 changed files with 420 additions and 288 deletions
|
@ -9,88 +9,104 @@
|
|||
/* INCLUDES *********************************************************/
|
||||
|
||||
#include "precomp.h"
|
||||
#include <atltypes.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
CRect tempRect;
|
||||
GetClientRect(&tempRect);
|
||||
CSize sizeScrollBox(tempRect.Width(), tempRect.Height());
|
||||
CRect rcClient;
|
||||
GetClientRect(&rcClient);
|
||||
|
||||
CSize sizePage(rcClient.right, rcClient.bottom);
|
||||
CSize sizeZoomed = { Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()) };
|
||||
CSize sizeWhole = { sizeZoomed.cx + (GRIP_SIZE * 2), sizeZoomed.cy + (GRIP_SIZE * 2) };
|
||||
|
||||
/* show/hide the scrollbars */
|
||||
ShowScrollBar(SB_HORZ, sizeScrollBox.cx < sizeWhole.cx);
|
||||
ShowScrollBar(SB_VERT, sizeScrollBox.cy < sizeWhole.cy);
|
||||
ShowScrollBar(SB_HORZ, sizePage.cx < sizeWhole.cx);
|
||||
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);
|
||||
sizeScrollBox = CSize(tempRect.Width(), tempRect.Height());
|
||||
GetClientRect(&rcClient); // Scrollbars might change, get client rectangle again
|
||||
sizePage = CSize(rcClient.right, rcClient.bottom);
|
||||
}
|
||||
|
||||
SCROLLINFO si = { sizeof(si), SIF_PAGE | SIF_RANGE };
|
||||
si.nMin = 0;
|
||||
|
||||
si.nMax = sizeWhole.cx;
|
||||
si.nPage = sizeScrollBox.cx;
|
||||
si.nPage = sizePage.cx;
|
||||
SetScrollInfo(SB_HORZ, &si);
|
||||
|
||||
si.nMax = sizeWhole.cy;
|
||||
si.nPage = sizeScrollBox.cy;
|
||||
si.nPage = sizePage.cy;
|
||||
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)
|
||||
{
|
||||
INT dx = -GetScrollPos(SB_HORZ), dy = -GetScrollPos(SB_VERT);
|
||||
imageArea.MoveWindow(dx + GRIP_SIZE, dy + GRIP_SIZE, sizeZoomed.cx, sizeZoomed.cy, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CCanvasWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
if (m_hWnd)
|
||||
{
|
||||
Update(m_hWnd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
VOID CCanvasWindow::OnHVScroll(WPARAM wParam, INT fnBar)
|
||||
{
|
||||
SCROLLINFO si;
|
||||
si.cbSize = sizeof(SCROLLINFO);
|
||||
si.fMask = SIF_ALL;
|
||||
GetScrollInfo(SB_HORZ, &si);
|
||||
GetScrollInfo(fnBar, &si);
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case SB_THUMBTRACK:
|
||||
|
@ -110,59 +126,193 @@ LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
|
|||
si.nPos += si.nPage;
|
||||
break;
|
||||
}
|
||||
SetScrollInfo(SB_HORZ, &si);
|
||||
SetScrollInfo(fnBar, &si);
|
||||
Update(m_hWnd);
|
||||
Invalidate(FALSE); // FIXME: Flicker
|
||||
}
|
||||
|
||||
LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
OnHVScroll(wParam, SB_HORZ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CCanvasWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
SCROLLINFO si;
|
||||
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);
|
||||
OnHVScroll(wParam, SB_VERT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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:
|
||||
case TOOL_SHAPE:
|
||||
if (toolsModel.GetActiveTool() == TOOL_BEZIER ||
|
||||
toolsModel.GetActiveTool() == TOOL_SHAPE)
|
||||
{
|
||||
if (ToolBase::pointSP != 0)
|
||||
{
|
||||
toolsModel.OnCancelDraw();
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
||||
// Finish dragging
|
||||
m_whereHit = HIT_NONE;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -170,3 +320,26 @@ LRESULT CCanvasWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue