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
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 id = (INT)SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt);
24         ::PostMessage(::GetParent(hwnd), WM_TOOLBARHIT, id, 0);
25     }
26     return ::CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
27 }
28 
29 BOOL CPaintToolBar::DoCreate(HWND hwndParent)
30 {
31     // NOTE: The horizontal line above the toolbar is hidden by CCS_NODIVIDER style.
32     RECT toolbarPos = { 0, 0, CX_TOOLBAR, CY_TOOLBAR };
33     DWORD style = WS_CHILD | WS_VISIBLE | CCS_NOPARENTALIGN | CCS_VERT | CCS_NORESIZE |
34                   TBSTYLE_TOOLTIPS | TBSTYLE_FLAT;
35     if (!CWindow::Create(TOOLBARCLASSNAME, hwndParent, toolbarPos, NULL, style))
36         return FALSE;
37 
38     HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 16, 0);
39     SendMessage(TB_SETIMAGELIST, 0, (LPARAM)hImageList);
40 
41     HBITMAP hbmIcons = (HBITMAP)::LoadImage(g_hinstExe, MAKEINTRESOURCE(IDB_TOOLBARICONS),
42                                             IMAGE_BITMAP, 256, 16, 0);
43     ImageList_AddMasked(hImageList, hbmIcons, RGB(255, 0, 255));
44     ::DeleteObject(hbmIcons);
45 
46     SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
47 
48     TCHAR szToolTip[30];
49     TBBUTTON tbbutton;
50     ZeroMemory(&tbbutton, sizeof(tbbutton));
51     tbbutton.fsStyle = TBSTYLE_CHECKGROUP;
52     for (INT i = 0; i < NUM_TOOLS; i++)
53     {
54         ::LoadString(g_hinstExe, IDS_TOOLTIP1 + i, szToolTip, _countof(szToolTip));
55         tbbutton.iString   = (INT_PTR)szToolTip;
56         tbbutton.fsState   = TBSTATE_ENABLED | ((i % 2 == 1) ? TBSTATE_WRAP : 0);
57         tbbutton.idCommand = ID_FREESEL + i;
58         tbbutton.iBitmap   = i;
59         SendMessage(TB_ADDBUTTONS, 1, (LPARAM) &tbbutton);
60     }
61 
62     SendMessage(TB_CHECKBUTTON, ID_PEN, MAKELPARAM(TRUE, 0));
63     SendMessage(TB_SETMAXTEXTROWS, 0, 0);
64     SendMessage(TB_SETBUTTONSIZE, 0, MAKELPARAM(CXY_TB_BUTTON, CXY_TB_BUTTON));
65 
66     SetWindowLongPtr(GWLP_USERDATA, SetWindowLongPtr(GWLP_WNDPROC, (LONG_PTR)ToolBarWndProc));
67     return TRUE;
68 }
69 
70 BOOL CToolBox::DoCreate(HWND hwndParent)
71 {
72     RECT rcToolBox = { 0, 0, 0, 0 }; // Rely on mainWindow's WM_SIZE
73     DWORD style = WS_CHILD | (registrySettings.ShowToolBox ? WS_VISIBLE : 0);
74     return !!Create(hwndParent, rcToolBox, NULL, style);
75 }
76 
77 LRESULT CToolBox::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
78 {
79     toolbar.DoCreate(m_hWnd);
80     toolSettingsWindow.DoCreate(m_hWnd);
81     return 0;
82 }
83 
84 LRESULT CToolBox::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
85 {
86     toolbar.SendMessage(WM_SYSCOLORCHANGE, 0, 0);
87     return 0;
88 }
89 
90 struct COMMAND_TO_TOOL
91 {
92     UINT id;
93     TOOLTYPE tool;
94 };
95 
96 static const COMMAND_TO_TOOL CommandToToolMapping[] =
97 {
98     { ID_FREESEL, TOOL_FREESEL },
99     { ID_RECTSEL, TOOL_RECTSEL },
100     { ID_RUBBER, TOOL_RUBBER },
101     { ID_FILL, TOOL_FILL },
102     { ID_COLOR, TOOL_COLOR },
103     { ID_ZOOM, TOOL_ZOOM },
104     { ID_PEN, TOOL_PEN },
105     { ID_BRUSH, TOOL_BRUSH },
106     { ID_AIRBRUSH, TOOL_AIRBRUSH },
107     { ID_TEXT, TOOL_TEXT },
108     { ID_LINE, TOOL_LINE },
109     { ID_BEZIER, TOOL_BEZIER },
110     { ID_RECT, TOOL_RECT },
111     { ID_SHAPE, TOOL_SHAPE },
112     { ID_ELLIPSE, TOOL_ELLIPSE },
113     { ID_RRECT, TOOL_RRECT },
114 };
115 
116 LRESULT CToolBox::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
117 {
118     UINT id = LOWORD(wParam);
119     for (size_t i = 0; i < _countof(CommandToToolMapping); ++i)
120     {
121         if (CommandToToolMapping[i].id == id)
122         {
123             toolsModel.SetActiveTool(CommandToToolMapping[i].tool);
124             break;
125         }
126     }
127     return 0;
128 }
129 
130 LRESULT CToolBox::OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
131 {
132     selectionModel.HideSelection();
133     toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
134 
135     // Check the toolbar button
136     TOOLTYPE tool = toolsModel.GetActiveTool();
137     for (size_t i = 0; i < _countof(CommandToToolMapping); ++i)
138     {
139         if (CommandToToolMapping[i].tool == tool)
140         {
141             toolbar.SendMessage(TB_CHECKBUTTON, CommandToToolMapping[i].id, TRUE);
142             break;
143         }
144     }
145 
146     return 0;
147 }
148 
149 LRESULT CToolBox::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
150 {
151     SetCapture();
152     return 0;
153 }
154 
155 LRESULT CToolBox::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
156 {
157     if (::GetCapture() != m_hWnd)
158         return 0;
159     POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
160     ClientToScreen(&pt);
161 
162     RECT rc;
163     mainWindow.GetWindowRect(&rc);
164 
165     POINT ptCenter = { (rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2 };
166 
167     DWORD dwExpectedBar2ID = ((pt.x < ptCenter.x) ? BAR2ID_LEFT : BAR2ID_RIGHT);
168 
169     if (registrySettings.Bar2ID != dwExpectedBar2ID)
170     {
171         registrySettings.Bar2ID = dwExpectedBar2ID;
172         mainWindow.PostMessage(WM_SIZE, 0, 0);
173     }
174 
175     return 0;
176 }
177 
178 LRESULT CToolBox::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
179 {
180     if (::GetCapture() != m_hWnd)
181         return 0;
182 
183     ::ReleaseCapture();
184     return 0;
185 }
186 
187 LRESULT CToolBox::OnToolBarHit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
188 {
189     // See also: CPaintToolBar::ToolBarWndProc
190     selectionModel.Landing();
191     return 0;
192 }
193