1 /* 2 * ReactOS User32 Library 3 * - Various drawing functions 4 * 5 * Copyright 2001 Casper S. Hournstroup 6 * Copyright 2003 Andrew Greenwood 7 * Copyright 2003 Filip Navara 8 * Copyright 2009 Matthias Kupfer 9 * Copyright 2017 Katayama Hirofumi MZ 10 * 11 * Based on Wine code. 12 * 13 * Copyright 1993, 1994 Alexandre Julliard 14 * Copyright 2002 Bill Medland 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation; either version 2 of the License, or 19 * (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29 */ 30 31 #include <user32.h> 32 33 WINE_DEFAULT_DEBUG_CHANNEL(user32); 34 35 /* GLOBALS *******************************************************************/ 36 37 /* These tables are used in: 38 * UITOOLS_DrawDiagEdge() 39 * UITOOLS_DrawRectEdge() 40 */ 41 static const signed char LTInnerNormal[] = { 42 -1, -1, -1, -1, 43 -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1, 44 -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1, 45 -1, -1, -1, -1 46 }; 47 48 static const signed char LTOuterNormal[] = { 49 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, 50 COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, 51 COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, 52 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1 53 }; 54 55 static const signed char RBInnerNormal[] = { 56 -1, -1, -1, -1, 57 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, 58 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, 59 -1, -1, -1, -1 60 }; 61 62 static const signed char RBOuterNormal[] = { 63 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, 64 COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, 65 COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, 66 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1 67 }; 68 69 static const signed char LTInnerSoft[] = { 70 -1, -1, -1, -1, 71 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, 72 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, 73 -1, -1, -1, -1 74 }; 75 76 static const signed char LTOuterSoft[] = { 77 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, 78 COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, 79 COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, 80 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1 81 }; 82 83 #define RBInnerSoft RBInnerNormal /* These are the same */ 84 #define RBOuterSoft RBOuterNormal 85 86 static const signed char LTRBOuterMono[] = { 87 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, 88 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, 89 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, 90 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, 91 }; 92 93 static const signed char LTRBInnerMono[] = { 94 -1, -1, -1, -1, 95 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, 96 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, 97 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, 98 }; 99 100 static const signed char LTRBOuterFlat[] = { 101 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, 102 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, 103 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, 104 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, 105 }; 106 107 static const signed char LTRBInnerFlat[] = { 108 -1, -1, -1, -1, 109 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, 110 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, 111 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, 112 }; 113 /* FUNCTIONS *****************************************************************/ 114 115 116 HBRUSH WINAPI GetSysColorBrush(int nIndex); 117 118 /* Ported from WINE20020904 */ 119 /* Same as DrawEdge invoked with BF_DIAGONAL */ 120 static BOOL IntDrawDiagEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags) 121 { 122 POINT Points[4]; 123 signed char InnerI, OuterI; 124 HPEN InnerPen, OuterPen; 125 POINT SavePoint; 126 HPEN SavePen; 127 int spx, spy; 128 int epx, epy; 129 int Width = rc->right - rc->left; 130 int Height= rc->bottom - rc->top; 131 int SmallDiam = Width > Height ? Height : Width; 132 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER 133 || (uType & BDR_OUTER) == BDR_OUTER) 134 && !(uFlags & (BF_FLAT|BF_MONO)) ); 135 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0) 136 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0); 137 138 /* Init some vars */ 139 OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN); 140 SavePen = (HPEN)SelectObject(hdc, InnerPen); 141 spx = spy = epx = epy = 0; /* Satisfy the compiler... */ 142 143 /* Determine the colors of the edges */ 144 if(uFlags & BF_MONO) 145 { 146 InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; 147 OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; 148 } 149 else if(uFlags & BF_FLAT) 150 { 151 InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; 152 OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; 153 } 154 else if(uFlags & BF_SOFT) 155 { 156 if(uFlags & BF_BOTTOM) 157 { 158 InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; 159 OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; 160 } 161 else 162 { 163 InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; 164 OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; 165 } 166 } 167 else 168 { 169 if(uFlags & BF_BOTTOM) 170 { 171 InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; 172 OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; 173 } 174 else 175 { 176 InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; 177 OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; 178 } 179 } 180 181 if(InnerI != -1) InnerPen = GetStockObject(DC_PEN); 182 if(OuterI != -1) OuterPen = GetStockObject(DC_PEN); 183 184 MoveToEx(hdc, 0, 0, &SavePoint); 185 186 /* Don't ask me why, but this is what is visible... */ 187 /* This must be possible to do much simpler, but I fail to */ 188 /* see the logic in the MS implementation (sigh...). */ 189 /* So, this might look a bit brute force here (and it is), but */ 190 /* it gets the job done;) */ 191 192 switch(uFlags & BF_RECT) 193 { 194 case 0: 195 case BF_LEFT: 196 case BF_BOTTOM: 197 case BF_BOTTOMLEFT: 198 /* Left bottom endpoint */ 199 epx = rc->left-1; 200 spx = epx + SmallDiam; 201 epy = rc->bottom; 202 spy = epy - SmallDiam; 203 break; 204 205 case BF_TOPLEFT: 206 case BF_BOTTOMRIGHT: 207 /* Left top endpoint */ 208 epx = rc->left-1; 209 spx = epx + SmallDiam; 210 epy = rc->top-1; 211 spy = epy + SmallDiam; 212 break; 213 214 case BF_TOP: 215 case BF_RIGHT: 216 case BF_TOPRIGHT: 217 case BF_RIGHT|BF_LEFT: 218 case BF_RIGHT|BF_LEFT|BF_TOP: 219 case BF_BOTTOM|BF_TOP: 220 case BF_BOTTOM|BF_TOP|BF_LEFT: 221 case BF_BOTTOMRIGHT|BF_LEFT: 222 case BF_BOTTOMRIGHT|BF_TOP: 223 case BF_RECT: 224 /* Right top endpoint */ 225 spx = rc->left; 226 epx = spx + SmallDiam; 227 spy = rc->bottom-1; 228 epy = spy - SmallDiam; 229 break; 230 } 231 232 MoveToEx(hdc, spx, spy, NULL); 233 SelectObject(hdc, OuterPen); 234 SetDCPenColor(hdc, GetSysColor(OuterI)); 235 LineTo(hdc, epx, epy); 236 237 SelectObject(hdc, InnerPen); 238 SetDCPenColor(hdc, GetSysColor(InnerI)); 239 240 switch(uFlags & (BF_RECT|BF_DIAGONAL)) 241 { 242 case BF_DIAGONAL_ENDBOTTOMLEFT: 243 case (BF_DIAGONAL|BF_BOTTOM): 244 case BF_DIAGONAL: 245 case (BF_DIAGONAL|BF_LEFT): 246 MoveToEx(hdc, spx-1, spy, NULL); 247 LineTo(hdc, epx, epy-1); 248 Points[0].x = spx-add; 249 Points[0].y = spy; 250 Points[1].x = rc->left; 251 Points[1].y = rc->top; 252 Points[2].x = epx+1; 253 Points[2].y = epy-1-add; 254 Points[3] = Points[2]; 255 break; 256 257 case BF_DIAGONAL_ENDBOTTOMRIGHT: 258 MoveToEx(hdc, spx-1, spy, NULL); 259 LineTo(hdc, epx, epy+1); 260 Points[0].x = spx-add; 261 Points[0].y = spy; 262 Points[1].x = rc->left; 263 Points[1].y = rc->bottom-1; 264 Points[2].x = epx+1; 265 Points[2].y = epy+1+add; 266 Points[3] = Points[2]; 267 break; 268 269 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP): 270 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT): 271 case BF_DIAGONAL_ENDTOPRIGHT: 272 case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT): 273 MoveToEx(hdc, spx+1, spy, NULL); 274 LineTo(hdc, epx, epy+1); 275 Points[0].x = epx-1; 276 Points[0].y = epy+1+add; 277 Points[1].x = rc->right-1; 278 Points[1].y = rc->top+add; 279 Points[2].x = rc->right-1; 280 Points[2].y = rc->bottom-1; 281 Points[3].x = spx+add; 282 Points[3].y = spy; 283 break; 284 285 case BF_DIAGONAL_ENDTOPLEFT: 286 MoveToEx(hdc, spx, spy-1, NULL); 287 LineTo(hdc, epx+1, epy); 288 Points[0].x = epx+1+add; 289 Points[0].y = epy+1; 290 Points[1].x = rc->right-1; 291 Points[1].y = rc->top; 292 Points[2].x = rc->right-1; 293 Points[2].y = rc->bottom-1-add; 294 Points[3].x = spx; 295 Points[3].y = spy-add; 296 break; 297 298 case (BF_DIAGONAL|BF_TOP): 299 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP): 300 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT): 301 MoveToEx(hdc, spx+1, spy-1, NULL); 302 LineTo(hdc, epx, epy); 303 Points[0].x = epx-1; 304 Points[0].y = epy+1; 305 Points[1].x = rc->right-1; 306 Points[1].y = rc->top; 307 Points[2].x = rc->right-1; 308 Points[2].y = rc->bottom-1-add; 309 Points[3].x = spx+add; 310 Points[3].y = spy-add; 311 break; 312 313 case (BF_DIAGONAL|BF_RIGHT): 314 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT): 315 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM): 316 MoveToEx(hdc, spx, spy, NULL); 317 LineTo(hdc, epx-1, epy+1); 318 Points[0].x = spx; 319 Points[0].y = spy; 320 Points[1].x = rc->left; 321 Points[1].y = rc->top+add; 322 Points[2].x = epx-1-add; 323 Points[2].y = epy+1+add; 324 Points[3] = Points[2]; 325 break; 326 } 327 328 /* Fill the interior if asked */ 329 if((uFlags & BF_MIDDLE) && retval) 330 { 331 HBRUSH hbsave; 332 HPEN hpsave; 333 hbsave = (HBRUSH)SelectObject(hdc, GetStockObject(DC_BRUSH)); 334 hpsave = (HPEN)SelectObject(hdc, GetStockObject(DC_PEN)); 335 SetDCBrushColor(hdc, GetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE)); 336 SetDCPenColor(hdc, GetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE)); 337 Polygon(hdc, Points, 4); 338 SelectObject(hdc, hbsave); 339 SelectObject(hdc, hpsave); 340 } 341 342 /* Adjust rectangle if asked */ 343 if(uFlags & BF_ADJUST) 344 { 345 if(uFlags & BF_LEFT) rc->left += add; 346 if(uFlags & BF_RIGHT) rc->right -= add; 347 if(uFlags & BF_TOP) rc->top += add; 348 if(uFlags & BF_BOTTOM) rc->bottom -= add; 349 } 350 351 /* Cleanup */ 352 SelectObject(hdc, SavePen); 353 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL); 354 355 return retval; 356 } 357 358 /* Ported from WINE20020904 */ 359 /* Same as DrawEdge invoked without BF_DIAGONAL 360 * 361 * 23-Nov-1997: Changed by Bertho Stultiens 362 * The width parameter sets the width of each outer and inner edge. 363 * 364 * Well, I started testing this and found out that there are a few things 365 * that weren't quite as win95. The following rewrite should reproduce 366 * win95 results completely. 367 * The colorselection is table-driven to avoid awfull if-statements. 368 * The table below show the color settings. 369 * 370 * Pen selection table for uFlags = 0 371 * 372 * uType | LTI | LTO | RBI | RBO 373 * ------+-------+-------+-------+------- 374 * 0000 | x | x | x | x 375 * 0001 | x | 22 | x | 21 376 * 0010 | x | 16 | x | 20 377 * 0011 | x | x | x | x 378 * ------+-------+-------+-------+------- 379 * 0100 | x | 20 | x | 16 380 * 0101 | 20 | 22 | 16 | 21 381 * 0110 | 20 | 16 | 16 | 20 382 * 0111 | x | x | x | x 383 * ------+-------+-------+-------+------- 384 * 1000 | x | 21 | x | 22 385 * 1001 | 21 | 22 | 22 | 21 386 * 1010 | 21 | 16 | 22 | 20 387 * 1011 | x | x | x | x 388 * ------+-------+-------+-------+------- 389 * 1100 | x | x | x | x 390 * 1101 | x | x (22)| x | x (21) 391 * 1110 | x | x (16)| x | x (20) 392 * 1111 | x | x | x | x 393 * 394 * Pen selection table for uFlags = BF_SOFT 395 * 396 * uType | LTI | LTO | RBI | RBO 397 * ------+-------+-------+-------+------- 398 * 0000 | x | x | x | x 399 * 0001 | x | 20 | x | 21 400 * 0010 | x | 21 | x | 20 401 * 0011 | x | x | x | x 402 * ------+-------+-------+-------+------- 403 * 0100 | x | 22 | x | 16 404 * 0101 | 22 | 20 | 16 | 21 405 * 0110 | 22 | 21 | 16 | 20 406 * 0111 | x | x | x | x 407 * ------+-------+-------+-------+------- 408 * 1000 | x | 16 | x | 22 409 * 1001 | 16 | 20 | 22 | 21 410 * 1010 | 16 | 21 | 22 | 20 411 * 1011 | x | x | x | x 412 * ------+-------+-------+-------+------- 413 * 1100 | x | x | x | x 414 * 1101 | x | x (20)| x | x (21) 415 * 1110 | x | x (21)| x | x (20) 416 * 1111 | x | x | x | x 417 * 418 * x = don't care; (n) = is what win95 actually uses 419 * LTI = left Top Inner line 420 * LTO = left Top Outer line 421 * RBI = Right Bottom Inner line 422 * RBO = Right Bottom Outer line 423 * 15 = COLOR_BTNFACE 424 * 16 = COLOR_BTNSHADOW 425 * 20 = COLOR_BTNHIGHLIGHT 426 * 21 = COLOR_3DDKSHADOW 427 * 22 = COLOR_3DLIGHT 428 */ 429 static BOOL IntDrawRectEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags, UINT width) 430 { 431 signed char LTInnerI, LTOuterI; 432 signed char RBInnerI, RBOuterI; 433 HBRUSH lti_brush, lto_brush, rbi_brush, rbo_brush; 434 RECT InnerRect = *rc, fill_rect; 435 int lbi_offset = 0, lti_offset = 0, rti_offset = 0, rbi_offset = 0; 436 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER 437 || (uType & BDR_OUTER) == BDR_OUTER) 438 && !(uFlags & (BF_FLAT|BF_MONO)) ); 439 440 lti_brush = lto_brush = rbi_brush = rbo_brush = GetStockObject(NULL_BRUSH); 441 442 /* Determine the colors of the edges */ 443 if(uFlags & BF_MONO) 444 { 445 LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; 446 LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; 447 } 448 else if(uFlags & BF_FLAT) 449 { 450 LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; 451 LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; 452 453 /* Bertho Stultiens states above that this function exactly matches win95 454 * In win98 BF_FLAT rectangles have an inner border same color as the 455 * middle (COLOR_BTNFACE). I believe it's the same for win95 but since 456 * I don't know I go with Bertho and just sets it for win98 until proven 457 * otherwise. 458 * Dennis Björklund, 10 June, 99 459 */ 460 if( LTInnerI != -1 ) LTInnerI = RBInnerI = COLOR_BTNFACE; 461 } 462 else if(uFlags & BF_SOFT) 463 { 464 LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; 465 LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; 466 RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; 467 RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; 468 } 469 else 470 { 471 LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; 472 LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; 473 RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; 474 RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; 475 } 476 477 if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT) lbi_offset = width; 478 if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT) rti_offset = width; 479 if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) rbi_offset = width; 480 if((uFlags & BF_TOPLEFT) == BF_TOPLEFT) lti_offset = width; 481 482 if(LTInnerI != -1) lti_brush = GetSysColorBrush(LTInnerI); 483 if(LTOuterI != -1) lto_brush = GetSysColorBrush(LTOuterI); 484 if(RBInnerI != -1) rbi_brush = GetSysColorBrush(RBInnerI); 485 if(RBOuterI != -1) rbo_brush = GetSysColorBrush(RBOuterI); 486 487 /* Draw the outer edge */ 488 if(uFlags & BF_TOP) 489 { 490 fill_rect = InnerRect; 491 fill_rect.bottom = fill_rect.top + width; 492 FillRect( hdc, &fill_rect, lto_brush ); 493 } 494 if(uFlags & BF_LEFT) 495 { 496 fill_rect = InnerRect; 497 fill_rect.right = fill_rect.left + width; 498 FillRect( hdc, &fill_rect, lto_brush ); 499 } 500 if(uFlags & BF_BOTTOM) 501 { 502 fill_rect = InnerRect; 503 fill_rect.top = fill_rect.bottom - width; 504 FillRect( hdc, &fill_rect, rbo_brush ); 505 } 506 if(uFlags & BF_RIGHT) 507 { 508 fill_rect = InnerRect; 509 fill_rect.left = fill_rect.right - width; 510 FillRect( hdc, &fill_rect, rbo_brush ); 511 } 512 513 /* Draw the inner edge */ 514 if(uFlags & BF_TOP) 515 { 516 SetRect( &fill_rect, InnerRect.left + lti_offset, InnerRect.top + width, 517 InnerRect.right - rti_offset, InnerRect.top + 2 * width ); 518 FillRect( hdc, &fill_rect, lti_brush ); 519 } 520 if(uFlags & BF_LEFT) 521 { 522 SetRect( &fill_rect, InnerRect.left + width, InnerRect.top + lti_offset, 523 InnerRect.left + 2 * width, InnerRect.bottom - lbi_offset ); 524 FillRect( hdc, &fill_rect, lti_brush ); 525 } 526 if(uFlags & BF_BOTTOM) 527 { 528 SetRect( &fill_rect, InnerRect.left + lbi_offset, InnerRect.bottom - 2 * width, 529 InnerRect.right - rbi_offset, InnerRect.bottom - width ); 530 FillRect( hdc, &fill_rect, rbi_brush ); 531 } 532 if(uFlags & BF_RIGHT) 533 { 534 SetRect( &fill_rect, InnerRect.right - 2 * width, InnerRect.top + rti_offset, 535 InnerRect.right - width, InnerRect.bottom - rbi_offset ); 536 FillRect( hdc, &fill_rect, rbi_brush ); 537 } 538 539 if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) ) 540 { 541 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? width : 0) 542 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? width : 0); 543 544 if(uFlags & BF_LEFT) InnerRect.left += add; 545 if(uFlags & BF_RIGHT) InnerRect.right -= add; 546 if(uFlags & BF_TOP) InnerRect.top += add; 547 if(uFlags & BF_BOTTOM) InnerRect.bottom -= add; 548 549 if((uFlags & BF_MIDDLE) && retval) 550 { 551 FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ? 552 COLOR_WINDOW : COLOR_BTNFACE)); 553 } 554 555 if(uFlags & BF_ADJUST) 556 *rc = InnerRect; 557 } 558 559 return retval; 560 } 561 562 /* Ported from WINE20020904 */ 563 /* Utility to create a square rectangle and returning the width */ 564 static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst) 565 { 566 int Width = src->right - src->left; 567 int Height = src->bottom - src->top; 568 int SmallDiam = Width > Height ? Height : Width; 569 570 *dst = *src; 571 572 /* Make it a square box */ 573 if(Width < Height) /* SmallDiam == Width */ 574 { 575 dst->top += (Height-Width)/2; 576 dst->bottom = dst->top + SmallDiam; 577 } 578 else if(Width > Height) /* SmallDiam == Height */ 579 { 580 dst->left += (Width-Height)/2; 581 dst->right = dst->left + SmallDiam; 582 } 583 584 return SmallDiam; 585 } 586 587 /* Ported from WINE20020904 */ 588 static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect ) 589 { 590 if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255)) 591 { 592 HBRUSH hbsave; 593 COLORREF bg; 594 595 FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE)); 596 bg = SetBkColor(dc, RGB(255, 255, 255)); 597 hbsave = (HBRUSH)SelectObject(dc, gpsi->hbrGray); 598 PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089); 599 SelectObject(dc, hbsave); 600 SetBkColor(dc, bg); 601 } 602 else 603 { 604 FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); 605 } 606 } 607 608 /* Ported from WINE20020904 */ 609 /* Draw a push button coming from DrawFrameControl() 610 * 611 * Does a pretty good job in emulating MS behavior. Some quirks are 612 * however there because MS uses a TrueType font (Marlett) to draw 613 * the buttons. 614 * 615 * FIXME: This looks a little bit strange, needs to be rewritten completely 616 * (several quirks with adjust, DFCS_CHECKED aso) 617 */ 618 static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags) 619 { 620 UINT edge; 621 RECT myr = *r; 622 623 if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT)) 624 edge = EDGE_SUNKEN; 625 else 626 edge = EDGE_RAISED; 627 628 if(uFlags & DFCS_CHECKED) 629 { 630 if(uFlags & DFCS_MONO) 631 IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST, 1); 632 else 633 IntDrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST, 1); 634 635 UITOOLS_DrawCheckedRect( dc, &myr ); 636 } 637 else 638 { 639 if(uFlags & DFCS_MONO) 640 { 641 IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST, 1); 642 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE)); 643 } 644 else 645 { 646 IntDrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT | BF_SOFT, 1); 647 } 648 } 649 650 /* Adjust rectangle if asked */ 651 if(uFlags & DFCS_ADJUSTRECT) 652 InflateRect(r, -2, -2); 653 654 return TRUE; 655 } 656 657 static BOOL UITOOLS95_DFC_ButtonCheckRadio(HDC dc, LPRECT r, UINT uFlags, BOOL Radio) 658 { 659 LOGFONTW lf; 660 HFONT hFont, hOldFont; 661 int i; 662 TCHAR OutRight, OutLeft, InRight, InLeft, Center; 663 INT X, Y, Width, Height, Shorter; 664 INT BkMode = GetBkMode(dc); 665 COLORREF TextColor = GetTextColor(dc); 666 667 Width = r->right - r->left; 668 Height = r->bottom - r->top; 669 Shorter = (Width < Height) ? Width : Height; 670 X = r->left + (Width - Shorter) / 2; 671 Y = r->top + (Height - Shorter) / 2; 672 673 if (Radio) 674 { 675 OutRight = 'j'; // Outer right 676 OutLeft = 'k'; // Outer left 677 InRight = 'l'; // inner left 678 InLeft = 'm'; // inner right 679 Center = 'n'; // center 680 } 681 else 682 { 683 OutRight = 'c'; // Outer right 684 OutLeft = 'd'; // Outer left 685 InRight = 'e'; // inner left 686 InLeft = 'f'; // inner right 687 Center = 'g'; // center 688 } 689 690 ZeroMemory(&lf, sizeof(LOGFONTW)); 691 lf.lfHeight = Shorter; 692 lf.lfCharSet = DEFAULT_CHARSET; 693 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 694 if (Radio && ((uFlags & 0xFF) == DFCS_BUTTONRADIOMASK)) 695 { 696 lf.lfQuality = NONANTIALIASED_QUALITY; 697 } 698 hFont = CreateFontIndirect(&lf); 699 hOldFont = SelectObject(dc, hFont); 700 701 if (Radio && ((uFlags & 0xFF) == DFCS_BUTTONRADIOMASK)) 702 { 703 #if 1 704 // FIXME: improve font rendering 705 RECT Rect; 706 HGDIOBJ hbrOld, hpenOld; 707 FillRect(dc, r, (HBRUSH)GetStockObject(WHITE_BRUSH)); 708 SetRect(&Rect, X, Y, X + Shorter, Y + Shorter); 709 InflateRect(&Rect, -(Shorter * 8) / 54, -(Shorter * 8) / 54); 710 hbrOld = SelectObject(dc, GetStockObject(BLACK_BRUSH)); 711 hpenOld = SelectObject(dc, GetStockObject(NULL_PEN)); 712 Ellipse(dc, Rect.left, Rect.top, Rect.right, Rect.bottom); 713 SelectObject(dc, hbrOld); 714 SelectObject(dc, hpenOld); 715 #else 716 SetBkMode(dc, OPAQUE); 717 SetBkColor(dc, RGB(255, 255, 255)); 718 SetTextColor(dc, RGB(0, 0, 0)); 719 TextOut(dc, X, Y, &Center, 1); 720 SetBkMode(dc, TRANSPARENT); 721 TextOut(dc, X, Y, &OutRight, 1); 722 TextOut(dc, X, Y, &OutLeft, 1); 723 TextOut(dc, X, Y, &InRight, 1); 724 TextOut(dc, X, Y, &InLeft, 1); 725 #endif 726 } 727 else 728 { 729 SetBkMode(dc, TRANSPARENT); 730 731 /* Center section, white for active, grey for inactive */ 732 if ((uFlags & (DFCS_INACTIVE | DFCS_PUSHED))) 733 i = COLOR_BTNFACE; 734 else 735 i = COLOR_WINDOW; 736 SetTextColor(dc, GetSysColor(i)); 737 TextOut(dc, X, Y, &Center, 1); 738 739 if (uFlags & (DFCS_FLAT | DFCS_MONO)) 740 { 741 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME)); 742 TextOut(dc, X, Y, &OutRight, 1); 743 TextOut(dc, X, Y, &OutLeft, 1); 744 TextOut(dc, X, Y, &InRight, 1); 745 TextOut(dc, X, Y, &InLeft, 1); 746 } 747 else 748 { 749 SetTextColor(dc, GetSysColor(COLOR_BTNSHADOW)); 750 TextOut(dc, X, Y, &OutRight, 1); 751 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 752 TextOut(dc, X, Y, &OutLeft, 1); 753 SetTextColor(dc, GetSysColor(COLOR_3DDKSHADOW)); 754 TextOut(dc, X, Y, &InRight, 1); 755 SetTextColor(dc, GetSysColor(COLOR_3DLIGHT)); 756 TextOut(dc, X, Y, &InLeft, 1); 757 } 758 759 if (uFlags & DFCS_CHECKED) 760 { 761 TCHAR Check = (Radio) ? 'i' : 'b'; 762 763 SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT)); 764 TextOut(dc, X, Y, &Check, 1); 765 } 766 } 767 768 SelectObject(dc, hOldFont); 769 DeleteObject(hFont); 770 771 SetTextColor(dc, TextColor); 772 SetBkMode(dc, BkMode); 773 774 return TRUE; 775 } 776 777 /* Ported from WINE20020904 */ 778 static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState) 779 { 780 switch(uState & 0xff) 781 { 782 case DFCS_BUTTONPUSH: 783 return UITOOLS95_DFC_ButtonPush(hdc, rc, uState); 784 785 case DFCS_BUTTONCHECK: 786 case DFCS_BUTTON3STATE: 787 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, FALSE); 788 789 case DFCS_BUTTONRADIOIMAGE: 790 case DFCS_BUTTONRADIOMASK: 791 case DFCS_BUTTONRADIO: 792 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE); 793 794 /* 795 default: 796 DbgPrint("Invalid button state=0x%04x\n", uState); 797 */ 798 } 799 800 return FALSE; 801 } 802 803 static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags) 804 { 805 LOGFONTW lf; 806 HFONT hFont, hOldFont; 807 COLORREF clrsave; 808 RECT myr; 809 INT bkmode; 810 TCHAR Symbol; 811 switch(uFlags & 0xff) 812 { 813 case DFCS_CAPTIONCLOSE: 814 Symbol = 'r'; 815 break; 816 case DFCS_CAPTIONHELP: 817 Symbol = 's'; 818 break; 819 case DFCS_CAPTIONMIN: 820 Symbol = '0'; 821 break; 822 case DFCS_CAPTIONMAX: 823 Symbol = '1'; 824 break; 825 case DFCS_CAPTIONRESTORE: 826 Symbol = '2'; 827 break; 828 default: 829 WARN("Invalid caption; flags=0x%04x\n", uFlags); 830 return FALSE; 831 } 832 IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT, 1); 833 ZeroMemory(&lf, sizeof(LOGFONTW)); 834 UITOOLS_MakeSquareRect(r, &myr); 835 myr.left += 1; 836 myr.top += 1; 837 myr.right -= 1; 838 myr.bottom -= 1; 839 if(uFlags & DFCS_PUSHED) 840 OffsetRect(&myr,1,1); 841 lf.lfHeight = myr.bottom - myr.top; 842 lf.lfWidth = 0; 843 lf.lfWeight = FW_NORMAL; 844 lf.lfCharSet = DEFAULT_CHARSET; 845 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 846 hFont = CreateFontIndirect(&lf); 847 /* save font and text color */ 848 hOldFont = SelectObject(dc, hFont); 849 clrsave = GetTextColor(dc); 850 bkmode = GetBkMode(dc); 851 /* set color and drawing mode */ 852 SetBkMode(dc, TRANSPARENT); 853 if(uFlags & DFCS_INACTIVE) 854 { 855 /* draw shadow */ 856 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 857 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1); 858 } 859 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); 860 /* draw selected symbol */ 861 TextOut(dc, myr.left, myr.top, &Symbol, 1); 862 /* restore previous settings */ 863 SetTextColor(dc, clrsave); 864 SelectObject(dc, hOldFont); 865 SetBkMode(dc, bkmode); 866 DeleteObject(hFont); 867 return TRUE; 868 } 869 870 static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags) 871 { 872 LOGFONTW lf; 873 HFONT hFont, hOldFont; 874 COLORREF clrsave; 875 RECT myr; 876 INT bkmode; 877 TCHAR Symbol; 878 switch(uFlags & 0xff) 879 { 880 case DFCS_SCROLLCOMBOBOX: 881 case DFCS_SCROLLDOWN: 882 Symbol = '6'; 883 break; 884 885 case DFCS_SCROLLUP: 886 Symbol = '5'; 887 break; 888 889 case DFCS_SCROLLLEFT: 890 Symbol = '3'; 891 break; 892 893 case DFCS_SCROLLRIGHT: 894 Symbol = '4'; 895 break; 896 897 case DFCS_SCROLLSIZEGRIP: 898 case DFCS_SCROLLSIZEGRIPRIGHT: 899 ZeroMemory(&lf, sizeof(LOGFONTW)); 900 UITOOLS_MakeSquareRect(r, &myr); 901 lf.lfHeight = myr.bottom - myr.top; 902 lf.lfWidth = 0; 903 lf.lfWeight = FW_NORMAL; 904 lf.lfCharSet = DEFAULT_CHARSET; 905 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 906 hFont = CreateFontIndirect(&lf); 907 /* save font and text color */ 908 hOldFont = SelectObject(dc, hFont); 909 clrsave = GetTextColor(dc); 910 bkmode = GetBkMode(dc); 911 /* set color and drawing mode */ 912 SetBkMode(dc, TRANSPARENT); 913 if (!(uFlags & (DFCS_MONO | DFCS_FLAT))) 914 { 915 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 916 /* draw selected symbol */ 917 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x'; 918 TextOut(dc, myr.left, myr.top, &Symbol, 1); 919 SetTextColor(dc, GetSysColor(COLOR_BTNSHADOW)); 920 } else 921 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME)); 922 /* draw selected symbol */ 923 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y'; 924 TextOut(dc, myr.left, myr.top, &Symbol, 1); 925 /* restore previous settings */ 926 SetTextColor(dc, clrsave); 927 SelectObject(dc, hOldFont); 928 SetBkMode(dc, bkmode); 929 DeleteObject(hFont); 930 return TRUE; 931 default: 932 WARN("Invalid scroll; flags=0x%04x\n", uFlags); 933 return FALSE; 934 } 935 IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT, 1); 936 ZeroMemory(&lf, sizeof(LOGFONTW)); 937 UITOOLS_MakeSquareRect(r, &myr); 938 myr.left += 1; 939 myr.top += 1; 940 myr.right -= 1; 941 myr.bottom -= 1; 942 if(uFlags & DFCS_PUSHED) 943 OffsetRect(&myr,1,1); 944 lf.lfHeight = myr.bottom - myr.top; 945 lf.lfWidth = 0; 946 lf.lfWeight = FW_NORMAL; 947 lf.lfCharSet = DEFAULT_CHARSET; 948 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 949 hFont = CreateFontIndirect(&lf); 950 /* save font and text color */ 951 hOldFont = SelectObject(dc, hFont); 952 clrsave = GetTextColor(dc); 953 bkmode = GetBkMode(dc); 954 /* set color and drawing mode */ 955 SetBkMode(dc, TRANSPARENT); 956 if(uFlags & DFCS_INACTIVE) 957 { 958 /* draw shadow */ 959 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 960 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1); 961 } 962 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); 963 /* draw selected symbol */ 964 TextOut(dc, myr.left, myr.top, &Symbol, 1); 965 /* restore previous settings */ 966 SetTextColor(dc, clrsave); 967 SelectObject(dc, hOldFont); 968 SetBkMode(dc, bkmode); 969 DeleteObject(hFont); 970 return TRUE; 971 } 972 973 static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags) 974 { 975 // TODO: DFCS_TRANSPARENT upon DFCS_MENUARROWUP or DFCS_MENUARROWDOWN 976 LOGFONTW lf; 977 HFONT hFont, hOldFont; 978 TCHAR Symbol; 979 RECT myr; 980 INT cxy, nBkMode; 981 cxy = UITOOLS_MakeSquareRect(r, &myr); 982 switch(uFlags & 0xff) 983 { 984 case DFCS_MENUARROWUP: 985 Symbol = '5'; 986 break; 987 988 case DFCS_MENUARROWDOWN: 989 Symbol = '6'; 990 break; 991 992 case DFCS_MENUARROW: 993 Symbol = '8'; 994 break; 995 996 case DFCS_MENUARROWRIGHT: 997 Symbol = 'w'; // FIXME: needs to confirm 998 break; 999 1000 case DFCS_MENUBULLET: 1001 Symbol = 'h'; 1002 break; 1003 1004 case DFCS_MENUCHECK: 1005 Symbol = 'a'; 1006 break; 1007 1008 default: 1009 WARN("Invalid menu; flags=0x%04x\n", uFlags); 1010 return FALSE; 1011 } 1012 /* acquire ressources only if valid menu */ 1013 ZeroMemory(&lf, sizeof(LOGFONTW)); 1014 lf.lfHeight = cxy; 1015 lf.lfWidth = 0; 1016 lf.lfWeight = FW_NORMAL; 1017 lf.lfCharSet = DEFAULT_CHARSET; 1018 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 1019 hFont = CreateFontIndirect(&lf); 1020 /* save font */ 1021 hOldFont = SelectObject(dc, hFont); 1022 1023 if ((uFlags & 0xff) == DFCS_MENUARROWUP || 1024 (uFlags & 0xff) == DFCS_MENUARROWDOWN ) 1025 { 1026 #if 0 1027 if (uFlags & DFCS_INACTIVE) 1028 { 1029 /* draw shadow */ 1030 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 1031 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1); 1032 } 1033 #endif 1034 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); 1035 } 1036 /* draw selected symbol */ 1037 nBkMode = SetBkMode(dc, TRANSPARENT); 1038 TextOut(dc, myr.left, myr.top, &Symbol, 1); 1039 SetBkMode(dc, nBkMode); 1040 /* restore previous settings */ 1041 SelectObject(dc, hOldFont); 1042 DeleteObject(hFont); 1043 return TRUE; 1044 } 1045 1046 BOOL 1047 WINAPI 1048 IntGrayString( 1049 HDC hDC, 1050 HBRUSH hBrush, 1051 GRAYSTRINGPROC lpOutputFunc, 1052 LPARAM lpData, 1053 int nCount, 1054 int X, 1055 int Y, 1056 int nWidth, 1057 int nHeight, 1058 BOOL unicode) 1059 { 1060 // AG: Mostly implemented, but probably won't work properly or return 1061 // correct error codes. I doubt it grays strings either... Untested! 1062 1063 BOOL success = FALSE; 1064 HBRUSH hbsave; 1065 HDC MemDC = NULL; 1066 HBITMAP MemBMP = NULL, OldBMP = NULL; 1067 HBRUSH OldBrush = NULL; 1068 HFONT OldFont = NULL; 1069 RECT r; 1070 COLORREF ForeColor, BackColor; 1071 1072 ForeColor = SetTextColor(hDC, RGB(0, 0, 0)); 1073 BackColor = SetBkColor(hDC, RGB(255, 255, 255)); 1074 1075 if (! hBrush) 1076 { 1077 // The documentation is a little vague on what exactly should happen 1078 // here. Something about using the same brush for window text??? 1079 hBrush = (HBRUSH) GetCurrentObject(hDC, OBJ_BRUSH); 1080 } 1081 1082 if ((nCount == -1) && (! lpOutputFunc)) 1083 return FALSE; 1084 1085 if (! nCount) 1086 { 1087 // TODO: calculate the length (easy enough) 1088 1089 if (unicode) 1090 nCount = lstrlenW((WCHAR*)lpData); 1091 else 1092 nCount = lstrlenA((CHAR*)lpData); 1093 } 1094 1095 if (! nWidth || ! nHeight) 1096 { 1097 SIZE s; 1098 // TODO: calculate the rect 1099 1100 if (unicode) 1101 success = GetTextExtentPoint32W(hDC, (WCHAR*) lpData, nCount, &s); 1102 else 1103 success = GetTextExtentPoint32A(hDC, (CHAR*) lpData, nCount, &s); 1104 1105 if (! success) goto cleanup; 1106 1107 if (! nWidth) nWidth = s.cx; 1108 if (! nHeight) nHeight = s.cy; 1109 } 1110 1111 SetRect(&r, X, Y, X + nWidth, Y + nHeight); 1112 1113 MemDC = CreateCompatibleDC(hDC); 1114 if (! MemDC) goto cleanup; 1115 MemBMP = CreateBitmap(nWidth, nHeight, 1, 1, NULL); 1116 if (! MemBMP) goto cleanup; 1117 OldBMP = SelectObject(MemDC, MemBMP); 1118 if (! OldBMP) goto cleanup; 1119 OldFont = SelectObject(MemDC, GetCurrentObject(hDC, OBJ_FONT)); 1120 if (! OldFont) goto cleanup; 1121 OldBrush = SelectObject(MemDC, hBrush); 1122 if (! OldBrush) goto cleanup; 1123 1124 if (! BitBlt(MemDC, 0, 0, nWidth, nHeight, hDC, X, Y, SRCCOPY)) goto cleanup; 1125 1126 SetTextColor(MemDC, RGB(255, 255, 255)); 1127 SetBkColor(MemDC, RGB(0, 0, 0)); 1128 1129 if (lpOutputFunc) 1130 { 1131 success = lpOutputFunc(MemDC, lpData, nCount); // Set brush etc first? 1132 1133 if ((nCount == -1) && (! success)) 1134 { 1135 // Don't gray (documented behaviour) 1136 success = (BOOL) BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY); 1137 goto cleanup; 1138 } 1139 } 1140 else 1141 { 1142 if (unicode) 1143 success = TextOutW(MemDC, 0, 0, (WCHAR*) lpData, nCount); 1144 else 1145 success = TextOutA(MemDC, 0, 0, (CHAR*) lpData, nCount); 1146 1147 if (! success) goto cleanup; 1148 1149 hbsave = (HBRUSH)SelectObject(MemDC, gpsi->hbrGray); 1150 PatBlt(MemDC, 0, 0, nWidth, nHeight, 0x000A0329); 1151 SelectObject(MemDC, hbsave); 1152 } 1153 1154 if (! BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY)) goto cleanup; 1155 1156 cleanup: 1157 SetTextColor(hDC, ForeColor); 1158 SetBkColor(hDC, BackColor); 1159 1160 if (MemDC) 1161 { 1162 if (OldFont) SelectObject(MemDC, OldFont); 1163 if (OldBrush) SelectObject(MemDC, OldBrush); 1164 if (OldBMP) SelectObject(MemDC, OldBMP); 1165 if (MemBMP) DeleteObject(MemBMP); 1166 DeleteDC(MemDC); 1167 } 1168 1169 return success; 1170 } 1171 1172 /********************************************************************** 1173 * PAINTING_DrawStateJam 1174 * 1175 * Jams in the requested type in the dc 1176 */ 1177 static BOOL PAINTING_DrawStateJam(HDC hdc, UINT opcode, 1178 DRAWSTATEPROC func, LPARAM lp, WPARAM wp, 1179 LPRECT rc, UINT dtflags, BOOL unicode ) 1180 { 1181 HDC memdc; 1182 HBITMAP hbmsave; 1183 BOOL retval; 1184 INT cx = rc->right - rc->left; 1185 INT cy = rc->bottom - rc->top; 1186 1187 switch(opcode) 1188 { 1189 case DST_TEXT: 1190 case DST_PREFIXTEXT: 1191 if(unicode) 1192 return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags); 1193 else 1194 return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags); 1195 1196 case DST_ICON: 1197 return DrawIconEx(hdc, rc->left, rc->top, (HICON)lp, cx, cy, 0, NULL, DI_NORMAL); 1198 1199 case DST_BITMAP: 1200 memdc = CreateCompatibleDC(hdc); 1201 if(!memdc) 1202 return FALSE; 1203 hbmsave = (HBITMAP)SelectObject(memdc, (HBITMAP)lp); 1204 if(!hbmsave) 1205 { 1206 DeleteDC(memdc); 1207 return FALSE; 1208 } 1209 retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY); 1210 SelectObject(memdc, hbmsave); 1211 DeleteDC(memdc); 1212 return retval; 1213 1214 case DST_COMPLEX: 1215 if(func) 1216 { 1217 BOOL bRet; 1218 /* DRAWSTATEPROC assumes that it draws at the center of coordinates */ 1219 1220 OffsetViewportOrgEx(hdc, rc->left, rc->top, NULL); 1221 bRet = func(hdc, lp, wp, cx, cy); 1222 /* Restore origin */ 1223 OffsetViewportOrgEx(hdc, -rc->left, -rc->top, NULL); 1224 return bRet; 1225 } 1226 else 1227 { 1228 return FALSE; 1229 } 1230 } 1231 return FALSE; 1232 } 1233 1234 static BOOL 1235 IntDrawState(HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp, 1236 INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode) 1237 { 1238 HBITMAP hbm, hbmsave; 1239 HFONT hfsave; 1240 HBRUSH hbsave, hbrtmp = 0; 1241 HDC memdc; 1242 RECT rc; 1243 UINT dtflags = DT_NOCLIP; 1244 COLORREF fg, bg; 1245 UINT opcode = flags & 0xf; 1246 INT len = wp; 1247 BOOL retval, tmp; 1248 LOGFONTW lf; 1249 HFONT hFontOriginal, hNaaFont = NULL; 1250 1251 if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len) /* The string is '\0' terminated */ 1252 { 1253 if(unicode) 1254 len = lstrlenW((LPWSTR)lp); 1255 else 1256 len = lstrlenA((LPSTR)lp); 1257 } 1258 1259 hFontOriginal = GetCurrentObject(hdc, OBJ_FONT); 1260 if (flags & (DSS_MONO | DSS_DISABLED)) 1261 { 1262 /* Create a non-antialiased font */ 1263 GetObjectW(hFontOriginal, sizeof(lf), &lf); 1264 lf.lfQuality = NONANTIALIASED_QUALITY; 1265 hNaaFont = CreateFontIndirectW(&lf); 1266 } 1267 1268 /* Find out what size the image has if not given by caller */ 1269 if(!cx || !cy) 1270 { 1271 SIZE s; 1272 BITMAP bm; 1273 1274 switch(opcode) 1275 { 1276 case DST_TEXT: 1277 case DST_PREFIXTEXT: 1278 if(unicode) 1279 retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s); 1280 else 1281 retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s); 1282 if(!retval) 1283 return FALSE; 1284 break; 1285 1286 case DST_ICON: 1287 if(!get_icon_size((HICON)lp, &s)) 1288 return FALSE; 1289 break; 1290 1291 case DST_BITMAP: 1292 if(!GetObjectW((HBITMAP)lp, sizeof(bm), &bm)) 1293 return FALSE; 1294 s.cx = bm.bmWidth; 1295 s.cy = bm.bmHeight; 1296 break; 1297 1298 case DST_COMPLEX: /* cx and cy must be set in this mode */ 1299 return FALSE; 1300 1301 default: 1302 ERR("Invalid opcode: %u\n", opcode); 1303 return FALSE; 1304 } 1305 1306 if(!cx) cx = s.cx; 1307 if(!cy) cy = s.cy; 1308 } 1309 1310 SetRect(&rc, x, y, x + cx, y + cy); 1311 1312 if(flags & DSS_RIGHT) /* This one is not documented in the win32.hlp file */ 1313 dtflags |= DT_RIGHT; 1314 if(opcode == DST_TEXT) 1315 dtflags |= DT_NOPREFIX; 1316 else if(opcode == DST_PREFIXTEXT) 1317 { 1318 if (flags & DSS_HIDEPREFIX) 1319 dtflags |= DT_HIDEPREFIX; 1320 if (flags & DSS_PREFIXONLY) 1321 dtflags |= DT_PREFIXONLY; 1322 } 1323 1324 /* For DSS_NORMAL we just jam in the image and return */ 1325 if((flags & 0x79f0) == DSS_NORMAL) 1326 { 1327 return PAINTING_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode); 1328 } 1329 1330 /* For all other states we need to convert the image to B/W in a local bitmap */ 1331 /* before it is displayed */ 1332 fg = SetTextColor(hdc, RGB(0, 0, 0)); 1333 bg = SetBkColor(hdc, RGB(255, 255, 255)); 1334 hbm = NULL; hbmsave = NULL; 1335 memdc = NULL; hbsave = NULL; 1336 retval = FALSE; /* assume failure */ 1337 1338 /* From here on we must use "goto cleanup" when something goes wrong */ 1339 hbm = CreateBitmap(cx, cy, 1, 1, NULL); 1340 if(!hbm) goto cleanup; 1341 memdc = CreateCompatibleDC(hdc); 1342 if(!memdc) goto cleanup; 1343 hbmsave = (HBITMAP)SelectObject(memdc, hbm); 1344 if(!hbmsave) goto cleanup; 1345 SetRect(&rc, 0, 0, cx, cy); 1346 if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH))) goto cleanup; 1347 SetBkColor(memdc, RGB(255, 255, 255)); 1348 SetTextColor(memdc, RGB(0, 0, 0)); 1349 if (hNaaFont) 1350 hfsave = (HFONT)SelectObject(memdc, hNaaFont); 1351 else 1352 hfsave = (HFONT)SelectObject(memdc, hFontOriginal); 1353 SetLayout( memdc, GetLayout( hdc )); 1354 1355 /* DST_COMPLEX may draw text as well, 1356 * so we must be sure that correct font is selected 1357 */ 1358 if(!hfsave && (opcode <= DST_PREFIXTEXT)) goto cleanup; 1359 tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode); 1360 if(hfsave) SelectObject(memdc, hfsave); 1361 if (hNaaFont) DeleteObject(hNaaFont); 1362 if(!tmp) goto cleanup; 1363 1364 /* This state cause the image to be dithered */ 1365 if(flags & DSS_UNION) 1366 { 1367 hbsave = (HBRUSH)SelectObject(memdc, gpsi->hbrGray); 1368 if(!hbsave) goto cleanup; 1369 tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089); 1370 SelectObject(memdc, hbsave); 1371 if(!tmp) goto cleanup; 1372 } 1373 1374 if (flags & DSS_DISABLED) 1375 hbrtmp = GetSysColorBrush(COLOR_3DHILIGHT); 1376 else if (flags & DSS_DEFAULT) 1377 hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); 1378 1379 /* Draw light or dark shadow */ 1380 if (flags & (DSS_DISABLED|DSS_DEFAULT)) 1381 { 1382 if(!hbrtmp) goto cleanup; 1383 hbsave = (HBRUSH)SelectObject(hdc, hbrtmp); 1384 if(!hbsave) goto cleanup; 1385 if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; 1386 SelectObject(hdc, hbsave); 1387 } 1388 1389 if (flags & DSS_DISABLED) 1390 { 1391 hbr = hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); 1392 if(!hbrtmp) goto cleanup; 1393 } 1394 else if (!hbr) 1395 { 1396 hbr = (HBRUSH)GetStockObject(BLACK_BRUSH); 1397 } 1398 1399 hbsave = (HBRUSH)SelectObject(hdc, hbr); 1400 1401 if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; 1402 1403 retval = TRUE; /* We succeeded */ 1404 1405 cleanup: 1406 SetTextColor(hdc, fg); 1407 SetBkColor(hdc, bg); 1408 1409 if(hbsave) SelectObject(hdc, hbsave); 1410 if(hbmsave) SelectObject(memdc, hbmsave); 1411 if(hbm) DeleteObject(hbm); 1412 if(memdc) DeleteDC(memdc); 1413 1414 return retval; 1415 } 1416 1417 /* 1418 * @implemented 1419 */ 1420 BOOL WINAPI 1421 RealDrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState) 1422 { 1423 if (GetMapMode(hDC) != MM_TEXT) 1424 return FALSE; 1425 1426 switch(uType) 1427 { 1428 case DFC_BUTTON: 1429 return UITOOLS95_DrawFrameButton(hDC, rc, uState); 1430 case DFC_CAPTION: 1431 return UITOOLS95_DrawFrameCaption(hDC, rc, uState); 1432 case DFC_MENU: 1433 return UITOOLS95_DrawFrameMenu(hDC, rc, uState); 1434 #if 0 1435 case DFC_POPUPMENU: 1436 UNIMPLEMENTED; 1437 break; 1438 #endif 1439 case DFC_SCROLL: 1440 return UITOOLS95_DrawFrameScroll(hDC, rc, uState); 1441 } 1442 return FALSE; 1443 } 1444 1445 BOOL WINAPI 1446 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState) 1447 { 1448 BOOL Hook, Ret = FALSE; 1449 1450 LoadUserApiHook(); 1451 1452 Hook = BeginIfHookedUserApiHook(); 1453 1454 /* Bypass SEH and go direct. */ 1455 if (!Hook) return RealDrawFrameControl(hDC, rc, uType, uState); 1456 1457 _SEH2_TRY 1458 { 1459 Ret = guah.DrawFrameControl(hDC, rc, uType, uState); 1460 } 1461 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1462 { 1463 ERR("Got exception in hooked DrawFrameControl!\n"); 1464 } 1465 _SEH2_END; 1466 1467 EndUserApiHook(); 1468 1469 return Ret; 1470 } 1471 1472 /* 1473 * @implemented 1474 */ 1475 BOOL WINAPI 1476 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags) 1477 { 1478 if (flags & BF_DIAGONAL) 1479 return IntDrawDiagEdge(hDC, rc, edge, flags); 1480 else 1481 return IntDrawRectEdge(hDC, rc, edge, flags, 1); 1482 } 1483 1484 /* 1485 * @implemented 1486 */ 1487 BOOL WINAPI 1488 GrayStringA(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, 1489 int nCount, int X, int Y, int nWidth, int nHeight) 1490 { 1491 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, FALSE); 1492 } 1493 1494 /* 1495 * @implemented 1496 */ 1497 BOOL WINAPI 1498 GrayStringW(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, 1499 int nCount, int X, int Y, int nWidth, int nHeight) 1500 { 1501 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, TRUE); 1502 } 1503 1504 /* 1505 * @implemented 1506 */ 1507 BOOL WINAPI 1508 InvertRect(HDC hDC, CONST RECT *lprc) 1509 { 1510 return PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, 1511 lprc->bottom - lprc->top, DSTINVERT); 1512 } 1513 1514 /* 1515 * @implemented 1516 */ 1517 INT WINAPI 1518 FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) 1519 { 1520 HBRUSH oldbrush; 1521 RECT r = *lprc; 1522 1523 if (IsRectEmpty(&r)) return 0; 1524 if (!(oldbrush = SelectObject(hDC, hbr))) return 0; 1525 1526 PatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY); 1527 PatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY); 1528 PatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY); 1529 PatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY); 1530 1531 SelectObject(hDC, oldbrush); 1532 return TRUE; 1533 } 1534 1535 /* 1536 * @implemented 1537 */ 1538 BOOL WINAPI 1539 FlashWindow(HWND hWnd, BOOL bInvert) 1540 { 1541 FLASHWINFO FlashWndInfo; 1542 1543 FlashWndInfo.cbSize = sizeof(FLASHWINFO); 1544 FlashWndInfo.hwnd = hWnd; 1545 FlashWndInfo.dwFlags = !bInvert ? 0 : (FLASHW_TRAY | FLASHW_CAPTION); 1546 FlashWndInfo.uCount = 1; 1547 FlashWndInfo.dwTimeout = 0; 1548 1549 return NtUserFlashWindowEx(&FlashWndInfo); 1550 } 1551 1552 /* 1553 * @implemented 1554 */ 1555 INT WINAPI 1556 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) 1557 { 1558 BOOL Ret; 1559 HBRUSH prevhbr = NULL; 1560 1561 /* Select brush if specified */ 1562 if (hbr) 1563 { 1564 /* Handle system colors */ 1565 if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1)) 1566 hbr = GetSysColorBrush(PtrToUlong(hbr) - 1); 1567 1568 prevhbr = SelectObject(hDC, hbr); 1569 if (prevhbr == NULL) 1570 return (INT)FALSE; 1571 } 1572 1573 Ret = PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, 1574 lprc->bottom - lprc->top, PATCOPY); 1575 1576 /* Select old brush */ 1577 if (prevhbr) 1578 SelectObject(hDC, prevhbr); 1579 1580 return (INT)Ret; 1581 } 1582 1583 /* 1584 * @implemented 1585 */ 1586 BOOL WINAPI 1587 DrawFocusRect(HDC hdc, CONST RECT *rect) 1588 { 1589 HGDIOBJ OldObj; 1590 UINT cx, cy; 1591 1592 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERWIDTH, 0, &cx, 0); 1593 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERHEIGHT, 0, &cy, 0); 1594 1595 OldObj = SelectObject(hdc, gpsi->hbrGray); 1596 1597 /* top */ 1598 PatBlt(hdc, rect->left, rect->top, rect->right - rect->left, cy, PATINVERT); 1599 /* bottom */ 1600 PatBlt(hdc, rect->left, rect->bottom - cy, rect->right - rect->left, cy, PATINVERT); 1601 /* left */ 1602 PatBlt(hdc, rect->left, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT); 1603 /* right */ 1604 PatBlt(hdc, rect->right - cx, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT); 1605 1606 SelectObject(hdc, OldObj); 1607 return TRUE; 1608 } 1609 1610 /* 1611 * @implemented 1612 */ 1613 BOOL WINAPI 1614 DrawStateA(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData, 1615 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags) 1616 { 1617 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, FALSE); 1618 } 1619 1620 /* 1621 * @implemented 1622 */ 1623 BOOL WINAPI 1624 DrawStateW(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData, 1625 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags) 1626 { 1627 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, TRUE); 1628 } 1629