[MSPAINT] Larger/smaller pen nib on Ctrl+Plus/Minus (#5738)

- Introduce the concept of pen width (not line width) to the tools model.
- Enable changing pen/line width by Ctrl+Plus/Minus key combination in TOOL_PEN,
  TOOL_LINE, TOOL_BEZIER, TOOL_RECT, TOOL_SHAPE, TOO_ELLIPSE, and
  TOOL_RRECT tools.
CORE-19094
This commit is contained in:
Katayama Hirofumi MZ 2023-09-28 16:32:36 +09:00 committed by GitHub
parent cbc63d876c
commit f2a012240f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 27 deletions

View file

@ -17,6 +17,7 @@ Line(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, int thickness)
HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, color));
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x2, y2);
SetPixelV(hdc, x2, y2, color);
DeleteObject(SelectObject(hdc, oldPen));
}

View file

@ -320,6 +320,11 @@ struct TwoPointDrawTool : ToolBase
m_bDrawing = FALSE;
ToolBase::OnCancelDraw();
}
void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakeLineThickerOrThinner(bMinus);
}
};
typedef enum DIRECTION
@ -499,8 +504,6 @@ struct RubberTool : SmoothDrawTool
Erase(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_bg, toolsModel.GetRubberRadius());
else
Replace(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_fg, m_bg, toolsModel.GetRubberRadius());
g_ptEnd.x = x;
g_ptEnd.y = y;
}
};
@ -587,10 +590,12 @@ struct PenTool : SmoothDrawTool
void draw(BOOL bLeftButton, LONG x, LONG y) override
{
COLORREF rgb = bLeftButton ? m_fg : m_bg;
Line(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, 1);
::SetPixelV(m_hdc, x, y, rgb);
g_ptEnd.x = x;
g_ptEnd.y = y;
Line(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetPenWidth());
}
void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakePenThickerOrThinner(bMinus);
}
};
@ -605,8 +610,11 @@ struct BrushTool : SmoothDrawTool
{
COLORREF rgb = bLeftButton ? m_fg : m_bg;
Brush(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetBrushStyle());
g_ptEnd.x = x;
g_ptEnd.y = y;
}
void OnSpecialTweak(BOOL bMinus) override
{
// TODO:
}
};
@ -863,6 +871,11 @@ struct BezierTool : ToolBase
m_bDrawing = FALSE;
ToolBase::OnFinishDraw();
}
void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakeLineThickerOrThinner(bMinus);
}
};
// TOOL_RECT
@ -991,6 +1004,11 @@ struct ShapeTool : ToolBase
ToolBase::OnFinishDraw();
}
void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakeLineThickerOrThinner(bMinus);
}
};
// TOOL_ELLIPSE

View file

@ -20,8 +20,13 @@ CPaintToolBar::ToolBarWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
{
// We have to detect clicking on toolbar even if no change of pressed button
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
INT id = (INT)SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt);
::PostMessage(::GetParent(hwnd), WM_TOOLBARHIT, id, 0);
INT index = (INT)::SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt);
if (index >= 0)
{
TBBUTTON button;
if (::SendMessage(hwnd, TB_GETBUTTON, index, (LPARAM)&button))
::PostMessage(::GetParent(hwnd), WM_COMMAND, button.idCommand, 0);
}
}
return ::CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
}
@ -112,6 +117,7 @@ static const COMMAND_TO_TOOL CommandToToolMapping[] =
{ ID_ELLIPSE, TOOL_ELLIPSE },
{ ID_RRECT, TOOL_RRECT },
};
static_assert(_countof(CommandToToolMapping) == TOOL_MAX, "Logical error");
LRESULT CToolBox::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
@ -183,10 +189,3 @@ LRESULT CToolBox::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa
::ReleaseCapture();
return 0;
}
LRESULT CToolBox::OnToolBarHit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// See also: CPaintToolBar::ToolBarWndProc
selectionModel.Landing();
return 0;
}

View file

