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