1 /*
2  * PROJECT:    PAINT for ReactOS
3  * LICENSE:    LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:    Window procedure of the main window and all children apart from
5  *             hPalWin, hToolSettings and hSelection
6  * COPYRIGHT:  Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
7  */
8 
9 #include "precomp.h"
10 
11 CToolBox toolBoxContainer;
12 
13 /* FUNCTIONS ********************************************************/
14 
15 LRESULT CALLBACK
ToolBarWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)16 CPaintToolBar::ToolBarWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
17 {
18     WNDPROC oldWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
19     if (uMsg == WM_LBUTTONUP)
20     {
21         // We have to detect clicking on toolbar even if no change of pressed button
22         POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
23         INT index = (INT)::SendMessageW(hwnd, TB_HITTEST, 0, (LPARAM)&pt);
24         if (index >= 0)
25         {
26             TBBUTTON button;
27             if (::SendMessageW(hwnd, TB_GETBUTTON, index, (LPARAM)&button))
28                 ::PostMessageW(::GetParent(hwnd), WM_COMMAND, button.idCommand, 0);
29         }
30     }
31     return ::CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
32 }
33 
DoCreate(HWND hwndParent)34 BOOL CPaintToolBar::DoCreate(HWND hwndParent)
35 {
36     // NOTE: The horizontal line above the toolbar is hidden by CCS_NODIVIDER style.
37     RECT toolbarPos =
38     {
39         0, 0,
40         CX_TOOLBAR + 2 * GetSystemMetrics(SM_CXBORDER),
41         CY_TOOLBAR + 2 * GetSystemMetrics(SM_CYBORDER)
42     };
43     DWORD style = WS_CHILD | WS_VISIBLE | CCS_NOPARENTALIGN | CCS_VERT | CCS_NORESIZE |
44                   TBSTYLE_TOOLTIPS | TBSTYLE_FLAT;
45     if (!CWindow::Create(TOOLBARCLASSNAMEW, hwndParent, toolbarPos, NULL, style))
46         return FALSE;
47 
48     HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 16, 0);
49     SendMessage(TB_SETIMAGELIST, 0, (LPARAM)hImageList);
50 
51     HBITMAP hbmIcons = (HBITMAP)::LoadImageW(g_hinstExe, MAKEINTRESOURCEW(IDB_TOOLBARICONS),
52                                              IMAGE_BITMAP, 256, 16, 0);
53     ImageList_AddMasked(hImageList, hbmIcons, RGB(255, 0, 255));
54     ::DeleteObject(hbmIcons);
55 
56     SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
57 
58     WCHAR szToolTip[30];
59     TBBUTTON tbbutton;
60     ZeroMemory(&tbbutton, sizeof(tbbutton));
61     tbbutton.fsStyle = TBSTYLE_CHECKGROUP;
62     for (INT i = 0; i < NUM_TOOLS; i++)
63     {
64         ::LoadStringW(g_hinstExe, IDS_TOOLTIP1 + i, szToolTip, _countof(szToolTip));
65         tbbutton.iString   = (INT_PTR)szToolTip;
66         tbbutton.fsState   = TBSTATE_ENABLED | ((i % 2 == 1) ? TBSTATE_WRAP : 0);
67         tbbutton.idCommand = ID_FREESEL + i;
68         tbbutton.iBitmap   = i;
69         SendMessage(TB_ADDBUTTONS, 1, (LPARAM) &tbbutton);
70     }
71 
72     SendMessage(TB_CHECKBUTTON, ID_PEN, MAKELPARAM(TRUE, 0));
73     SendMessage(TB_SETMAXTEXTROWS, 0, 0);
74     SendMessage(TB_SETBUTTONSIZE, 0, MAKELPARAM(CXY_TB_BUTTON, CXY_TB_BUTTON));
75 
76     SetWindowLongPtr(GWLP_USERDATA, SetWindowLongPtr(GWLP_WNDPROC, (LONG_PTR)ToolBarWndProc));
77     return TRUE;
78 }
79 
DoCreate(HWND hwndParent)80 BOOL CToolBox::DoCreate(HWND hwndParent)
81 {
82     RECT rcToolBox = { 0, 0, 0, 0 }; // Rely on mainWindow's WM_SIZE
83     DWORD style = WS_CHILD | (registrySettings.ShowToolBox ? WS_VISIBLE : 0);
84     return !!Create(hwndParent, rcToolBox, NULL, style);
85 }
86 
OnCreate(UINT nMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)87 LRESULT CToolBox::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
88 {
89     toolbar.DoCreate(m_hWnd);
90     toolSettingsWindow.DoCreate(m_hWnd);
91     return 0;
92 }
93 
OnSysColorChange(UINT nMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)94 LRESULT CToolBox::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
95 {
96     toolbar.SendMessage(WM_SYSCOLORCHANGE, 0, 0);
97     return 0;
98 }
99 
100 struct COMMAND_TO_TOOL
101 {
102     UINT id;
103     TOOLTYPE tool;
104 };
105 
106 static const COMMAND_TO_TOOL CommandToToolMapping[] =
107 {
108     { ID_FREESEL, TOOL_FREESEL },
109     { ID_RECTSEL, TOOL_RECTSEL },
110     { ID_RUBBER, TOOL_RUBBER },
111     { ID_FILL, TOOL_FILL },
112     { ID_COLOR, TOOL_COLOR },
113     { ID_ZOOM, TOOL_ZOOM },
114     { ID_PEN, TOOL_PEN },
115     { ID_BRUSH, TOOL_BRUSH },
116     { ID_AIRBRUSH, TOOL_AIRBRUSH },
117     { ID_TEXT, TOOL_TEXT },
118     { ID_LINE, TOOL_LINE },
119     { ID_BEZIER, TOOL_BEZIER },
120     { ID_RECT, TOOL_RECT },
121     { ID_SHAPE, TOOL_SHAPE },
122     { ID_ELLIPSE, TOOL_ELLIPSE },
123     { ID_RRECT, TOOL_RRECT },
124 };
125 static_assert(_countof(CommandToToolMapping) == TOOL_MAX, "Logical error");
126 
OnCommand(UINT nMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)127 LRESULT CToolBox::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
128 {
129     UINT id = LOWORD(wParam);
130     for (size_t i = 0; i < _countof(CommandToToolMapping); ++i)
131     {
132         if (CommandToToolMapping[i].id == id)
133         {
134             toolsModel.SetActiveTool(CommandToToolMapping[i].tool);
135             break;
136         }
137     }
138     return 0;
139 }
140 
OnToolsModelToolChanged(UINT nMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)141 LRESULT CToolBox::OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
142 {
143     selectionModel.HideSelection();
144     toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
145 
146     // Check the toolbar button
147     TOOLTYPE tool = toolsModel.GetActiveTool();
148     for (size_t i = 0; i < _countof(CommandToToolMapping); ++i)
149     {
150         if (CommandToToolMapping[i].tool == tool)
151         {
152             toolbar.SendMessage(TB_CHECKBUTTON, CommandToToolMapping[i].id, TRUE);
153             break;
154         }
155     }
156 
157     return 0;
158 }
159 
OnLButtonDown(UINT nMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)160 LRESULT CToolBox::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
161 {
162     SetCapture();
163     return 0;
164 }
165 
OnMouseMove(UINT nMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)166 LRESULT CToolBox::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
167 {
168     if (::GetCapture() != m_hWnd)
169         return 0;
170     POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
171     ClientToScreen(&pt);
172 
173     RECT rc;
174     mainWindow.GetWindowRect(&rc);
175 
176     POINT ptCenter = { (rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2 };
177 
178     DWORD dwExpectedBar2ID = ((pt.x < ptCenter.x) ? BAR2ID_LEFT : BAR2ID_RIGHT);
179 
180     if (registrySettings.Bar2ID != dwExpectedBar2ID)
181     {
182         registrySettings.Bar2ID = dwExpectedBar2ID;
183         mainWindow.PostMessage(WM_SIZE, 0, 0);
184     }
185 
186     return 0;
187 }
188 
OnLButtonUp(UINT nMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)189 LRESULT CToolBox::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
190 {
191     if (::GetCapture() != m_hWnd)
192         return 0;
193 
194     ::ReleaseCapture();
195     return 0;
196 }
197