@ -14,8 +14,6 @@
#define CX_TOOLBAR (TOOLBAR_COLUMNS * CXY_TB_BUTTON)
#define CY_TOOLBAR (TOOLBAR_ROWS * CXY_TB_BUTTON)
#define WM_TOOLBARHIT (WM_APP + 1)
class CPaintToolBar : public CWindow
{
public:
@ -36,7 +34,6 @@ public:
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_TOOLSMODELTOOLCHANGED, OnToolsModelToolChanged)
MESSAGE_HANDLER(WM_TOOLBARHIT, OnToolBarHit)
END_MSG_MAP()
BOOL DoCreate(HWND hwndParent);
@ -51,5 +48,4 @@ private:
LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnToolBarHit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};

View file

@ -13,7 +13,7 @@ ToolsModel toolsModel;
ToolsModel::ToolsModel()
{
m_lineWidth = 1;
m_lineWidth = m_penWidth = 1;
m_shapeStyle = 0;
m_brushStyle = 0;
m_oldActiveTool = m_activeTool = TOOL_PEN;
@ -53,6 +53,31 @@ void ToolsModel::SetLineWidth(int nLineWidth)
{
m_lineWidth = nLineWidth;
NotifyToolSettingsChanged();
imageModel.NotifyImageChanged();
}
INT ToolsModel::GetPenWidth() const
{
return m_penWidth;
}
void ToolsModel::SetPenWidth(INT nPenWidth)
{
m_penWidth = nPenWidth;
NotifyToolSettingsChanged();
imageModel.NotifyImageChanged();
}
void ToolsModel::MakeLineThickerOrThinner(BOOL bThinner)
{
INT thickness = GetLineWidth();
SetLineWidth(bThinner ? max(1, thickness - 1) : (thickness + 1));
}
void ToolsModel::MakePenThickerOrThinner(BOOL bThinner)
{
INT thickness = GetPenWidth();
SetPenWidth(bThinner ? max(1, thickness - 1) : (thickness + 1));
}
int ToolsModel::GetShapeStyle() const
@ -91,23 +116,38 @@ void ToolsModel::SetActiveTool(TOOLTYPE nActiveTool)
{
OnFinishDraw();
selectionModel.Landing();
m_activeTool = nActiveTool;
switch (m_activeTool)
{
case TOOL_FREESEL:
case TOOL_RECTSEL:
case TOOL_RUBBER:
case TOOL_COLOR:
case TOOL_ZOOM:
case TOOL_TEXT:
// The active tool is not an actually drawing tool
break;
default:
m_oldActiveTool = m_activeTool;
case TOOL_LINE:
case TOOL_BEZIER:
case TOOL_RECT:
case TOOL_SHAPE:
case TOOL_ELLIPSE:
case TOOL_FILL:
case TOOL_AIRBRUSH:
case TOOL_RRECT:
case TOOL_RUBBER:
case TOOL_BRUSH:
case TOOL_PEN:
// The active tool is an actually drawing tool. Save it for TOOL_COLOR to restore
m_oldActiveTool = nActiveTool;
break;
}
m_activeTool = nActiveTool;
m_pToolObject = GetOrCreateTool(m_activeTool);
NotifyToolChanged();
}
@ -189,9 +229,9 @@ void ToolsModel::NotifyZoomChanged()
void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
{
m_pToolObject->beginEvent();
m_pToolObject->OnButtonDown(bLeftButton, x, y, bDoubleClick);
g_ptStart.x = g_ptEnd.x = x;
g_ptStart.y = g_ptEnd.y = y;
m_pToolObject->OnButtonDown(bLeftButton, x, y, bDoubleClick);
m_pToolObject->endEvent();
}

View file

@ -67,6 +67,7 @@ class ToolsModel
{
private:
int m_lineWidth;
INT m_penWidth;
int m_shapeStyle;
int m_brushStyle;
TOOLTYPE m_activeTool;
@ -85,8 +86,15 @@ public:
~ToolsModel();
BOOL IsSelection() const;
int GetLineWidth() const;
void SetLineWidth(int nLineWidth);
void MakeLineThickerOrThinner(BOOL bThinner);
INT GetPenWidth() const;
void SetPenWidth(INT nPenWidth);
void MakePenThickerOrThinner(BOOL bThinner);
int GetShapeStyle() const;
void SetShapeStyle(int nShapeStyle);
int GetBrushStyle() const;