1 /* 2 * PROJECT: PAINT for ReactOS 3 * LICENSE: LGPL 4 * FILE: base/applications/mspaint/mouse.cpp 5 * PURPOSE: Things which should not be in the mouse event handler itself 6 * PROGRAMMERS: Benedikt Freisen 7 */ 8 9 /* INCLUDES *********************************************************/ 10 11 #include "precomp.h" 12 13 /* FUNCTIONS ********************************************************/ 14 15 void 16 placeSelWin() 17 { 18 selectionWindow.MoveWindow(selectionModel.GetDestRectLeft() * toolsModel.GetZoom() / 1000, selectionModel.GetDestRectTop() * toolsModel.GetZoom() / 1000, 19 selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 6, selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE); 20 selectionWindow.BringWindowToTop(); 21 imageArea.InvalidateRect(NULL, FALSE); 22 } 23 24 void 25 regularize(LONG x0, LONG y0, LONG& x1, LONG& y1) 26 { 27 if (abs(x1 - x0) >= abs(y1 - y0)) 28 y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0)); 29 else 30 x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0)); 31 } 32 33 void 34 roundTo8Directions(LONG x0, LONG y0, LONG& x1, LONG& y1) 35 { 36 if (abs(x1 - x0) >= abs(y1 - y0)) 37 { 38 if (abs(y1 - y0) * 5 < abs(x1 - x0) * 2) 39 y1 = y0; 40 else 41 y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0)); 42 } 43 else 44 { 45 if (abs(x1 - x0) * 5 < abs(y1 - y0) * 2) 46 x1 = x0; 47 else 48 x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0)); 49 } 50 } 51 52 POINT pointStack[256]; 53 short pointSP; 54 55 void 56 startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) 57 { 58 start.x = x; 59 start.y = y; 60 last.x = x; 61 last.y = y; 62 switch (toolsModel.GetActiveTool()) 63 { 64 case TOOL_FREESEL: 65 selectionWindow.ShowWindow(SW_HIDE); 66 selectionModel.ResetPtStack(); 67 selectionModel.PushToPtStack(x, y); 68 break; 69 case TOOL_LINE: 70 case TOOL_RECT: 71 case TOOL_ELLIPSE: 72 case TOOL_RRECT: 73 imageModel.CopyPrevious(); 74 break; 75 case TOOL_RECTSEL: 76 case TOOL_TEXT: 77 imageModel.CopyPrevious(); 78 selectionWindow.ShowWindow(SW_HIDE); 79 selectionModel.SetSrcRectSizeToZero(); 80 break; 81 case TOOL_RUBBER: 82 imageModel.CopyPrevious(); 83 Erase(hdc, x, y, x, y, bg, toolsModel.GetRubberRadius()); 84 break; 85 case TOOL_FILL: 86 imageModel.CopyPrevious(); 87 Fill(hdc, x, y, fg); 88 break; 89 case TOOL_PEN: 90 imageModel.CopyPrevious(); 91 SetPixel(hdc, x, y, fg); 92 break; 93 case TOOL_BRUSH: 94 imageModel.CopyPrevious(); 95 Brush(hdc, x, y, x, y, fg, toolsModel.GetBrushStyle()); 96 break; 97 case TOOL_AIRBRUSH: 98 imageModel.CopyPrevious(); 99 Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth()); 100 break; 101 case TOOL_BEZIER: 102 pointStack[pointSP].x = x; 103 pointStack[pointSP].y = y; 104 if (pointSP == 0) 105 { 106 imageModel.CopyPrevious(); 107 pointSP++; 108 } 109 break; 110 case TOOL_SHAPE: 111 pointStack[pointSP].x = x; 112 pointStack[pointSP].y = y; 113 if (pointSP + 1 >= 2) 114 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE); 115 if (pointSP == 0) 116 { 117 imageModel.CopyPrevious(); 118 pointSP++; 119 } 120 break; 121 } 122 } 123 124 void 125 whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) 126 { 127 switch (toolsModel.GetActiveTool()) 128 { 129 case TOOL_FREESEL: 130 if (selectionModel.PtStackSize() == 1) 131 imageModel.CopyPrevious(); 132 selectionModel.PushToPtStack(max(0, min(x, imageModel.GetWidth())), max(0, min(y, imageModel.GetHeight()))); 133 imageModel.ResetToPrevious(); 134 selectionModel.DrawFramePoly(hdc); 135 break; 136 case TOOL_RECTSEL: 137 case TOOL_TEXT: 138 { 139 POINT temp; 140 imageModel.ResetToPrevious(); 141 temp.x = max(0, min(x, imageModel.GetWidth())); 142 temp.y = max(0, min(y, imageModel.GetHeight())); 143 selectionModel.SetSrcAndDestRectFromPoints(start, temp); 144 RectSel(hdc, start.x, start.y, temp.x, temp.y); 145 break; 146 } 147 case TOOL_RUBBER: 148 Erase(hdc, last.x, last.y, x, y, bg, toolsModel.GetRubberRadius()); 149 break; 150 case TOOL_PEN: 151 Line(hdc, last.x, last.y, x, y, fg, 1); 152 break; 153 case TOOL_BRUSH: 154 Brush(hdc, last.x, last.y, x, y, fg, toolsModel.GetBrushStyle()); 155 break; 156 case TOOL_AIRBRUSH: 157 Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth()); 158 break; 159 case TOOL_LINE: 160 imageModel.ResetToPrevious(); 161 if (GetAsyncKeyState(VK_SHIFT) < 0) 162 roundTo8Directions(start.x, start.y, x, y); 163 Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth()); 164 break; 165 case TOOL_BEZIER: 166 imageModel.ResetToPrevious(); 167 pointStack[pointSP].x = x; 168 pointStack[pointSP].y = y; 169 switch (pointSP) 170 { 171 case 1: 172 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, fg, 173 toolsModel.GetLineWidth()); 174 break; 175 case 2: 176 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], fg, toolsModel.GetLineWidth()); 177 break; 178 case 3: 179 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], fg, toolsModel.GetLineWidth()); 180 break; 181 } 182 break; 183 case TOOL_RECT: 184 imageModel.ResetToPrevious(); 185 if (GetAsyncKeyState(VK_SHIFT) < 0) 186 regularize(start.x, start.y, x, y); 187 Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 188 break; 189 case TOOL_SHAPE: 190 imageModel.ResetToPrevious(); 191 pointStack[pointSP].x = x; 192 pointStack[pointSP].y = y; 193 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) 194 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, 195 pointStack[pointSP].x, pointStack[pointSP].y); 196 if (pointSP + 1 >= 2) 197 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE); 198 break; 199 case TOOL_ELLIPSE: 200 imageModel.ResetToPrevious(); 201 if (GetAsyncKeyState(VK_SHIFT) < 0) 202 regularize(start.x, start.y, x, y); 203 Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 204 break; 205 case TOOL_RRECT: 206 imageModel.ResetToPrevious(); 207 if (GetAsyncKeyState(VK_SHIFT) < 0) 208 regularize(start.x, start.y, x, y); 209 RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 210 break; 211 } 212 213 last.x = x; 214 last.y = y; 215 } 216 217 void 218 endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) 219 { 220 switch (toolsModel.GetActiveTool()) 221 { 222 case TOOL_FREESEL: 223 { 224 selectionModel.CalculateBoundingBoxAndContents(hdc); 225 if (selectionModel.PtStackSize() > 1) 226 { 227 selectionModel.DrawBackgroundPoly(hdc, bg); 228 imageModel.CopyPrevious(); 229 230 selectionModel.DrawSelection(hdc); 231 232 placeSelWin(); 233 selectionWindow.ShowWindow(SW_SHOW); 234 ForceRefreshSelectionContents(); 235 } 236 selectionModel.ResetPtStack(); 237 break; 238 } 239 case TOOL_RECTSEL: 240 imageModel.ResetToPrevious(); 241 if (selectionModel.IsSrcRectSizeNonzero()) 242 { 243 selectionModel.CalculateContents(hdc); 244 selectionModel.DrawBackgroundRect(hdc, bg); 245 imageModel.CopyPrevious(); 246 247 selectionModel.DrawSelection(hdc); 248 249 placeSelWin(); 250 selectionWindow.ShowWindow(SW_SHOW); 251 ForceRefreshSelectionContents(); 252 } 253 break; 254 case TOOL_TEXT: 255 imageModel.ResetToPrevious(); 256 if (selectionModel.IsSrcRectSizeNonzero()) 257 { 258 imageModel.CopyPrevious(); 259 260 placeSelWin(); 261 selectionWindow.ShowWindow(SW_SHOW); 262 ForceRefreshSelectionContents(); 263 } 264 break; 265 case TOOL_RUBBER: 266 Erase(hdc, last.x, last.y, x, y, bg, toolsModel.GetRubberRadius()); 267 break; 268 case TOOL_PEN: 269 Line(hdc, last.x, last.y, x, y, fg, 1); 270 SetPixel(hdc, x, y, fg); 271 break; 272 case TOOL_LINE: 273 imageModel.ResetToPrevious(); 274 if (GetAsyncKeyState(VK_SHIFT) < 0) 275 roundTo8Directions(start.x, start.y, x, y); 276 Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth()); 277 break; 278 case TOOL_BEZIER: 279 pointSP++; 280 if (pointSP == 4) 281 pointSP = 0; 282 break; 283 case TOOL_RECT: 284 imageModel.ResetToPrevious(); 285 if (GetAsyncKeyState(VK_SHIFT) < 0) 286 regularize(start.x, start.y, x, y); 287 Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 288 break; 289 case TOOL_SHAPE: 290 imageModel.ResetToPrevious(); 291 pointStack[pointSP].x = x; 292 pointStack[pointSP].y = y; 293 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) 294 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, 295 pointStack[pointSP].x, pointStack[pointSP].y); 296 pointSP++; 297 if (pointSP >= 2) 298 { 299 if ((pointStack[0].x - x) * (pointStack[0].x - x) + 300 (pointStack[0].y - y) * (pointStack[0].y - y) <= toolsModel.GetLineWidth() * toolsModel.GetLineWidth() + 1) 301 { 302 Poly(hdc, pointStack, pointSP, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), TRUE, FALSE); 303 pointSP = 0; 304 } 305 else 306 { 307 Poly(hdc, pointStack, pointSP, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE); 308 } 309 } 310 if (pointSP == 255) 311 pointSP--; 312 break; 313 case TOOL_ELLIPSE: 314 imageModel.ResetToPrevious(); 315 if (GetAsyncKeyState(VK_SHIFT) < 0) 316 regularize(start.x, start.y, x, y); 317 Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 318 break; 319 case TOOL_RRECT: 320 imageModel.ResetToPrevious(); 321 if (GetAsyncKeyState(VK_SHIFT) < 0) 322 regularize(start.x, start.y, x, y); 323 RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 324 break; 325 } 326 } 327 328 void 329 startPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) 330 { 331 start.x = x; 332 start.y = y; 333 last.x = x; 334 last.y = y; 335 switch (toolsModel.GetActiveTool()) 336 { 337 case TOOL_FREESEL: 338 case TOOL_TEXT: 339 case TOOL_LINE: 340 case TOOL_RECT: 341 case TOOL_ELLIPSE: 342 case TOOL_RRECT: 343 imageModel.CopyPrevious(); 344 break; 345 case TOOL_RUBBER: 346 imageModel.CopyPrevious(); 347 Replace(hdc, x, y, x, y, fg, bg, toolsModel.GetRubberRadius()); 348 break; 349 case TOOL_FILL: 350 imageModel.CopyPrevious(); 351 Fill(hdc, x, y, bg); 352 break; 353 case TOOL_PEN: 354 imageModel.CopyPrevious(); 355 SetPixel(hdc, x, y, bg); 356 break; 357 case TOOL_BRUSH: 358 imageModel.CopyPrevious(); 359 Brush(hdc, x, y, x, y, bg, toolsModel.GetBrushStyle()); 360 break; 361 case TOOL_AIRBRUSH: 362 imageModel.CopyPrevious(); 363 Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth()); 364 break; 365 case TOOL_BEZIER: 366 pointStack[pointSP].x = x; 367 pointStack[pointSP].y = y; 368 if (pointSP == 0) 369 { 370 imageModel.CopyPrevious(); 371 pointSP++; 372 } 373 break; 374 case TOOL_SHAPE: 375 pointStack[pointSP].x = x; 376 pointStack[pointSP].y = y; 377 if (pointSP + 1 >= 2) 378 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE); 379 if (pointSP == 0) 380 { 381 imageModel.CopyPrevious(); 382 pointSP++; 383 } 384 break; 385 } 386 } 387 388 void 389 whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) 390 { 391 switch (toolsModel.GetActiveTool()) 392 { 393 case TOOL_RUBBER: 394 Replace(hdc, last.x, last.y, x, y, fg, bg, toolsModel.GetRubberRadius()); 395 break; 396 case TOOL_PEN: 397 Line(hdc, last.x, last.y, x, y, bg, 1); 398 break; 399 case TOOL_BRUSH: 400 Brush(hdc, last.x, last.y, x, y, bg, toolsModel.GetBrushStyle()); 401 break; 402 case TOOL_AIRBRUSH: 403 Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth()); 404 break; 405 case TOOL_LINE: 406 imageModel.ResetToPrevious(); 407 if (GetAsyncKeyState(VK_SHIFT) < 0) 408 roundTo8Directions(start.x, start.y, x, y); 409 Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth()); 410 break; 411 case TOOL_BEZIER: 412 imageModel.ResetToPrevious(); 413 pointStack[pointSP].x = x; 414 pointStack[pointSP].y = y; 415 switch (pointSP) 416 { 417 case 1: 418 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, bg, 419 toolsModel.GetLineWidth()); 420 break; 421 case 2: 422 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], bg, toolsModel.GetLineWidth()); 423 break; 424 case 3: 425 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], bg, toolsModel.GetLineWidth()); 426 break; 427 } 428 break; 429 case TOOL_RECT: 430 imageModel.ResetToPrevious(); 431 if (GetAsyncKeyState(VK_SHIFT) < 0) 432 regularize(start.x, start.y, x, y); 433 Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 434 break; 435 case TOOL_SHAPE: 436 imageModel.ResetToPrevious(); 437 pointStack[pointSP].x = x; 438 pointStack[pointSP].y = y; 439 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) 440 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, 441 pointStack[pointSP].x, pointStack[pointSP].y); 442 if (pointSP + 1 >= 2) 443 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE); 444 break; 445 case TOOL_ELLIPSE: 446 imageModel.ResetToPrevious(); 447 if (GetAsyncKeyState(VK_SHIFT) < 0) 448 regularize(start.x, start.y, x, y); 449 Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 450 break; 451 case TOOL_RRECT: 452 imageModel.ResetToPrevious(); 453 if (GetAsyncKeyState(VK_SHIFT) < 0) 454 regularize(start.x, start.y, x, y); 455 RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 456 break; 457 } 458 459 last.x = x; 460 last.y = y; 461 } 462 463 void 464 endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) 465 { 466 switch (toolsModel.GetActiveTool()) 467 { 468 case TOOL_RUBBER: 469 Replace(hdc, last.x, last.y, x, y, fg, bg, toolsModel.GetRubberRadius()); 470 break; 471 case TOOL_PEN: 472 Line(hdc, last.x, last.y, x, y, bg, 1); 473 SetPixel(hdc, x, y, bg); 474 break; 475 case TOOL_LINE: 476 imageModel.ResetToPrevious(); 477 if (GetAsyncKeyState(VK_SHIFT) < 0) 478 roundTo8Directions(start.x, start.y, x, y); 479 Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth()); 480 break; 481 case TOOL_BEZIER: 482 pointSP++; 483 if (pointSP == 4) 484 pointSP = 0; 485 break; 486 case TOOL_RECT: 487 imageModel.ResetToPrevious(); 488 if (GetAsyncKeyState(VK_SHIFT) < 0) 489 regularize(start.x, start.y, x, y); 490 Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 491 break; 492 case TOOL_SHAPE: 493 imageModel.ResetToPrevious(); 494 pointStack[pointSP].x = x; 495 pointStack[pointSP].y = y; 496 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) 497 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, 498 pointStack[pointSP].x, pointStack[pointSP].y); 499 pointSP++; 500 if (pointSP >= 2) 501 { 502 if ((pointStack[0].x - x) * (pointStack[0].x - x) + 503 (pointStack[0].y - y) * (pointStack[0].y - y) <= toolsModel.GetLineWidth() * toolsModel.GetLineWidth() + 1) 504 { 505 Poly(hdc, pointStack, pointSP, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), TRUE, FALSE); 506 pointSP = 0; 507 } 508 else 509 { 510 Poly(hdc, pointStack, pointSP, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE); 511 } 512 } 513 if (pointSP == 255) 514 pointSP--; 515 break; 516 case TOOL_ELLIPSE: 517 imageModel.ResetToPrevious(); 518 if (GetAsyncKeyState(VK_SHIFT) < 0) 519 regularize(start.x, start.y, x, y); 520 Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 521 break; 522 case TOOL_RRECT: 523 imageModel.ResetToPrevious(); 524 if (GetAsyncKeyState(VK_SHIFT) < 0) 525 regularize(start.x, start.y, x, y); 526 RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle()); 527 break; 528 } 529 } 530