[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)); HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, color));
MoveToEx(hdc, x1, y1, NULL); MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x2, y2); LineTo(hdc, x2, y2);
SetPixelV(hdc, x2, y2, color);
DeleteObject(SelectObject(hdc, oldPen)); DeleteObject(SelectObject(hdc, oldPen));
} }

View File

@ -320,6 +320,11 @@ struct TwoPointDrawTool : ToolBase
m_bDrawing = FALSE; m_bDrawing = FALSE;
ToolBase::OnCancelDraw(); ToolBase::OnCancelDraw();
} }
void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakeLineThickerOrThinner(bMinus);
}
}; };
typedef enum DIRECTION 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()); Erase(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_bg, toolsModel.GetRubberRadius());
else else
Replace(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_fg, m_bg, toolsModel.GetRubberRadius()); 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 void draw(BOOL bLeftButton, LONG x, LONG y) override
{ {
COLORREF rgb = bLeftButton ? m_fg : m_bg; COLORREF rgb = bLeftButton ? m_fg : m_bg;
Line(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, 1); Line(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetPenWidth());
::SetPixelV(m_hdc, x, y, rgb); }
g_ptEnd.x = x;
g_ptEnd.y = y; void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakePenThickerOrThinner(bMinus);
} }
}; };
@ -605,8 +610,11 @@ struct BrushTool : SmoothDrawTool
{ {
COLORREF rgb = bLeftButton ? m_fg : m_bg; COLORREF rgb = bLeftButton ? m_fg : m_bg;
Brush(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetBrushStyle()); 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; m_bDrawing = FALSE;
ToolBase::OnFinishDraw(); ToolBase::OnFinishDraw();
} }
void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakeLineThickerOrThinner(bMinus);
}
}; };
// TOOL_RECT // TOOL_RECT
@ -991,6 +1004,11 @@ struct ShapeTool : ToolBase
ToolBase::OnFinishDraw(); ToolBase::OnFinishDraw();
} }
void OnSpecialTweak(BOOL bMinus) override
{
toolsModel.MakeLineThickerOrThinner(bMinus);
}
}; };
// TOOL_ELLIPSE // 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 // We have to detect clicking on toolbar even if no change of pressed button
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
INT id = (INT)SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt); INT index = (INT)::SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt);
::PostMessage(::GetParent(hwnd), WM_TOOLBARHIT, id, 0); 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); return ::CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
} }
@ -112,6 +117,7 @@ static const COMMAND_TO_TOOL CommandToToolMapping[] =
{ ID_ELLIPSE, TOOL_ELLIPSE }, { ID_ELLIPSE, TOOL_ELLIPSE },
{ ID_RRECT, TOOL_RRECT }, { ID_RRECT, TOOL_RRECT },
}; };
static_assert(_countof(CommandToToolMapping) == TOOL_MAX, "Logical error");
LRESULT CToolBox::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 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(); ::ReleaseCapture();
return 0; 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 CX_TOOLBAR (TOOLBAR_COLUMNS * CXY_TB_BUTTON)
#define CY_TOOLBAR (TOOLBAR_ROWS * CXY_TB_BUTTON) #define CY_TOOLBAR (TOOLBAR_ROWS * CXY_TB_BUTTON)
#define WM_TOOLBARHIT (WM_APP + 1)
class CPaintToolBar : public CWindow class CPaintToolBar : public CWindow
{ {
public: public:
@ -36,7 +34,6 @@ public:
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_TOOLSMODELTOOLCHANGED, OnToolsModelToolChanged) MESSAGE_HANDLER(WM_TOOLSMODELTOOLCHANGED, OnToolsModelToolChanged)
MESSAGE_HANDLER(WM_TOOLBARHIT, OnToolBarHit)
END_MSG_MAP() END_MSG_MAP()
BOOL DoCreate(HWND hwndParent); BOOL DoCreate(HWND hwndParent);
@ -51,5 +48,4 @@ private:
LRESULT OnMouseMove(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 OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnToolsModelToolChanged(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() ToolsModel::ToolsModel()
{ {
m_lineWidth = 1; m_lineWidth = m_penWidth = 1;
m_shapeStyle = 0; m_shapeStyle = 0;
m_brushStyle = 0; m_brushStyle = 0;
m_oldActiveTool = m_activeTool = TOOL_PEN; m_oldActiveTool = m_activeTool = TOOL_PEN;
@ -53,6 +53,31 @@ void ToolsModel::SetLineWidth(int nLineWidth)
{ {
m_lineWidth = nLineWidth; m_lineWidth = nLineWidth;
NotifyToolSettingsChanged(); 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 int ToolsModel::GetShapeStyle() const
@ -91,23 +116,38 @@ void ToolsModel::SetActiveTool(TOOLTYPE nActiveTool)
{ {
OnFinishDraw(); OnFinishDraw();
selectionModel.Landing();
m_activeTool = nActiveTool;
switch (m_activeTool) switch (m_activeTool)
{ {
case TOOL_FREESEL: case TOOL_FREESEL:
case TOOL_RECTSEL: case TOOL_RECTSEL:
case TOOL_RUBBER:
case TOOL_COLOR: case TOOL_COLOR:
case TOOL_ZOOM: case TOOL_ZOOM:
case TOOL_TEXT: case TOOL_TEXT:
// The active tool is not an actually drawing tool
break; break;
default: case TOOL_LINE:
m_oldActiveTool = m_activeTool; 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; break;
} }
m_activeTool = nActiveTool;
m_pToolObject = GetOrCreateTool(m_activeTool); m_pToolObject = GetOrCreateTool(m_activeTool);
NotifyToolChanged(); NotifyToolChanged();
} }
@ -189,9 +229,9 @@ void ToolsModel::NotifyZoomChanged()
void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
{ {
m_pToolObject->beginEvent(); m_pToolObject->beginEvent();
m_pToolObject->OnButtonDown(bLeftButton, x, y, bDoubleClick);
g_ptStart.x = g_ptEnd.x = x; g_ptStart.x = g_ptEnd.x = x;
g_ptStart.y = g_ptEnd.y = y; g_ptStart.y = g_ptEnd.y = y;
m_pToolObject->OnButtonDown(bLeftButton, x, y, bDoubleClick);
m_pToolObject->endEvent(); m_pToolObject->endEvent();
} }

View File

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