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 index = (INT)::SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt); 24 if (index >= 0) 25 { 26 TBBUTTON button; 27 if (::SendMessage(hwnd, TB_GETBUTTON, index, (LPARAM)&button)) 28 ::PostMessage(::GetParent(hwnd), WM_COMMAND, button.idCommand, 0); 29 } 30 } 31 return ::CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); 32 } 33 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(TOOLBARCLASSNAME, 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)::LoadImage(g_hinstExe, MAKEINTRESOURCE(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 TCHAR 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 ::LoadString(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 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 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 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 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 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 160 LRESULT CToolBox::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 161 { 162 SetCapture(); 163 return 0; 164 } 165 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 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