[MSPAINT]
[reactos.git] / reactos / base / applications / mspaint / selection.cpp
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/selection.cpp
5 * PURPOSE: Window procedure of the selection window
6 * PROGRAMMERS: Benedikt Freisen
7 * Katayama Hirofumi MZ
8 */
9
10 /* INCLUDES *********************************************************/
11
12 #include "precomp.h"
13
14 /* FUNCTIONS ********************************************************/
15
16 const LPCTSTR CSelectionWindow::m_lpszCursorLUT[9] = { /* action to mouse cursor lookup table */
17 IDC_SIZEALL,
18
19 IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
20 IDC_SIZEWE, IDC_SIZEWE,
21 IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE
22 };
23
24 BOOL
25 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask, DWORD dwRop, COLORREF keyColor)
26 {
27 HDC hTempDC;
28 HDC hTempDC2;
29 HBITMAP hTempBm;
30 HBRUSH hTempBrush;
31 HBITMAP hTempMask;
32
33 hTempDC = CreateCompatibleDC(hdcSrc);
34 hTempDC2 = CreateCompatibleDC(hdcSrc);
35 hTempBm = CreateCompatibleBitmap(hTempDC, nWidth, nHeight);
36 SelectObject(hTempDC, hTempBm);
37 hTempBrush = CreateSolidBrush(keyColor);
38 SelectObject(hTempDC, hTempBrush);
39 BitBlt(hTempDC, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
40 PatBlt(hTempDC, 0, 0, nWidth, nHeight, PATINVERT);
41 hTempMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
42 SelectObject(hTempDC2, hTempMask);
43 BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, 0, 0, SRCCOPY);
44 SelectObject(hTempDC, hbmMask);
45 BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, xMask, yMask, SRCAND);
46 MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hTempMask, xMask, yMask, dwRop);
47 DeleteDC(hTempDC);
48 DeleteDC(hTempDC2);
49 DeleteObject(hTempBm);
50 DeleteObject(hTempBrush);
51 DeleteObject(hTempMask);
52 return TRUE;
53 }
54
55 void
56 ForceRefreshSelectionContents()
57 {
58 if (selectionWindow.IsWindowVisible())
59 {
60 selectionWindow.SendMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(0, 0));
61 selectionWindow.SendMessage(WM_MOUSEMOVE, 0, MAKELPARAM(0, 0));
62 selectionWindow.SendMessage(WM_LBUTTONUP, 0, MAKELPARAM(0, 0));
63 }
64 }
65
66 int CSelectionWindow::IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight)
67 {
68 if (iYPos < 3)
69 {
70 if (iXPos < 3)
71 return ACTION_RESIZE_TOP_LEFT;
72 if ((iXPos < iWidth / 2 + 2) && (iXPos >= iWidth / 2 - 1))
73 return ACTION_RESIZE_TOP;
74 if (iXPos >= iWidth - 3)
75 return ACTION_RESIZE_TOP_RIGHT;
76 }
77 if ((iYPos < iHeight / 2 + 2) && (iYPos >= iHeight / 2 - 1))
78 {
79 if (iXPos < 3)
80 return ACTION_RESIZE_LEFT;
81 if (iXPos >= iWidth - 3)
82 return ACTION_RESIZE_RIGHT;
83 }
84 if (iYPos >= iHeight - 3)
85 {
86 if (iXPos < 3)
87 return ACTION_RESIZE_BOTTOM_LEFT;
88 if ((iXPos < iWidth / 2 + 2) && (iXPos >= iWidth / 2 - 1))
89 return ACTION_RESIZE_BOTTOM;
90 if (iXPos >= iWidth - 3)
91 return ACTION_RESIZE_BOTTOM_RIGHT;
92 }
93 return 0;
94 }
95
96 LRESULT CSelectionWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
97 {
98 if (!m_bMoving)
99 {
100 HDC hDC = GetDC();
101 DefWindowProc(WM_PAINT, wParam, lParam);
102 SelectionFrame(hDC, 1, 1, selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 5,
103 selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 5,
104 m_dwSystemSelectionColor);
105 ReleaseDC(hDC);
106 }
107 return 0;
108 }
109
110 LRESULT CSelectionWindow::OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
111 {
112 // do nothing => transparent background
113 return 0;
114 }
115
116 LRESULT CSelectionWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
117 {
118 m_bMoving = FALSE;
119 m_iAction = ACTION_MOVE;
120 /* update the system selection color */
121 m_dwSystemSelectionColor = GetSysColor(COLOR_HIGHLIGHT);
122 SendMessage(WM_PAINT, 0, MAKELPARAM(0, 0));
123 return 0;
124 }
125
126 LRESULT CSelectionWindow::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
127 {
128 /* update the system selection color */
129 m_dwSystemSelectionColor = GetSysColor(COLOR_HIGHLIGHT);
130 SendMessage(WM_PAINT, 0, MAKELPARAM(0, 0));
131 return 0;
132 }
133
134 LRESULT CSelectionWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
135 {
136 SetCursor(LoadCursor(NULL, IDC_SIZEALL));
137 return 0;
138 }
139
140 LRESULT CSelectionWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
141 {
142 m_ptPos.x = GET_X_LPARAM(lParam);
143 m_ptPos.y = GET_Y_LPARAM(lParam);
144 m_ptDelta.x = 0;
145 m_ptDelta.y = 0;
146 SetCapture();
147 if (m_iAction != ACTION_MOVE)
148 SetCursor(LoadCursor(NULL, m_lpszCursorLUT[m_iAction]));
149 m_bMoving = TRUE;
150 scrlClientWindow.InvalidateRect(NULL, TRUE);
151 imageArea.SendMessage(WM_PAINT, 0, 0);
152 return 0;
153 }
154
155 LRESULT CSelectionWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
156 {
157 if (m_bMoving)
158 {
159 imageModel.ResetToPrevious();
160 m_ptFrac.x += GET_X_LPARAM(lParam) - m_ptPos.x;
161 m_ptFrac.y += GET_Y_LPARAM(lParam) - m_ptPos.y;
162 m_ptDelta.x += m_ptFrac.x * 1000 / toolsModel.GetZoom();
163 m_ptDelta.y += m_ptFrac.y * 1000 / toolsModel.GetZoom();
164 if (toolsModel.GetZoom() < 1000)
165 {
166 m_ptFrac.x = 0;
167 m_ptFrac.y = 0;
168 }
169 else
170 {
171 m_ptFrac.x -= (m_ptFrac.x * 1000 / toolsModel.GetZoom()) * toolsModel.GetZoom() / 1000;
172 m_ptFrac.y -= (m_ptFrac.y * 1000 / toolsModel.GetZoom()) * toolsModel.GetZoom() / 1000;
173 }
174 selectionModel.ModifyDestRect(m_ptDelta, m_iAction);
175
176 CString strSize;
177 strSize.Format(_T("%d x %d"), selectionModel.GetDestRectWidth(), selectionModel.GetDestRectHeight());
178 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
179
180 if (toolsModel.GetActiveTool() == TOOL_TEXT)
181 {
182 selectionModel.DrawTextToolText(imageModel.GetDC(), paletteModel.GetFgColor(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
183 }
184 else
185 {
186 if (m_iAction != ACTION_MOVE)
187 selectionModel.DrawSelectionStretched(imageModel.GetDC());
188 else
189 selectionModel.DrawSelection(imageModel.GetDC(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
190 }
191 imageArea.InvalidateRect(NULL, FALSE);
192 imageArea.SendMessage(WM_PAINT, 0, 0);
193 m_ptPos.x = GET_X_LPARAM(lParam);
194 m_ptPos.y = GET_Y_LPARAM(lParam);
195 }
196 else
197 {
198 int w = selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 6;
199 int h = selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 6;
200 m_ptPos.x = GET_X_LPARAM(lParam);
201 m_ptPos.y = GET_Y_LPARAM(lParam);
202 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) NULL);
203 m_iAction = IdentifyCorner(m_ptPos.x, m_ptPos.y, w, h);
204 if (m_iAction != ACTION_MOVE)
205 SetCursor(LoadCursor(NULL, m_lpszCursorLUT[m_iAction]));
206 }
207 return 0;
208 }
209
210 LRESULT CSelectionWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
211 {
212 if (m_bMoving)
213 {
214 m_bMoving = FALSE;
215 ReleaseCapture();
216 if (m_iAction != ACTION_MOVE)
217 {
218 if (toolsModel.GetActiveTool() == TOOL_TEXT)
219 {
220 // FIXME: What to do?
221 }
222 else
223 {
224 selectionModel.ScaleContentsToFit();
225 }
226 }
227 placeSelWin();
228 ShowWindow(SW_HIDE);
229 ShowWindow(SW_SHOW);
230 }
231 return 0;
232 }
233
234 LRESULT CSelectionWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
235 {
236 if (m_bMoving)
237 {
238 m_bMoving = FALSE;
239 if (m_iAction == ACTION_MOVE)
240 {
241 // FIXME: dirty hack
242 placeSelWin();
243 imageModel.Undo();
244 imageModel.Undo();
245 }
246 else
247 {
248 m_iAction = ACTION_MOVE;
249 }
250 ShowWindow(SW_HIDE);
251 }
252 return 0;
253 }
254
255 LRESULT CSelectionWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
256 {
257 if (wParam == VK_ESCAPE)
258 {
259 if (GetCapture() == m_hWnd)
260 {
261 ReleaseCapture();
262 }
263 }
264 return 0;
265 }
266
267 LRESULT CSelectionWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
268 {
269 if (toolsModel.GetActiveTool() == TOOL_TEXT)
270 ForceRefreshSelectionContents();
271 return 0;
272 }
273
274 LRESULT CSelectionWindow::OnToolsModelSettingsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
275 {
276 if (toolsModel.GetActiveTool() == TOOL_FREESEL ||
277 toolsModel.GetActiveTool() == TOOL_RECTSEL ||
278 toolsModel.GetActiveTool() == TOOL_TEXT)
279 ForceRefreshSelectionContents();
280 return 0;
281 }
282
283 LRESULT CSelectionWindow::OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
284 {
285 ForceRefreshSelectionContents();
286 return 0;
287 }