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