83adc00c914ed88f36406f29ec5ff75a7ac4a083
[reactos.git] / reactos / base / applications / mspaint / selection.c
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/paint/selection.c
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 LPCTSTR cursors[9] = { IDC_SIZEALL, IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
16 IDC_SIZEWE, IDC_SIZEWE, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE
17 };
18
19 BOOL moving = FALSE;
20 int action = 0;
21 POINTS pos;
22 POINTS frac;
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 (IsWindowVisible(hSelection))
59 {
60 SendMessage(hSelection, WM_LBUTTONDOWN, 0, MAKELPARAM(0, 0));
61 SendMessage(hSelection, WM_MOUSEMOVE, 0, MAKELPARAM(0, 0));
62 SendMessage(hSelection, WM_LBUTTONUP, 0, MAKELPARAM(0, 0));
63 }
64 }
65
66 int
67 identifyCorner(short x, short y, short w, short h)
68 {
69 if (y < 3)
70 {
71 if (x < 3)
72 return 1;
73 if ((x < w / 2 + 2) && (x >= w / 2 - 1))
74 return 2;
75 if (x >= w - 3)
76 return 3;
77 }
78 if ((y < h / 2 + 2) && (y >= h / 2 - 1))
79 {
80 if (x < 3)
81 return 4;
82 if (x >= w - 3)
83 return 5;
84 }
85 if (y >= h - 3)
86 {
87 if (x < 3)
88 return 6;
89 if ((x < w / 2 + 2) && (x >= w / 2 - 1))
90 return 7;
91 if (x >= w - 3)
92 return 8;
93 }
94 return 0;
95 }
96
97 LRESULT CALLBACK
98 SelectionWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
99 {
100 switch (message)
101 {
102 case WM_PAINT:
103 {
104 if (!moving)
105 {
106 HDC hDC = GetDC(hwnd);
107 DefWindowProc(hwnd, message, wParam, lParam);
108 SelectionFrame(hDC, 1, 1, RECT_WIDTH(rectSel_dest) * zoom / 1000 + 5,
109 RECT_HEIGHT(rectSel_dest) * zoom / 1000 + 5);
110 ReleaseDC(hwnd, hDC);
111 }
112 break;
113 }
114 case WM_LBUTTONDOWN:
115 pos.x = GET_X_LPARAM(lParam);
116 pos.y = GET_Y_LPARAM(lParam);
117 SetCapture(hwnd);
118 if (action != 0)
119 SetCursor(LoadCursor(NULL, cursors[action]));
120 moving = TRUE;
121 break;
122 case WM_MOUSEMOVE:
123 if (moving)
124 {
125 TCHAR sizeStr[100];
126 POINT delta;
127 resetToU1();
128 frac.x += GET_X_LPARAM(lParam) - pos.x;
129 frac.y += GET_Y_LPARAM(lParam) - pos.y;
130 if (zoom < 1000)
131 {
132 delta.x = frac.x * 1000 / zoom;
133 frac.x = 0;
134 delta.y = frac.y * 1000 / zoom;
135 frac.y = 0;
136 }
137 else
138 {
139 delta.x = frac.x * 1000 / zoom;
140 frac.x -= (frac.x * 1000 / zoom) * zoom / 1000;
141 delta.y = frac.y * 1000 / zoom;
142 frac.y -= (frac.y * 1000 / zoom) * zoom / 1000;
143 }
144 switch (action)
145 {
146 /* TODO: make sure that the selection is at least 1 pixel wide and high */
147 case 0: /* move selection */
148 OffsetRect(&rectSel_dest, delta.x, delta.y);
149 break;
150 case 1: /* resize at upper left corner */
151 rectSel_dest.left += delta.x;
152 rectSel_dest.top += delta.y;
153 break;
154 case 2: /* resize at top edge */
155 rectSel_dest.top += delta.y;
156 break;
157 case 3: /* resize at upper right corner */
158 rectSel_dest.top += delta.y;
159 rectSel_dest.right += delta.x;
160 break;
161 case 4: /* resize at left edge */
162 rectSel_dest.left += delta.x;
163 break;
164 case 5: /* resize at right edge */
165 rectSel_dest.right += delta.x;
166 break;
167 case 6: /* resize at lower left corner */
168 rectSel_dest.left += delta.x;
169 rectSel_dest.bottom += delta.y;
170 break;
171 case 7: /* resize at bottom edge */
172 rectSel_dest.bottom += delta.y;
173 break;
174 case 8: /* resize at lower right corner */
175 rectSel_dest.right += delta.x;
176 rectSel_dest.bottom += delta.y;
177 break;
178 }
179
180 _stprintf(sizeStr, _T("%d x %d"), RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest));
181 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) sizeStr);
182
183 if (activeTool == 10) /* text tool */
184 {
185 Text(hDrawingDC, rectSel_dest.left, rectSel_dest.top, rectSel_dest.right, rectSel_dest.bottom, fgColor, bgColor, textToolText, hfontTextFont, transpBg);
186 }
187 else
188 {
189 if (action != 0)
190 StretchBlt(hDrawingDC, rectSel_dest.left, rectSel_dest.top, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC, 0, 0, GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY);
191 else
192 if (transpBg == 0)
193 MaskBlt(hDrawingDC, rectSel_dest.left, rectSel_dest.top, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest),
194 hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
195 else
196 {
197 ColorKeyedMaskBlt(hDrawingDC, rectSel_dest.left, rectSel_dest.top, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest),
198 hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND), bgColor);
199 }
200 }
201 InvalidateRect(hImageArea, NULL, FALSE);
202 pos.x = GET_X_LPARAM(lParam);
203 pos.y = GET_Y_LPARAM(lParam);
204 //SendMessage(hwnd, WM_PAINT, 0, 0);
205 }
206 else
207 {
208 int w = RECT_WIDTH(rectSel_dest) * zoom / 1000 + 6;
209 int h = RECT_HEIGHT(rectSel_dest) * zoom / 1000 + 6;
210 pos.x = GET_X_LPARAM(lParam);
211 pos.y = GET_Y_LPARAM(lParam);
212 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) NULL);
213 action = identifyCorner(pos.x, pos.y, w, h);
214 if (action != 0)
215 SetCursor(LoadCursor(NULL, cursors[action]));
216 }
217 break;
218 case WM_LBUTTONUP:
219 if (moving)
220 {
221 moving = FALSE;
222 ReleaseCapture();
223 if (action != 0)
224 {
225 if (activeTool == 10) /* text tool */
226 {
227
228 }
229 else
230 {
231 HDC hTempDC;
232 HBITMAP hTempBm;
233 hTempDC = CreateCompatibleDC(hSelDC);
234 hTempBm = CreateDIBWithProperties(RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest));
235 SelectObject(hTempDC, hTempBm);
236 SelectObject(hSelDC, hSelBm);
237 StretchBlt(hTempDC, 0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC, 0, 0,
238 GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY);
239 DeleteObject(hSelBm);
240 hSelBm = hTempBm;
241 hTempBm = CreateBitmap(RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), 1, 1, NULL);
242 SelectObject(hTempDC, hTempBm);
243 SelectObject(hSelDC, hSelMask);
244 StretchBlt(hTempDC, 0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC, 0, 0,
245 GetDIBWidth(hSelMask), GetDIBHeight(hSelMask), SRCCOPY);
246 DeleteObject(hSelMask);
247 hSelMask = hTempBm;
248 SelectObject(hSelDC, hSelBm);
249 DeleteDC(hTempDC);
250 }
251 }
252 placeSelWin();
253 ShowWindow(hSelection, SW_HIDE);
254 ShowWindow(hSelection, SW_SHOW);
255 }
256 break;
257 default:
258 return DefWindowProc(hwnd, message, wParam, lParam);
259 }
260
261 return 0;
262 }