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 LOGFONTW lf; 976 HFONT hFont, hOldFont; 977 TCHAR Symbol; 978 switch(uFlags & 0xff) 979 { 980 case DFCS_MENUARROWUP: 981 Symbol = '5'; 982 break; 983 984 case DFCS_MENUARROWDOWN: 985 Symbol = '6'; 986 break; 987 988 case DFCS_MENUARROW: 989 Symbol = '8'; 990 break; 991 992 case DFCS_MENUARROWRIGHT: 993 Symbol = 'w'; // FIXME: needs to confirm 994 break; 995 996 case DFCS_MENUBULLET: 997 Symbol = 'h'; 998 break; 999 1000 case DFCS_MENUCHECK: 1001 Symbol = 'a'; 1002 break; 1003 1004 default: 1005 WARN("Invalid menu; flags=0x%04x\n", uFlags); 1006 return FALSE; 1007 } 1008 /* acquire ressources only if valid menu */ 1009 ZeroMemory(&lf, sizeof(LOGFONTW)); 1010 lf.lfHeight = r->bottom - r->top; 1011 lf.lfWidth = 0; 1012 lf.lfWeight = FW_NORMAL; 1013 lf.lfCharSet = DEFAULT_CHARSET; 1014 lstrcpy(lf.lfFaceName, TEXT("Marlett")); 1015 hFont = CreateFontIndirect(&lf); 1016 /* save font */ 1017 hOldFont = SelectObject(dc, hFont); 1018 1019 if ((uFlags & 0xff) == DFCS_MENUARROWUP || 1020 (uFlags & 0xff) == DFCS_MENUARROWDOWN ) 1021 { 1022 #if 0 1023 if (uFlags & DFCS_INACTIVE) 1024 { 1025 /* draw shadow */ 1026 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); 1027 TextOut(dc, r->left + 1, r->top + 1, &Symbol, 1); 1028 } 1029 #endif 1030 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); 1031 } 1032 /* draw selected symbol */ 1033 TextOut(dc, r->left, r->top, &Symbol, 1); 1034 /* restore previous settings */ 1035 SelectObject(dc, hOldFont); 1036 DeleteObject(hFont); 1037 return TRUE; 1038 } 1039 1040 BOOL 1041 WINAPI 1042 IntGrayString( 1043 HDC hDC, 1044 HBRUSH hBrush, 1045 GRAYSTRINGPROC lpOutputFunc, 1046 LPARAM lpData, 1047 int nCount, 1048 int X, 1049 int Y, 1050 int nWidth, 1051 int nHeight, 1052 BOOL unicode) 1053 { 1054 // AG: Mostly implemented, but probably won't work properly or return 1055 // correct error codes. I doubt it grays strings either... Untested! 1056 1057 BOOL success = FALSE; 1058 HBRUSH hbsave; 1059 HDC MemDC = NULL; 1060 HBITMAP MemBMP = NULL, OldBMP = NULL; 1061 HBRUSH OldBrush = NULL; 1062 HFONT OldFont = NULL; 1063 RECT r; 1064 COLORREF ForeColor, BackColor; 1065 1066 ForeColor = SetTextColor(hDC, RGB(0, 0, 0)); 1067 BackColor = SetBkColor(hDC, RGB(255, 255, 255)); 1068 1069 if (! hBrush) 1070 { 1071 // The documentation is a little vague on what exactly should happen 1072 // here. Something about using the same brush for window text??? 1073 hBrush = (HBRUSH) GetCurrentObject(hDC, OBJ_BRUSH); 1074 } 1075 1076 if ((nCount == -1) && (! lpOutputFunc)) 1077 return FALSE; 1078 1079 if (! nCount) 1080 { 1081 // TODO: calculate the length (easy enough) 1082 1083 if (unicode) 1084 nCount = lstrlenW((WCHAR*)lpData); 1085 else 1086 nCount = lstrlenA((CHAR*)lpData); 1087 } 1088 1089 if (! nWidth || ! nHeight) 1090 { 1091 SIZE s; 1092 // TODO: calculate the rect 1093 1094 if (unicode) 1095 success = GetTextExtentPoint32W(hDC, (WCHAR*) lpData, nCount, &s); 1096 else 1097 success = GetTextExtentPoint32A(hDC, (CHAR*) lpData, nCount, &s); 1098 1099 if (! success) goto cleanup; 1100 1101 if (! nWidth) nWidth = s.cx; 1102 if (! nHeight) nHeight = s.cy; 1103 } 1104 1105 SetRect(&r, X, Y, X + nWidth, Y + nHeight); 1106 1107 MemDC = CreateCompatibleDC(hDC); 1108 if (! MemDC) goto cleanup; 1109 MemBMP = CreateBitmap(nWidth, nHeight, 1, 1, NULL); 1110 if (! MemBMP) goto cleanup; 1111 OldBMP = SelectObject(MemDC, MemBMP); 1112 if (! OldBMP) goto cleanup; 1113 OldFont = SelectObject(MemDC, GetCurrentObject(hDC, OBJ_FONT)); 1114 if (! OldFont) goto cleanup; 1115 OldBrush = SelectObject(MemDC, hBrush); 1116 if (! OldBrush) goto cleanup; 1117 1118 if (! BitBlt(MemDC, 0, 0, nWidth, nHeight, hDC, X, Y, SRCCOPY)) goto cleanup; 1119 1120 SetTextColor(MemDC, RGB(255, 255, 255)); 1121 SetBkColor(MemDC, RGB(0, 0, 0)); 1122 1123 if (lpOutputFunc) 1124 { 1125 success = lpOutputFunc(MemDC, lpData, nCount); // Set brush etc first? 1126 1127 if ((nCount == -1) && (! success)) 1128 { 1129 // Don't gray (documented behaviour) 1130 success = (BOOL) BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY); 1131 goto cleanup; 1132 } 1133 } 1134 else 1135 { 1136 if (unicode) 1137 success = TextOutW(MemDC, 0, 0, (WCHAR*) lpData, nCount); 1138 else 1139 success = TextOutA(MemDC, 0, 0, (CHAR*) lpData, nCount); 1140 1141 if (! success) goto cleanup; 1142 1143 hbsave = (HBRUSH)SelectObject(MemDC, gpsi->hbrGray); 1144 PatBlt(MemDC, 0, 0, nWidth, nHeight, 0x000A0329); 1145 SelectObject(MemDC, hbsave); 1146 } 1147 1148 if (! BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY)) goto cleanup; 1149 1150 cleanup: 1151 SetTextColor(hDC, ForeColor); 1152 SetBkColor(hDC, BackColor); 1153 1154 if (MemDC) 1155 { 1156 if (OldFont) SelectObject(MemDC, OldFont); 1157 if (OldBrush) SelectObject(MemDC, OldBrush); 1158 if (OldBMP) SelectObject(MemDC, OldBMP); 1159 if (MemBMP) DeleteObject(MemBMP); 1160 DeleteDC(MemDC); 1161 } 1162 1163 return success; 1164 } 1165 1166 /********************************************************************** 1167 * PAINTING_DrawStateJam 1168 * 1169 * Jams in the requested type in the dc 1170 */ 1171 static BOOL PAINTING_DrawStateJam(HDC hdc, UINT opcode, 1172 DRAWSTATEPROC func, LPARAM lp, WPARAM wp, 1173 LPRECT rc, UINT dtflags, BOOL unicode ) 1174 { 1175 HDC memdc; 1176 HBITMAP hbmsave; 1177 BOOL retval; 1178 INT cx = rc->right - rc->left; 1179 INT cy = rc->bottom - rc->top; 1180 1181 switch(opcode) 1182 { 1183 case DST_TEXT: 1184 case DST_PREFIXTEXT: 1185 if(unicode) 1186 return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags); 1187 else 1188 return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags); 1189 1190 case DST_ICON: 1191 return DrawIconEx(hdc, rc->left, rc->top, (HICON)lp, cx, cy, 0, NULL, DI_NORMAL); 1192 1193 case DST_BITMAP: 1194 memdc = CreateCompatibleDC(hdc); 1195 if(!memdc) 1196 return FALSE; 1197 hbmsave = (HBITMAP)SelectObject(memdc, (HBITMAP)lp); 1198 if(!hbmsave) 1199 { 1200 DeleteDC(memdc); 1201 return FALSE; 1202 } 1203 retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY); 1204 SelectObject(memdc, hbmsave); 1205 DeleteDC(memdc); 1206 return retval; 1207 1208 case DST_COMPLEX: 1209 if(func) 1210 { 1211 BOOL bRet; 1212 /* DRAWSTATEPROC assumes that it draws at the center of coordinates */ 1213 1214 OffsetViewportOrgEx(hdc, rc->left, rc->top, NULL); 1215 bRet = func(hdc, lp, wp, cx, cy); 1216 /* Restore origin */ 1217 OffsetViewportOrgEx(hdc, -rc->left, -rc->top, NULL); 1218 return bRet; 1219 } 1220 else 1221 { 1222 return FALSE; 1223 } 1224 } 1225 return FALSE; 1226 } 1227 1228 static BOOL 1229 IntDrawState(HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp, 1230 INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode) 1231 { 1232 HBITMAP hbm, hbmsave; 1233 HFONT hfsave; 1234 HBRUSH hbsave, hbrtmp = 0; 1235 HDC memdc; 1236 RECT rc; 1237 UINT dtflags = DT_NOCLIP; 1238 COLORREF fg, bg; 1239 UINT opcode = flags & 0xf; 1240 INT len = wp; 1241 BOOL retval, tmp; 1242 LOGFONTW lf; 1243 HFONT hFontOriginal, hNaaFont = NULL; 1244 1245 if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len) /* The string is '\0' terminated */ 1246 { 1247 if(unicode) 1248 len = lstrlenW((LPWSTR)lp); 1249 else 1250 len = lstrlenA((LPSTR)lp); 1251 } 1252 1253 hFontOriginal = GetCurrentObject(hdc, OBJ_FONT); 1254 if (flags & (DSS_MONO | DSS_DISABLED)) 1255 { 1256 /* Create a non-antialiased font */ 1257 GetObjectW(hFontOriginal, sizeof(lf), &lf); 1258 lf.lfQuality = NONANTIALIASED_QUALITY; 1259 hNaaFont = CreateFontIndirectW(&lf); 1260 } 1261 1262 /* Find out what size the image has if not given by caller */ 1263 if(!cx || !cy) 1264 { 1265 SIZE s; 1266 BITMAP bm; 1267 1268 switch(opcode) 1269 { 1270 case DST_TEXT: 1271 case DST_PREFIXTEXT: 1272 if(unicode) 1273 retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s); 1274 else 1275 retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s); 1276 if(!retval) 1277 return FALSE; 1278 break; 1279 1280 case DST_ICON: 1281 if(!get_icon_size((HICON)lp, &s)) 1282 return FALSE; 1283 break; 1284 1285 case DST_BITMAP: 1286 if(!GetObjectW((HBITMAP)lp, sizeof(bm), &bm)) 1287 return FALSE; 1288 s.cx = bm.bmWidth; 1289 s.cy = bm.bmHeight; 1290 break; 1291 1292 case DST_COMPLEX: /* cx and cy must be set in this mode */ 1293 return FALSE; 1294 1295 default: 1296 ERR("Invalid opcode: %u\n", opcode); 1297 return FALSE; 1298 } 1299 1300 if(!cx) cx = s.cx; 1301 if(!cy) cy = s.cy; 1302 } 1303 1304 SetRect(&rc, x, y, x + cx, y + cy); 1305 1306 if(flags & DSS_RIGHT) /* This one is not documented in the win32.hlp file */ 1307 dtflags |= DT_RIGHT; 1308 if(opcode == DST_TEXT) 1309 dtflags |= DT_NOPREFIX; 1310 else if(opcode == DST_PREFIXTEXT) 1311 { 1312 if (flags & DSS_HIDEPREFIX) 1313 dtflags |= DT_HIDEPREFIX; 1314 if (flags & DSS_PREFIXONLY) 1315 dtflags |= DT_PREFIXONLY; 1316 } 1317 1318 /* For DSS_NORMAL we just jam in the image and return */ 1319 if((flags & 0x79f0) == DSS_NORMAL) 1320 { 1321 return PAINTING_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode); 1322 } 1323 1324 /* For all other states we need to convert the image to B/W in a local bitmap */ 1325 /* before it is displayed */ 1326 fg = SetTextColor(hdc, RGB(0, 0, 0)); 1327 bg = SetBkColor(hdc, RGB(255, 255, 255)); 1328 hbm = NULL; hbmsave = NULL; 1329 memdc = NULL; hbsave = NULL; 1330 retval = FALSE; /* assume failure */ 1331 1332 /* From here on we must use "goto cleanup" when something goes wrong */ 1333 hbm = CreateBitmap(cx, cy, 1, 1, NULL); 1334 if(!hbm) goto cleanup; 1335 memdc = CreateCompatibleDC(hdc); 1336 if(!memdc) goto cleanup; 1337 hbmsave = (HBITMAP)SelectObject(memdc, hbm); 1338 if(!hbmsave) goto cleanup; 1339 SetRect(&rc, 0, 0, cx, cy); 1340 if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH))) goto cleanup; 1341 SetBkColor(memdc, RGB(255, 255, 255)); 1342 SetTextColor(memdc, RGB(0, 0, 0)); 1343 if (hNaaFont) 1344 hfsave = (HFONT)SelectObject(memdc, hNaaFont); 1345 else 1346 hfsave = (HFONT)SelectObject(memdc, hFontOriginal); 1347 SetLayout( memdc, GetLayout( hdc )); 1348 1349 /* DST_COMPLEX may draw text as well, 1350 * so we must be sure that correct font is selected 1351 */ 1352 if(!hfsave && (opcode <= DST_PREFIXTEXT)) goto cleanup; 1353 tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode); 1354 if(hfsave) SelectObject(memdc, hfsave); 1355 if (hNaaFont) DeleteObject(hNaaFont); 1356 if(!tmp) goto cleanup; 1357 1358 /* This state cause the image to be dithered */ 1359 if(flags & DSS_UNION) 1360 { 1361 hbsave = (HBRUSH)SelectObject(memdc, gpsi->hbrGray); 1362 if(!hbsave) goto cleanup; 1363 tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089); 1364 SelectObject(memdc, hbsave); 1365 if(!tmp) goto cleanup; 1366 } 1367 1368 if (flags & DSS_DISABLED) 1369 hbrtmp = GetSysColorBrush(COLOR_3DHILIGHT); 1370 else if (flags & DSS_DEFAULT) 1371 hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); 1372 1373 /* Draw light or dark shadow */ 1374 if (flags & (DSS_DISABLED|DSS_DEFAULT)) 1375 { 1376 if(!hbrtmp) goto cleanup; 1377 hbsave = (HBRUSH)SelectObject(hdc, hbrtmp); 1378 if(!hbsave) goto cleanup; 1379 if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; 1380 SelectObject(hdc, hbsave); 1381 } 1382 1383 if (flags & DSS_DISABLED) 1384 { 1385 hbr = hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); 1386 if(!hbrtmp) goto cleanup; 1387 } 1388 else if (!hbr) 1389 { 1390 hbr = (HBRUSH)GetStockObject(BLACK_BRUSH); 1391 } 1392 1393 hbsave = (HBRUSH)SelectObject(hdc, hbr); 1394 1395 if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; 1396 1397 retval = TRUE; /* We succeeded */ 1398 1399 cleanup: 1400 SetTextColor(hdc, fg); 1401 SetBkColor(hdc, bg); 1402 1403 if(hbsave) SelectObject(hdc, hbsave); 1404 if(hbmsave) SelectObject(memdc, hbmsave); 1405 if(hbm) DeleteObject(hbm); 1406 if(memdc) DeleteDC(memdc); 1407 1408 return retval; 1409 } 1410 1411 /* 1412 * @implemented 1413 */ 1414 BOOL WINAPI 1415 RealDrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState) 1416 { 1417 if (GetMapMode(hDC) != MM_TEXT) 1418 return FALSE; 1419 1420 switch(uType) 1421 { 1422 case DFC_BUTTON: 1423 return UITOOLS95_DrawFrameButton(hDC, rc, uState); 1424 case DFC_CAPTION: 1425 return UITOOLS95_DrawFrameCaption(hDC, rc, uState); 1426 case DFC_MENU: 1427 return UITOOLS95_DrawFrameMenu(hDC, rc, uState); 1428 #if 0 1429 case DFC_POPUPMENU: 1430 UNIMPLEMENTED; 1431 break; 1432 #endif 1433 case DFC_SCROLL: 1434 return UITOOLS95_DrawFrameScroll(hDC, rc, uState); 1435 } 1436 return FALSE; 1437 } 1438 1439 BOOL WINAPI 1440 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState) 1441 { 1442 BOOL Hook, Ret = FALSE; 1443 1444 LoadUserApiHook(); 1445 1446 Hook = BeginIfHookedUserApiHook(); 1447 1448 /* Bypass SEH and go direct. */ 1449 if (!Hook) return RealDrawFrameControl(hDC, rc, uType, uState); 1450 1451 _SEH2_TRY 1452 { 1453 Ret = guah.DrawFrameControl(hDC, rc, uType, uState); 1454 } 1455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1456 { 1457 ERR("Got exception in hooked DrawFrameControl!\n"); 1458 } 1459 _SEH2_END; 1460 1461 EndUserApiHook(); 1462 1463 return Ret; 1464 } 1465 1466 /* 1467 * @implemented 1468 */ 1469 BOOL WINAPI 1470 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags) 1471 { 1472 if (flags & BF_DIAGONAL) 1473 return IntDrawDiagEdge(hDC, rc, edge, flags); 1474 else 1475 return IntDrawRectEdge(hDC, rc, edge, flags, 1); 1476 } 1477 1478 /* 1479 * @implemented 1480 */ 1481 BOOL WINAPI 1482 GrayStringA(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, 1483 int nCount, int X, int Y, int nWidth, int nHeight) 1484 { 1485 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, FALSE); 1486 } 1487 1488 /* 1489 * @implemented 1490 */ 1491 BOOL WINAPI 1492 GrayStringW(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, 1493 int nCount, int X, int Y, int nWidth, int nHeight) 1494 { 1495 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, TRUE); 1496 } 1497 1498 /* 1499 * @implemented 1500 */ 1501 BOOL WINAPI 1502 InvertRect(HDC hDC, CONST RECT *lprc) 1503 { 1504 return PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, 1505 lprc->bottom - lprc->top, DSTINVERT); 1506 } 1507 1508 /* 1509 * @implemented 1510 */ 1511 INT WINAPI 1512 FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) 1513 { 1514 HBRUSH oldbrush; 1515 RECT r = *lprc; 1516 1517 if (IsRectEmpty(&r)) return 0; 1518 if (!(oldbrush = SelectObject(hDC, hbr))) return 0; 1519 1520 PatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY); 1521 PatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY); 1522 PatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY); 1523 PatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY); 1524 1525 SelectObject(hDC, oldbrush); 1526 return TRUE; 1527 } 1528 1529 /* 1530 * @implemented 1531 */ 1532 BOOL WINAPI 1533 FlashWindow(HWND hWnd, BOOL bInvert) 1534 { 1535 FLASHWINFO FlashWndInfo; 1536 1537 FlashWndInfo.cbSize = sizeof(FLASHWINFO); 1538 FlashWndInfo.hwnd = hWnd; 1539 FlashWndInfo.dwFlags = !bInvert ? 0 : (FLASHW_TRAY | FLASHW_CAPTION); 1540 FlashWndInfo.uCount = 1; 1541 FlashWndInfo.dwTimeout = 0; 1542 1543 return NtUserFlashWindowEx(&FlashWndInfo); 1544 } 1545 1546 /* 1547 * @implemented 1548 */ 1549 INT WINAPI 1550 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) 1551 { 1552 BOOL Ret; 1553 HBRUSH prevhbr = NULL; 1554 1555 /* Select brush if specified */ 1556 if (hbr) 1557 { 1558 /* Handle system colors */ 1559 if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1)) 1560 hbr = GetSysColorBrush(PtrToUlong(hbr) - 1); 1561 1562 prevhbr = SelectObject(hDC, hbr); 1563 if (prevhbr == NULL) 1564 return (INT)FALSE; 1565 } 1566 1567 Ret = PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, 1568 lprc->bottom - lprc->top, PATCOPY); 1569 1570 /* Select old brush */ 1571 if (prevhbr) 1572 SelectObject(hDC, prevhbr); 1573 1574 return (INT)Ret; 1575 } 1576 1577 /* 1578 * @implemented 1579 */ 1580 BOOL WINAPI 1581 DrawFocusRect(HDC hdc, CONST RECT *rect) 1582 { 1583 HGDIOBJ OldObj; 1584 UINT cx, cy; 1585 1586 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERWIDTH, 0, &cx, 0); 1587 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERHEIGHT, 0, &cy, 0); 1588 1589 OldObj = SelectObject(hdc, gpsi->hbrGray); 1590 1591 /* top */ 1592 PatBlt(hdc, rect->left, rect->top, rect->right - rect->left, cy, PATINVERT); 1593 /* bottom */ 1594 PatBlt(hdc, rect->left, rect->bottom - cy, rect->right - rect->left, cy, PATINVERT); 1595 /* left */ 1596 PatBlt(hdc, rect->left, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT); 1597 /* right */ 1598 PatBlt(hdc, rect->right - cx, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT); 1599 1600 SelectObject(hdc, OldObj); 1601 return TRUE; 1602 } 1603 1604 /* 1605 * @implemented 1606 */ 1607 BOOL WINAPI 1608 DrawStateA(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData, 1609 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags) 1610 { 1611 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, FALSE); 1612 } 1613 1614 /* 1615 * @implemented 1616 */ 1617 BOOL WINAPI 1618 DrawStateW(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData, 1619 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags) 1620 { 1621 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, TRUE); 1622 } 1623