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-2022 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 SetRect(&Rect, X, Y, X + Shorter, Y + Shorter); 708 InflateRect(&Rect, -(Shorter * 8) / 54, -(Shorter * 8) / 54); 709 hbrOld = SelectObject(dc, GetStockObject(BLACK_BRUSH)); 710 hpenOld = SelectObject(dc, GetStockObject(NULL_PEN)); 711 Ellipse(dc, Rect.left, Rect.top, Rect.right, Rect.bottom); 712 SelectObject(dc, hbrOld); 713 SelectObject(dc, hpenOld); 714 #else 715 SetBkMode(dc, OPAQUE); 716 SetBkColor(dc, RGB(255, 255, 255)); 717 SetTextColor(dc, RGB(0, 0, 0)); 718 TextOut(dc, X, Y, &Center, 1); 719 SetBkMode(dc, TRANSPARENT); 720 TextOut(dc, X, Y, &OutRight, 1); 721 TextOut(dc, X, Y, &OutLeft, 1); 722 TextOut(dc, X, Y, &InRight, 1); 723 TextOut(dc, X, Y, &InLeft, 1); 724 #endif 725 } 726 else 727 { 728 SetBkMode(dc, TRANSPARENT); 729 730 /* Center section, white for active, grey for inactive */ 731 if ((uFlags & (DFCS_INACTIVE | DFCS_PUSHED))) 732 i = COLOR_BTNFACE; 733 else 734 i = COLOR_WINDOW; 735 SetTextColor(dc, GetSysColor(i)); 736 TextOut(dc, X, Y, &Center, 1); 737 738 if (uFlags & (DFCS_FLAT | DFCS_MONO)) 739 { 740 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME)); 741 TextOut(dc, X, Y, &OutRight, 1); 742 TextOut(dc, X, Y, &OutLeft, 1); 743 TextOut(dc, X, Y, &InRight, 1); 744 TextOut(dc, X, Y, &InLeft, 1); 745 } 746 else 747 { 748 SetTextColor(dc, GetSysColor(COLOR_BTNSHADOW)); 749 TextOut(dc, X, Y, &OutRight, 1); 750 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 751 TextOut(dc, X, Y, &OutLeft, 1); 752 SetTextColor(dc, GetSysColor(COLOR_3DDKSHADOW)); 753 TextOut(dc, X, Y, &InRight, 1); 754 SetTextColor(dc, GetSysColor(COLOR_3DLIGHT)); 755 TextOut(dc, X, Y, &InLeft, 1); 756 } 757 758 if (uFlags & DFCS_CHECKED) 759 { 760 TCHAR Check = (Radio) ? 'i' : 'b'; 761 762 SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT)); 763 TextOut(dc, X, Y, &Check, 1); 764 } 765 } 766 767 SelectObject(dc, hOldFont); 768 DeleteObject(hFont); 769 770 SetTextColor(dc, TextColor); 771 SetBkMode(dc, BkMode); 772 773 return TRUE; 774 } 775 776 /* Ported from WINE20020904 */ 777 static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState) 778 { 779 switch(uState & 0x1f) 780 { 781 case DFCS_BUTTONPUSH: 782 return UITOOLS95_DFC_ButtonPush(hdc, rc, uState); 783 784 case DFCS_BUTTONCHECK: 785 case DFCS_BUTTON3STATE: 786 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, FALSE); 787 788 case DFCS_BUTTONRADIOIMAGE: 789 case DFCS_BUTTONRADIOMASK: 790 if (uState & DFCS_BUTTONRADIOIMAGE) 791 FillRect(hdc, rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); /* Fill by black */ 792 else 793 FillRect(hdc, rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); /* Fill by white */ 794 795 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE); 796 797 case DFCS_BUTTONRADIO: 798 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE); 799 800 default: 801 ERR("Invalid button state=0x%04x\n", uState); 802 } 803 804 return FALSE; 805 } 806 807 static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags) 808 { 809 LOGFONTW lf; 810 HFONT hFont, hOldFont; 811 COLORREF clrsave; 812 RECT myr; 813 INT bkmode; 814 TCHAR Symbol; 815 switch(uFlags & 0xf) 816 { 817 case DFCS_CAPTIONCLOSE: 818 Symbol = 'r'; 819 break; 820 case DFCS_CAPTIONHELP: 821 Symbol = 's'; 822 break; 823 case DFCS_CAPTIONMIN: 824 Symbol = '0'; 825 break; 826 case DFCS_CAPTIONMAX: 827 Symbol = '1'; 828 break; 829 case DFCS_CAPTIONRESTORE: 830 Symbol = '2'; 831 break; 832 default: 833 ERR("Invalid caption; flags=0x%04x\n", uFlags); 834 return FALSE; 835 } 836 IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT, 1); 837 ZeroMemory(&lf, sizeof(LOGFONTW)); 838 UITOOLS_MakeSquareRect(r, &myr); 839 myr.left += 1; 840 myr.top += 1; 841 myr.right -= 1; 842 myr.bottom -= 1; 843 if(uFlags & DFCS_PUSHED) 844 OffsetRect(&myr,1,1); 845 lf.lfHeight = myr.bottom - myr.top; 846 lf.lfWidth = 0; 847 lf.lfWeight = FW_NORMAL; 848 lf.lfCharSet = DEFAULT_CHARSET; 849 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 850 hFont = CreateFontIndirect(&lf); 851 /* save font and text color */ 852 hOldFont = SelectObject(dc, hFont); 853 clrsave = GetTextColor(dc); 854 bkmode = GetBkMode(dc); 855 /* set color and drawing mode */ 856 SetBkMode(dc, TRANSPARENT); 857 if(uFlags & DFCS_INACTIVE) 858 { 859 /* draw shadow */ 860 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 861 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1); 862 } 863 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); 864 /* draw selected symbol */ 865 TextOut(dc, myr.left, myr.top, &Symbol, 1); 866 /* restore previous settings */ 867 SetTextColor(dc, clrsave); 868 SelectObject(dc, hOldFont); 869 SetBkMode(dc, bkmode); 870 DeleteObject(hFont); 871 return TRUE; 872 } 873 874 static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags) 875 { 876 LOGFONTW lf; 877 HFONT hFont, hOldFont; 878 COLORREF clrsave; 879 RECT myr; 880 INT bkmode; 881 TCHAR Symbol; 882 switch(uFlags & 0x1f) 883 { 884 case DFCS_SCROLLCOMBOBOX: 885 case DFCS_SCROLLDOWN: 886 Symbol = '6'; 887 break; 888 889 case DFCS_SCROLLUP: 890 Symbol = '5'; 891 break; 892 893 case DFCS_SCROLLLEFT: 894 Symbol = '3'; 895 break; 896 897 case DFCS_SCROLLRIGHT: 898 Symbol = '4'; 899 break; 900 901 case DFCS_SCROLLSIZEGRIP: 902 case DFCS_SCROLLSIZEGRIPRIGHT: 903 ZeroMemory(&lf, sizeof(LOGFONTW)); 904 UITOOLS_MakeSquareRect(r, &myr); 905 lf.lfHeight = myr.bottom - myr.top; 906 lf.lfWidth = 0; 907 lf.lfWeight = FW_NORMAL; 908 lf.lfCharSet = DEFAULT_CHARSET; 909 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 910 hFont = CreateFontIndirect(&lf); 911 /* save font and text color */ 912 hOldFont = SelectObject(dc, hFont); 913 clrsave = GetTextColor(dc); 914 bkmode = GetBkMode(dc); 915 /* set color and drawing mode */ 916 SetBkMode(dc, TRANSPARENT); 917 if (!(uFlags & (DFCS_MONO | DFCS_FLAT))) 918 { 919 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 920 /* draw selected symbol */ 921 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x'; 922 TextOut(dc, myr.left, myr.top, &Symbol, 1); 923 SetTextColor(dc, GetSysColor(COLOR_BTNSHADOW)); 924 } else 925 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME)); 926 /* draw selected symbol */ 927 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y'; 928 TextOut(dc, myr.left, myr.top, &Symbol, 1); 929 /* restore previous settings */ 930 SetTextColor(dc, clrsave); 931 SelectObject(dc, hOldFont); 932 SetBkMode(dc, bkmode); 933 DeleteObject(hFont); 934 return TRUE; 935 default: 936 ERR("Invalid scroll; flags=0x%04x\n", uFlags); 937 return FALSE; 938 } 939 IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT, 1); 940 ZeroMemory(&lf, sizeof(LOGFONTW)); 941 UITOOLS_MakeSquareRect(r, &myr); 942 myr.left += 1; 943 myr.top += 1; 944 myr.right -= 1; 945 myr.bottom -= 1; 946 if(uFlags & DFCS_PUSHED) 947 OffsetRect(&myr,1,1); 948 lf.lfHeight = myr.bottom - myr.top; 949 lf.lfWidth = 0; 950 lf.lfWeight = FW_NORMAL; 951 lf.lfCharSet = DEFAULT_CHARSET; 952 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 953 hFont = CreateFontIndirect(&lf); 954 /* save font and text color */ 955 hOldFont = SelectObject(dc, hFont); 956 clrsave = GetTextColor(dc); 957 bkmode = GetBkMode(dc); 958 /* set color and drawing mode */ 959 SetBkMode(dc, TRANSPARENT); 960 if(uFlags & DFCS_INACTIVE) 961 { 962 /* draw shadow */ 963 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 964 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1); 965 } 966 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); 967 /* draw selected symbol */ 968 TextOut(dc, myr.left, myr.top, &Symbol, 1); 969 /* restore previous settings */ 970 SetTextColor(dc, clrsave); 971 SelectObject(dc, hOldFont); 972 SetBkMode(dc, bkmode); 973 DeleteObject(hFont); 974 return TRUE; 975 } 976 977 static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags) 978 { 979 LOGFONTW lf; 980 HFONT hFont, hOldFont; 981 TCHAR Symbol; 982 RECT myr; 983 INT cxy; 984 cxy = UITOOLS_MakeSquareRect(r, &myr); 985 switch(uFlags & 0x1f) 986 { 987 case DFCS_MENUARROWUP: 988 Symbol = '5'; 989 break; 990 991 case DFCS_MENUARROWDOWN: 992 Symbol = '6'; 993 break; 994 995 case DFCS_MENUARROW: 996 Symbol = '8'; 997 break; 998 999 case DFCS_MENUARROWRIGHT: 1000 Symbol = 'w'; // FIXME: needs to confirm 1001 break; 1002 1003 case DFCS_MENUBULLET: 1004 Symbol = 'h'; 1005 break; 1006 1007 case DFCS_MENUCHECK: 1008 case DFCS_MENUCHECK | DFCS_MENUBULLET: 1009 Symbol = 'a'; 1010 break; 1011 1012 default: 1013 ERR("Invalid menu; flags=0x%04x\n", uFlags); 1014 return FALSE; 1015 } 1016 /* acquire ressources only if valid menu */ 1017 ZeroMemory(&lf, sizeof(LOGFONTW)); 1018 lf.lfHeight = cxy; 1019 lf.lfWidth = 0; 1020 lf.lfWeight = FW_NORMAL; 1021 lf.lfCharSet = DEFAULT_CHARSET; 1022 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 1023 hFont = CreateFontIndirect(&lf); 1024 /* save font */ 1025 hOldFont = SelectObject(dc, hFont); 1026 1027 if ((uFlags & 0x1f) == DFCS_MENUARROWUP || 1028 (uFlags & 0x1f) == DFCS_MENUARROWDOWN ) 1029 { 1030 #if 0 1031 if (uFlags & DFCS_INACTIVE) 1032 { 1033 /* draw shadow */ 1034 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 1035 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1); 1036 } 1037 #endif 1038 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); 1039 } 1040 /* draw selected symbol */ 1041 TextOut(dc, myr.left, myr.top, &Symbol, 1); 1042 /* restore previous settings */ 1043 SelectObject(dc, hOldFont); 1044 DeleteObject(hFont); 1045 return TRUE; 1046 } 1047 1048 BOOL 1049 WINAPI 1050 IntGrayString( 1051 HDC hDC, 1052 HBRUSH hBrush, 1053 GRAYSTRINGPROC lpOutputFunc, 1054 LPARAM lpData, 1055 int nCount, 1056 int X, 1057 int Y, 1058 int nWidth, 1059 int nHeight, 1060 BOOL unicode) 1061 { 1062 // AG: Mostly implemented, but probably won't work properly or return 1063 // correct error codes. I doubt it grays strings either... Untested! 1064 1065 BOOL success = FALSE; 1066 HBRUSH hbsave; 1067 HDC MemDC = NULL; 1068 HBITMAP MemBMP = NULL, OldBMP = NULL; 1069 HBRUSH OldBrush = NULL; 1070 HFONT OldFont = NULL; 1071 RECT r; 1072 COLORREF ForeColor, BackColor; 1073 1074 ForeColor = SetTextColor(hDC, RGB(0, 0, 0)); 1075 BackColor = SetBkColor(hDC, RGB(255, 255, 255)); 1076 1077 if (! hBrush) 1078 { 1079 // The documentation is a little vague on what exactly should happen 1080 // here. Something about using the same brush for window text??? 1081 hBrush = (HBRUSH) GetCurrentObject(hDC, OBJ_BRUSH); 1082 } 1083 1084 if ((nCount == -1) && (! lpOutputFunc)) 1085 return FALSE; 1086 1087 if (! nCount) 1088 { 1089 // TODO: calculate the length (easy enough) 1090 1091 if (unicode) 1092 nCount = lstrlenW((WCHAR*)lpData); 1093 else 1094 nCount = lstrlenA((CHAR*)lpData); 1095 } 1096 1097 if (! nWidth || ! nHeight) 1098 { 1099 SIZE s; 1100 // TODO: calculate the rect 1101 1102 if (unicode) 1103 success = GetTextExtentPoint32W(hDC, (WCHAR*) lpData, nCount, &s); 1104 else 1105 success = GetTextExtentPoint32A(hDC, (CHAR*) lpData, nCount, &s); 1106 1107 if (! success) goto cleanup; 1108 1109 if (! nWidth) nWidth = s.cx; 1110 if (! nHeight) nHeight = s.cy; 1111 } 1112 1113 SetRect(&r, X, Y, X + nWidth, Y + nHeight); 1114 1115 MemDC = CreateCompatibleDC(hDC); 1116 if (! MemDC) goto cleanup; 1117 MemBMP = CreateBitmap(nWidth, nHeight, 1, 1, NULL); 1118 if (! MemBMP) goto cleanup; 1119 OldBMP = SelectObject(MemDC, MemBMP); 1120 if (! OldBMP) goto cleanup; 1121 OldFont = SelectObject(MemDC, GetCurrentObject(hDC, OBJ_FONT)); 1122 if (! OldFont) goto cleanup; 1123 OldBrush = SelectObject(MemDC, hBrush); 1124 if (! OldBrush) goto cleanup; 1125 1126 if (! BitBlt(MemDC, 0, 0, nWidth, nHeight, hDC, X, Y, SRCCOPY)) goto cleanup; 1127 1128 SetTextColor(MemDC, RGB(255, 255, 255)); 1129 SetBkColor(MemDC, RGB(0, 0, 0)); 1130 1131 if (lpOutputFunc) 1132 { 1133 success = lpOutputFunc(MemDC, lpData, nCount); // Set brush etc first? 1134 1135 if ((nCount == -1) && (! success)) 1136 { 1137 // Don't gray (documented behaviour) 1138 success = (BOOL) BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY); 1139 goto cleanup; 1140 } 1141 } 1142 else 1143 { 1144 if (unicode) 1145 success = TextOutW(MemDC, 0, 0, (WCHAR*) lpData, nCount); 1146 else 1147 success = TextOutA(MemDC, 0, 0, (CHAR*) lpData, nCount); 1148 1149 if (! success) goto cleanup; 1150 1151 hbsave = (HBRUSH)SelectObject(MemDC, gpsi->hbrGray); 1152 PatBlt(MemDC, 0, 0, nWidth, nHeight, 0x000A0329); 1153 SelectObject(MemDC, hbsave); 1154 } 1155 1156 if (! BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY)) goto cleanup; 1157 1158 cleanup: 1159 SetTextColor(hDC, ForeColor); 1160 SetBkColor(hDC, BackColor); 1161 1162 if (MemDC) 1163 { 1164 if (OldFont) SelectObject(MemDC, OldFont); 1165 if (OldBrush) SelectObject(MemDC, OldBrush); 1166 if (OldBMP) SelectObject(MemDC, OldBMP); 1167 if (MemBMP) DeleteObject(MemBMP); 1168 DeleteDC(MemDC); 1169 } 1170 1171 return success; 1172 } 1173 1174 /********************************************************************** 1175 * PAINTING_DrawStateJam 1176 * 1177 * Jams in the requested type in the dc 1178 */ 1179 static BOOL PAINTING_DrawStateJam(HDC hdc, UINT opcode, 1180 DRAWSTATEPROC func, LPARAM lp, WPARAM wp, 1181 LPRECT rc, UINT dtflags, BOOL unicode ) 1182 { 1183 HDC memdc; 1184 HBITMAP hbmsave; 1185 BOOL retval; 1186 INT cx = rc->right - rc->left; 1187 INT cy = rc->bottom - rc->top; 1188 1189 switch(opcode) 1190 { 1191 case DST_TEXT: 1192 case DST_PREFIXTEXT: 1193 if(unicode) 1194 return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags); 1195 else 1196 return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags); 1197 1198 case DST_ICON: 1199 return DrawIconEx(hdc, rc->left, rc->top, (HICON)lp, cx, cy, 0, NULL, DI_NORMAL); 1200 1201 case DST_BITMAP: 1202 memdc = CreateCompatibleDC(hdc); 1203 if(!memdc) 1204 return FALSE; 1205 hbmsave = (HBITMAP)SelectObject(memdc, (HBITMAP)lp); 1206 if(!hbmsave) 1207 { 1208 DeleteDC(memdc); 1209 return FALSE; 1210 } 1211 retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY); 1212 SelectObject(memdc, hbmsave); 1213 DeleteDC(memdc); 1214 return retval; 1215 1216 case DST_COMPLEX: 1217 if(func) 1218 { 1219 BOOL bRet; 1220 /* DRAWSTATEPROC assumes that it draws at the center of coordinates */ 1221 1222 OffsetViewportOrgEx(hdc, rc->left, rc->top, NULL); 1223 bRet = func(hdc, lp, wp, cx, cy); 1224 /* Restore origin */ 1225 OffsetViewportOrgEx(hdc, -rc->left, -rc->top, NULL); 1226 return bRet; 1227 } 1228 else 1229 { 1230 return FALSE; 1231 } 1232 } 1233 return FALSE; 1234 } 1235 1236 static BOOL 1237 IntDrawState(HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp, 1238 INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode) 1239 { 1240 HBITMAP hbm, hbmsave; 1241 HFONT hfsave; 1242 HBRUSH hbsave, hbrtmp = 0; 1243 HDC memdc; 1244 RECT rc; 1245 UINT dtflags = DT_NOCLIP; 1246 COLORREF fg, bg; 1247 UINT opcode = flags & 0xf; 1248 INT len = wp; 1249 BOOL retval, tmp; 1250 LOGFONTW lf; 1251 HFONT hFontOriginal, hNaaFont = NULL; 1252 1253 if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len) /* The string is '\0' terminated */ 1254 { 1255 if(unicode) 1256 len = lstrlenW((LPWSTR)lp); 1257 else 1258 len = lstrlenA((LPSTR)lp); 1259 } 1260 1261 hFontOriginal = GetCurrentObject(hdc, OBJ_FONT); 1262 if (flags & (DSS_MONO | DSS_DISABLED)) 1263 { 1264 /* Create a non-antialiased font */ 1265 GetObjectW(hFontOriginal, sizeof(lf), &lf); 1266 lf.lfQuality = NONANTIALIASED_QUALITY; 1267 hNaaFont = CreateFontIndirectW(&lf); 1268 } 1269 1270 /* Find out what size the image has if not given by caller */ 1271 if(!cx || !cy) 1272 { 1273 SIZE s; 1274 BITMAP bm; 1275 1276 switch(opcode) 1277 { 1278 case DST_TEXT: 1279 case DST_PREFIXTEXT: 1280 if(unicode) 1281 retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s); 1282 else 1283 retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s); 1284 if(!retval) 1285 return FALSE; 1286 break; 1287 1288 case DST_ICON: 1289 if(!get_icon_size((HICON)lp, &s)) 1290 return FALSE; 1291 break; 1292 1293 case DST_BITMAP: 1294 if(!GetObjectW((HBITMAP)lp, sizeof(bm), &bm)) 1295 return FALSE; 1296 s.cx = bm.bmWidth; 1297 s.cy = bm.bmHeight; 1298 break; 1299 1300 case DST_COMPLEX: /* cx and cy must be set in this mode */ 1301 return FALSE; 1302 1303 default: 1304 ERR("Invalid opcode: %u\n", opcode); 1305 return FALSE; 1306 } 1307 1308 if(!cx) cx = s.cx; 1309 if(!cy) cy = s.cy; 1310 } 1311 1312 SetRect(&rc, x, y, x + cx, y + cy); 1313 1314 if(flags & DSS_RIGHT) /* This one is not documented in the win32.hlp file */ 1315 dtflags |= DT_RIGHT; 1316 if(opcode == DST_TEXT) 1317 dtflags |= DT_NOPREFIX; 1318 else if(opcode == DST_PREFIXTEXT) 1319 { 1320 if (flags & DSS_HIDEPREFIX) 1321 dtflags |= DT_HIDEPREFIX; 1322 if (flags & DSS_PREFIXONLY) 1323 dtflags |= DT_PREFIXONLY; 1324 } 1325 1326 /* For DSS_NORMAL we just jam in the image and return */ 1327 if((flags & 0x79f0) == DSS_NORMAL) 1328 { 1329 return PAINTING_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode); 1330 } 1331 1332 /* For all other states we need to convert the image to B/W in a local bitmap */ 1333 /* before it is displayed */ 1334 fg = SetTextColor(hdc, RGB(0, 0, 0)); 1335 bg = SetBkColor(hdc, RGB(255, 255, 255)); 1336 hbm = NULL; hbmsave = NULL; 1337 memdc = NULL; hbsave = NULL; 1338 retval = FALSE; /* assume failure */ 1339 1340 /* From here on we must use "goto cleanup" when something goes wrong */ 1341 hbm = CreateBitmap(cx, cy, 1, 1, NULL); 1342 if(!hbm) goto cleanup; 1343 memdc = CreateCompatibleDC(hdc); 1344 if(!memdc) goto cleanup; 1345 hbmsave = (HBITMAP)SelectObject(memdc, hbm); 1346 if(!hbmsave) goto cleanup; 1347 SetRect(&rc, 0, 0, cx, cy); 1348 if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH))) goto cleanup; 1349 SetBkColor(memdc, RGB(255, 255, 255)); 1350 SetTextColor(memdc, RGB(0, 0, 0)); 1351 if (hNaaFont) 1352 hfsave = (HFONT)SelectObject(memdc, hNaaFont); 1353 else 1354 hfsave = (HFONT)SelectObject(memdc, hFontOriginal); 1355 SetLayout( memdc, GetLayout( hdc )); 1356 1357 /* DST_COMPLEX may draw text as well, 1358 * so we must be sure that correct font is selected 1359 */ 1360 if(!hfsave && (opcode <= DST_PREFIXTEXT)) goto cleanup; 1361 tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode); 1362 if(hfsave) SelectObject(memdc, hfsave); 1363 if (hNaaFont) DeleteObject(hNaaFont); 1364 if(!tmp) goto cleanup; 1365 1366 /* This state cause the image to be dithered */ 1367 if(flags & DSS_UNION) 1368 { 1369 hbsave = (HBRUSH)SelectObject(memdc, gpsi->hbrGray); 1370 if(!hbsave) goto cleanup; 1371 tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089); 1372 SelectObject(memdc, hbsave); 1373 if(!tmp) goto cleanup; 1374 } 1375 1376 if (flags & DSS_DISABLED) 1377 hbrtmp = GetSysColorBrush(COLOR_3DHILIGHT); 1378 else if (flags & DSS_DEFAULT) 1379 hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); 1380 1381 /* Draw light or dark shadow */ 1382 if (flags & (DSS_DISABLED|DSS_DEFAULT)) 1383 { 1384 if(!hbrtmp) goto cleanup; 1385 hbsave = (HBRUSH)SelectObject(hdc, hbrtmp); 1386 if(!hbsave) goto cleanup; 1387 if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; 1388 SelectObject(hdc, hbsave); 1389 } 1390 1391 if (flags & DSS_DISABLED) 1392 { 1393 hbr = hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); 1394 if(!hbrtmp) goto cleanup; 1395 } 1396 else if (!hbr) 1397 { 1398 hbr = (HBRUSH)GetStockObject(BLACK_BRUSH); 1399 } 1400 1401 hbsave = (HBRUSH)SelectObject(hdc, hbr); 1402 1403 if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; 1404 1405 retval = TRUE; /* We succeeded */ 1406 1407 cleanup: 1408 SetTextColor(hdc, fg); 1409 SetBkColor(hdc, bg); 1410 1411 if(hbsave) SelectObject(hdc, hbsave); 1412 if(hbmsave) SelectObject(memdc, hbmsave); 1413 if(hbm) DeleteObject(hbm); 1414 if(memdc) DeleteDC(memdc); 1415 1416 return retval; 1417 } 1418 1419 /* 1420 * @implemented 1421 */ 1422 BOOL WINAPI 1423 RealDrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState) 1424 { 1425 if (GetMapMode(hDC) != MM_TEXT) 1426 return FALSE; 1427 1428 switch(uType) 1429 { 1430 case DFC_BUTTON: 1431 return UITOOLS95_DrawFrameButton(hDC, rc, uState); 1432 case DFC_CAPTION: 1433 return UITOOLS95_DrawFrameCaption(hDC, rc, uState); 1434 case DFC_MENU: 1435 { 1436 BOOL ret; 1437 COLORREF rgbOldText; 1438 INT iOldBackMode; 1439 1440 if (uState & (DFCS_MENUARROWUP | DFCS_MENUARROWDOWN)) 1441 { 1442 if (!(uState & DFCS_TRANSPARENT)) 1443 FillRect(hDC, rc, (HBRUSH)(COLOR_MENU + 1)); /* Fill by menu color */ 1444 } 1445 else 1446 { 1447 FillRect(hDC, rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); /* Fill by white */ 1448 } 1449 1450 rgbOldText = SetTextColor(hDC, RGB(0, 0, 0)); /* Draw by black */ 1451 iOldBackMode = SetBkMode(hDC, TRANSPARENT); 1452 ret = UITOOLS95_DrawFrameMenu(hDC, rc, uState); 1453 SetBkMode(hDC, iOldBackMode); 1454 SetTextColor(hDC, rgbOldText); 1455 return ret; 1456 } 1457 #if 0 1458 case DFC_POPUPMENU: 1459 UNIMPLEMENTED; 1460 break; 1461 #endif 1462 case DFC_SCROLL: 1463 return UITOOLS95_DrawFrameScroll(hDC, rc, uState); 1464 } 1465 return FALSE; 1466 } 1467 1468 BOOL WINAPI 1469 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState) 1470 { 1471 BOOL Hook, Ret = FALSE; 1472 1473 LoadUserApiHook(); 1474 1475 Hook = BeginIfHookedUserApiHook(); 1476 1477 /* Bypass SEH and go direct. */ 1478 if (!Hook) return RealDrawFrameControl(hDC, rc, uType, uState); 1479 1480 _SEH2_TRY 1481 { 1482 Ret = guah.DrawFrameControl(hDC, rc, uType, uState); 1483 } 1484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1485 { 1486 ERR("Got exception in hooked DrawFrameControl!\n"); 1487 } 1488 _SEH2_END; 1489 1490 EndUserApiHook(); 1491 1492 return Ret; 1493 } 1494 1495 /* 1496 * @implemented 1497 */ 1498 BOOL WINAPI 1499 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags) 1500 { 1501 if (flags & BF_DIAGONAL) 1502 return IntDrawDiagEdge(hDC, rc, edge, flags); 1503 else 1504 return IntDrawRectEdge(hDC, rc, edge, flags, 1); 1505 } 1506 1507 /* 1508 * @implemented 1509 */ 1510 BOOL WINAPI 1511 GrayStringA(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, 1512 int nCount, int X, int Y, int nWidth, int nHeight) 1513 { 1514 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, FALSE); 1515 } 1516 1517 /* 1518 * @implemented 1519 */ 1520 BOOL WINAPI 1521 GrayStringW(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, 1522 int nCount, int X, int Y, int nWidth, int nHeight) 1523 { 1524 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, TRUE); 1525 } 1526 1527 /* 1528 * @implemented 1529 */ 1530 BOOL WINAPI 1531 InvertRect(HDC hDC, CONST RECT *lprc) 1532 { 1533 return PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, 1534 lprc->bottom - lprc->top, DSTINVERT); 1535 } 1536 1537 /* 1538 * @implemented 1539 */ 1540 INT WINAPI 1541 FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) 1542 { 1543 HBRUSH oldbrush; 1544 RECT r = *lprc; 1545 1546 if (IsRectEmpty(&r)) return 0; 1547 if (!(oldbrush = SelectObject(hDC, hbr))) return 0; 1548 1549 PatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY); 1550 PatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY); 1551 PatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY); 1552 PatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY); 1553 1554 SelectObject(hDC, oldbrush); 1555 return TRUE; 1556 } 1557 1558 /* 1559 * @implemented 1560 */ 1561 BOOL WINAPI 1562 FlashWindow(HWND hWnd, BOOL bInvert) 1563 { 1564 FLASHWINFO FlashWndInfo; 1565 1566 FlashWndInfo.cbSize = sizeof(FLASHWINFO); 1567 FlashWndInfo.hwnd = hWnd; 1568 FlashWndInfo.dwFlags = !bInvert ? 0 : (FLASHW_TRAY | FLASHW_CAPTION); 1569 FlashWndInfo.uCount = 1; 1570 FlashWndInfo.dwTimeout = 0; 1571 1572 return NtUserFlashWindowEx(&FlashWndInfo); 1573 } 1574 1575 /* 1576 * @implemented 1577 */ 1578 INT WINAPI 1579 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) 1580 { 1581 BOOL Ret; 1582 HBRUSH prevhbr = NULL; 1583 1584 /* Select brush if specified */ 1585 if (hbr) 1586 { 1587 /* Handle system colors */ 1588 if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1)) 1589 hbr = GetSysColorBrush(PtrToUlong(hbr) - 1); 1590 1591 prevhbr = SelectObject(hDC, hbr); 1592 if (prevhbr == NULL) 1593 return (INT)FALSE; 1594 } 1595 1596 Ret = PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, 1597 lprc->bottom - lprc->top, PATCOPY); 1598 1599 /* Select old brush */ 1600 if (prevhbr) 1601 SelectObject(hDC, prevhbr); 1602 1603 return (INT)Ret; 1604 } 1605 1606 /* 1607 * @implemented 1608 */ 1609 BOOL WINAPI 1610 DrawFocusRect(HDC hdc, CONST RECT *rect) 1611 { 1612 HGDIOBJ OldObj; 1613 UINT cx, cy; 1614 1615 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERWIDTH, 0, &cx, 0); 1616 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERHEIGHT, 0, &cy, 0); 1617 1618 OldObj = SelectObject(hdc, gpsi->hbrGray); 1619 1620 /* top */ 1621 PatBlt(hdc, rect->left, rect->top, rect->right - rect->left, cy, PATINVERT); 1622 /* bottom */ 1623 PatBlt(hdc, rect->left, rect->bottom - cy, rect->right - rect->left, cy, PATINVERT); 1624 /* left */ 1625 PatBlt(hdc, rect->left, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT); 1626 /* right */ 1627 PatBlt(hdc, rect->right - cx, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT); 1628 1629 SelectObject(hdc, OldObj); 1630 return TRUE; 1631 } 1632 1633 /* 1634 * @implemented 1635 */ 1636 BOOL WINAPI 1637 DrawStateA(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData, 1638 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags) 1639 { 1640 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, FALSE); 1641 } 1642 1643 /* 1644 * @implemented 1645 */ 1646 BOOL WINAPI 1647 DrawStateW(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData, 1648 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags) 1649 { 1650 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, TRUE); 1651 } 1652