1 /* 2 * Static control 3 * 4 * Copyright David W. Metcalfe, 1993 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * 20 * Notes: 21 * - Windows XP introduced new behavior: The background of centered 22 * icons and bitmaps is painted differently. This is only done if 23 * a manifest is present. 24 * Because it has not yet been decided how to implement the two 25 * different modes in Wine, only the Windows XP mode is implemented. 26 * - Controls with SS_SIMPLE but without SS_NOPREFIX: 27 * The text should not be changed. Windows doesn't clear the 28 * client rectangle, so the new text must be larger than the old one. 29 * - The SS_RIGHTJUST style is currently not implemented by Windows 30 * (or it does something different than documented). 31 * 32 * TODO: 33 * - Animated cursors 34 */ 35 36 #include <stdarg.h> 37 38 #include "windef.h" 39 #include "winbase.h" 40 #include "wingdi.h" 41 #include "winuser.h" 42 #include "commctrl.h" 43 44 #include "wine/debug.h" 45 46 #include "comctl32.h" 47 48 WINE_DEFAULT_DEBUG_CHANNEL(static); 49 50 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style ); 51 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ); 52 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style ); 53 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style ); 54 static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, DWORD style ); 55 static void STATIC_PaintEnhMetafn( HWND hwnd, HDC hdc, DWORD style ); 56 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style ); 57 58 /* offsets for GetWindowLong for static private information */ 59 #define HFONT_GWL_OFFSET 0 60 #define HICON_GWL_OFFSET (sizeof(HFONT)) 61 #define STATIC_EXTRA_BYTES (HICON_GWL_OFFSET + sizeof(HICON)) 62 63 typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style ); 64 65 static const pfPaint staticPaintFunc[SS_TYPEMASK+1] = 66 { 67 STATIC_PaintTextfn, /* SS_LEFT */ 68 STATIC_PaintTextfn, /* SS_CENTER */ 69 STATIC_PaintTextfn, /* SS_RIGHT */ 70 STATIC_PaintIconfn, /* SS_ICON */ 71 STATIC_PaintRectfn, /* SS_BLACKRECT */ 72 STATIC_PaintRectfn, /* SS_GRAYRECT */ 73 STATIC_PaintRectfn, /* SS_WHITERECT */ 74 STATIC_PaintRectfn, /* SS_BLACKFRAME */ 75 STATIC_PaintRectfn, /* SS_GRAYFRAME */ 76 STATIC_PaintRectfn, /* SS_WHITEFRAME */ 77 NULL, /* SS_USERITEM */ 78 STATIC_PaintTextfn, /* SS_SIMPLE */ 79 STATIC_PaintTextfn, /* SS_LEFTNOWORDWRAP */ 80 STATIC_PaintOwnerDrawfn, /* SS_OWNERDRAW */ 81 STATIC_PaintBitmapfn, /* SS_BITMAP */ 82 STATIC_PaintEnhMetafn, /* SS_ENHMETAFILE */ 83 STATIC_PaintEtchedfn, /* SS_ETCHEDHORZ */ 84 STATIC_PaintEtchedfn, /* SS_ETCHEDVERT */ 85 STATIC_PaintEtchedfn, /* SS_ETCHEDFRAME */ 86 }; 87 88 static BOOL get_icon_size( HICON handle, SIZE *size ) 89 { 90 ICONINFO info; 91 BITMAP bmp; 92 int ret; 93 94 if (!GetIconInfo(handle, &info)) 95 return FALSE; 96 97 #ifdef __REACTOS__ 98 ret = GetObjectW(info.hbmMask, sizeof(bmp), &bmp); 99 #else 100 ret = GetObjectW(info.hbmColor, sizeof(bmp), &bmp); 101 #endif 102 if (ret) 103 { 104 size->cx = bmp.bmWidth; 105 size->cy = bmp.bmHeight; 106 #ifdef __REACTOS__ 107 /* 108 If this structure defines a black and white icon, this bitmask is formatted 109 so that the upper half is the icon AND bitmask and the lower half is 110 the icon XOR bitmask. 111 */ 112 if (!info.hbmColor) 113 size->cy /= 2; 114 #endif 115 } 116 117 DeleteObject(info.hbmMask); 118 DeleteObject(info.hbmColor); 119 120 return !!ret; 121 } 122 123 /*********************************************************************** 124 * STATIC_SetIcon 125 * 126 * Set the icon for an SS_ICON control. 127 */ 128 static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) 129 { 130 HICON prevIcon; 131 SIZE size; 132 133 if ((style & SS_TYPEMASK) != SS_ICON) return 0; 134 if (hicon && !get_icon_size( hicon, &size )) 135 { 136 WARN("hicon != 0, but invalid\n"); 137 return 0; 138 } 139 prevIcon = (HICON)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hicon ); 140 if (hicon && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) 141 { 142 /* Windows currently doesn't implement SS_RIGHTJUST */ 143 /* 144 if ((style & SS_RIGHTJUST) != 0) 145 { 146 RECT wr; 147 GetWindowRect(hwnd, &wr); 148 SetWindowPos( hwnd, 0, wr.right - info->nWidth, wr.bottom - info->nHeight, 149 info->nWidth, info->nHeight, SWP_NOACTIVATE | SWP_NOZORDER ); 150 } 151 else */ 152 { 153 SetWindowPos( hwnd, 0, 0, 0, size.cx, size.cy, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); 154 } 155 } 156 return prevIcon; 157 } 158 159 /*********************************************************************** 160 * STATIC_SetBitmap 161 * 162 * Set the bitmap for an SS_BITMAP control. 163 */ 164 static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style ) 165 { 166 HBITMAP hOldBitmap; 167 168 if ((style & SS_TYPEMASK) != SS_BITMAP) return 0; 169 if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) 170 { 171 WARN("hBitmap != 0, but it's not a bitmap\n"); 172 return 0; 173 } 174 hOldBitmap = (HBITMAP)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hBitmap ); 175 if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) 176 { 177 BITMAP bm; 178 GetObjectW(hBitmap, sizeof(bm), &bm); 179 /* Windows currently doesn't implement SS_RIGHTJUST */ 180 /* 181 if ((style & SS_RIGHTJUST) != 0) 182 { 183 RECT wr; 184 GetWindowRect(hwnd, &wr); 185 SetWindowPos( hwnd, 0, wr.right - bm.bmWidth, wr.bottom - bm.bmHeight, 186 bm.bmWidth, bm.bmHeight, SWP_NOACTIVATE | SWP_NOZORDER ); 187 } 188 else */ 189 { 190 SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight, 191 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); 192 } 193 } 194 return hOldBitmap; 195 } 196 197 /*********************************************************************** 198 * STATIC_SetEnhMetaFile 199 * 200 * Set the enhanced metafile for an SS_ENHMETAFILE control. 201 */ 202 static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, DWORD style ) 203 { 204 if ((style & SS_TYPEMASK) != SS_ENHMETAFILE) return 0; 205 if (hEnhMetaFile && GetObjectType(hEnhMetaFile) != OBJ_ENHMETAFILE) 206 { 207 WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n"); 208 return 0; 209 } 210 return (HENHMETAFILE)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hEnhMetaFile ); 211 } 212 213 /*********************************************************************** 214 * STATIC_GetImage 215 * 216 * Gets the bitmap for an SS_BITMAP control, the icon/cursor for an 217 * SS_ICON control or the enhanced metafile for an SS_ENHMETAFILE control. 218 */ 219 static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style ) 220 { 221 switch (style & SS_TYPEMASK) 222 { 223 case SS_ICON: 224 if ((wParam != IMAGE_ICON) && 225 (wParam != IMAGE_CURSOR)) return NULL; 226 break; 227 case SS_BITMAP: 228 if (wParam != IMAGE_BITMAP) return NULL; 229 break; 230 case SS_ENHMETAFILE: 231 if (wParam != IMAGE_ENHMETAFILE) return NULL; 232 break; 233 default: 234 return NULL; 235 } 236 return (HANDLE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ); 237 } 238 239 /*********************************************************************** 240 * STATIC_LoadIconW 241 * 242 * Load the icon for an SS_ICON control. 243 */ 244 static HICON STATIC_LoadIconW( HINSTANCE hInstance, LPCWSTR name, DWORD style ) 245 { 246 HICON hicon = 0; 247 248 if (hInstance && ((ULONG_PTR)hInstance >> 16)) 249 { 250 if ((style & SS_REALSIZEIMAGE) != 0) 251 hicon = LoadImageW(hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED); 252 else 253 { 254 hicon = LoadIconW( hInstance, name ); 255 if (!hicon) hicon = LoadCursorW( hInstance, name ); 256 } 257 } 258 if (!hicon) hicon = LoadIconW( 0, name ); 259 /* Windows doesn't try to load a standard cursor, 260 probably because most IDs for standard cursors conflict 261 with the IDs for standard icons anyway */ 262 return hicon; 263 } 264 265 /*********************************************************************** 266 * STATIC_TryPaintFcn 267 * 268 * Try to immediately paint the control. 269 */ 270 static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style) 271 { 272 LONG style = full_style & SS_TYPEMASK; 273 RECT rc; 274 275 GetClientRect( hwnd, &rc ); 276 if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style]) 277 { 278 HDC hdc; 279 HRGN hrgn; 280 281 hdc = GetDC( hwnd ); 282 hrgn = set_control_clipping( hdc, &rc ); 283 (staticPaintFunc[style])( hwnd, hdc, full_style ); 284 SelectClipRgn( hdc, hrgn ); 285 if (hrgn) DeleteObject( hrgn ); 286 ReleaseDC( hwnd, hdc ); 287 } 288 } 289 290 static HBRUSH STATIC_SendWmCtlColorStatic(HWND hwnd, HDC hdc) 291 { 292 HBRUSH hBrush; 293 HWND parent = GetParent(hwnd); 294 295 if (!parent) parent = hwnd; 296 hBrush = (HBRUSH) SendMessageW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd ); 297 if (!hBrush) /* did the app forget to call DefWindowProc ? */ 298 { 299 /* FIXME: DefWindowProc should return different colors if a 300 manifest is present */ 301 hBrush = (HBRUSH)DefWindowProcW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd); 302 } 303 return hBrush; 304 } 305 306 /*********************************************************************** 307 * hasTextStyle 308 * 309 * Tests if the control displays text. 310 */ 311 static BOOL hasTextStyle( DWORD style ) 312 { 313 switch (style & SS_TYPEMASK) 314 { 315 case SS_SIMPLE: 316 case SS_LEFT: 317 case SS_LEFTNOWORDWRAP: 318 case SS_CENTER: 319 case SS_RIGHT: 320 case SS_OWNERDRAW: 321 return TRUE; 322 } 323 324 return FALSE; 325 } 326 327 static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 328 { 329 LRESULT lResult = 0; 330 LONG full_style = GetWindowLongW( hwnd, GWL_STYLE ); 331 LONG style = full_style & SS_TYPEMASK; 332 333 if (!IsWindow( hwnd )) return 0; 334 335 switch (uMsg) 336 { 337 case WM_CREATE: 338 if (style < 0L || style > SS_TYPEMASK) 339 { 340 ERR("Unknown style 0x%02x\n", style ); 341 return -1; 342 } 343 break; 344 345 case WM_NCDESTROY: 346 if (style == SS_ICON) 347 { 348 /* 349 * FIXME 350 * DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) ); 351 * 352 * We don't want to do this yet because DestroyIcon32 is broken. If the icon 353 * had already been loaded by the application the last thing we want to do is 354 * GlobalFree16 the handle. 355 */ 356 break; 357 } 358 else 359 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 360 361 case WM_ERASEBKGND: 362 /* do all painting in WM_PAINT like Windows does */ 363 return 1; 364 365 case WM_PRINTCLIENT: 366 case WM_PAINT: 367 { 368 PAINTSTRUCT ps; 369 RECT rect; 370 HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps); 371 GetClientRect( hwnd, &rect ); 372 if (staticPaintFunc[style]) 373 { 374 HRGN hrgn = set_control_clipping( hdc, &rect ); 375 (staticPaintFunc[style])( hwnd, hdc, full_style ); 376 SelectClipRgn( hdc, hrgn ); 377 if (hrgn) DeleteObject( hrgn ); 378 } 379 if (!wParam) EndPaint(hwnd, &ps); 380 } 381 break; 382 383 case WM_ENABLE: 384 STATIC_TryPaintFcn( hwnd, full_style ); 385 if (full_style & SS_NOTIFY) 386 { 387 if (wParam) 388 SendMessageW( GetParent(hwnd), WM_COMMAND, 389 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_ENABLE ), (LPARAM)hwnd); 390 else 391 SendMessageW( GetParent(hwnd), WM_COMMAND, 392 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DISABLE ), (LPARAM)hwnd); 393 } 394 break; 395 396 case WM_SYSCOLORCHANGE: 397 COMCTL32_RefreshSysColors(); 398 STATIC_TryPaintFcn( hwnd, full_style ); 399 break; 400 401 case WM_NCCREATE: 402 { 403 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam; 404 405 if (full_style & SS_SUNKEN) 406 SetWindowLongW( hwnd, GWL_EXSTYLE, 407 GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE ); 408 409 switch (style) 410 { 411 case SS_ICON: 412 { 413 HICON hIcon; 414 415 hIcon = STATIC_LoadIconW(cs->hInstance, cs->lpszName, full_style); 416 STATIC_SetIcon(hwnd, hIcon, full_style); 417 } 418 break; 419 case SS_BITMAP: 420 if ((ULONG_PTR)cs->hInstance >> 16) 421 { 422 HBITMAP hBitmap; 423 hBitmap = LoadBitmapW(cs->hInstance, cs->lpszName); 424 STATIC_SetBitmap(hwnd, hBitmap, full_style); 425 } 426 break; 427 } 428 /* SS_ENHMETAFILE: Despite what MSDN says, Windows does not load 429 the enhanced metafile that was specified as the window text. */ 430 } 431 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 432 433 case WM_SETTEXT: 434 if (hasTextStyle( full_style )) 435 { 436 lResult = DefWindowProcW( hwnd, uMsg, wParam, lParam ); 437 STATIC_TryPaintFcn( hwnd, full_style ); 438 } 439 break; 440 441 case WM_SETFONT: 442 if (hasTextStyle( full_style )) 443 { 444 SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, wParam ); 445 if (LOWORD(lParam)) 446 RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN ); 447 } 448 break; 449 450 case WM_GETFONT: 451 return GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); 452 453 case WM_NCHITTEST: 454 if (full_style & SS_NOTIFY) 455 return HTCLIENT; 456 else 457 return HTTRANSPARENT; 458 459 case WM_GETDLGCODE: 460 return DLGC_STATIC; 461 462 case WM_LBUTTONDOWN: 463 case WM_NCLBUTTONDOWN: 464 if (full_style & SS_NOTIFY) 465 SendMessageW( GetParent(hwnd), WM_COMMAND, 466 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_CLICKED ), (LPARAM)hwnd); 467 return 0; 468 469 case WM_LBUTTONDBLCLK: 470 case WM_NCLBUTTONDBLCLK: 471 if (full_style & SS_NOTIFY) 472 SendMessageW( GetParent(hwnd), WM_COMMAND, 473 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DBLCLK ), (LPARAM)hwnd); 474 return 0; 475 476 case STM_GETIMAGE: 477 return (LRESULT)STATIC_GetImage( hwnd, wParam, full_style ); 478 479 case STM_GETICON: 480 return (LRESULT)STATIC_GetImage( hwnd, IMAGE_ICON, full_style ); 481 482 case STM_SETIMAGE: 483 switch (wParam) 484 { 485 case IMAGE_BITMAP: 486 lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style ); 487 break; 488 case IMAGE_ENHMETAFILE: 489 lResult = (LRESULT)STATIC_SetEnhMetaFile( hwnd, (HENHMETAFILE)lParam, full_style ); 490 break; 491 case IMAGE_ICON: 492 case IMAGE_CURSOR: 493 lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style ); 494 break; 495 default: 496 FIXME("STM_SETIMAGE: Unhandled type %lx\n", wParam); 497 break; 498 } 499 STATIC_TryPaintFcn( hwnd, full_style ); 500 break; 501 502 case STM_SETICON: 503 lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style ); 504 STATIC_TryPaintFcn( hwnd, full_style ); 505 break; 506 507 default: 508 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 509 } 510 return lResult; 511 } 512 513 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style ) 514 { 515 DRAWITEMSTRUCT dis; 516 HFONT font, oldFont = NULL; 517 UINT id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID ); 518 519 dis.CtlType = ODT_STATIC; 520 dis.CtlID = id; 521 dis.itemID = 0; 522 dis.itemAction = ODA_DRAWENTIRE; 523 dis.itemState = IsWindowEnabled(hwnd) ? 0 : ODS_DISABLED; 524 dis.hwndItem = hwnd; 525 dis.hDC = hdc; 526 dis.itemData = 0; 527 GetClientRect( hwnd, &dis.rcItem ); 528 529 font = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); 530 if (font) oldFont = SelectObject( hdc, font ); 531 SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd ); 532 SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis ); 533 if (font) SelectObject( hdc, oldFont ); 534 } 535 536 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) 537 { 538 RECT rc; 539 HBRUSH hBrush; 540 HFONT hFont, hOldFont = NULL; 541 UINT format; 542 INT len, buf_size; 543 WCHAR *text; 544 545 GetClientRect( hwnd, &rc); 546 547 switch (style & SS_TYPEMASK) 548 { 549 case SS_LEFT: 550 format = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK; 551 break; 552 553 case SS_CENTER: 554 format = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK; 555 break; 556 557 case SS_RIGHT: 558 format = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK; 559 break; 560 561 case SS_SIMPLE: 562 format = DT_LEFT | DT_SINGLELINE; 563 break; 564 565 case SS_LEFTNOWORDWRAP: 566 format = DT_LEFT | DT_EXPANDTABS; 567 break; 568 569 default: 570 return; 571 } 572 573 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_RIGHT) 574 format = DT_RIGHT | (format & ~(DT_LEFT | DT_CENTER)); 575 576 if (style & SS_NOPREFIX) 577 format |= DT_NOPREFIX; 578 579 if ((style & SS_TYPEMASK) != SS_SIMPLE) 580 { 581 if (style & SS_CENTERIMAGE) 582 format |= DT_SINGLELINE | DT_VCENTER; 583 if (style & SS_EDITCONTROL) 584 format |= DT_EDITCONTROL; 585 if (style & SS_ENDELLIPSIS) 586 format |= DT_SINGLELINE | DT_END_ELLIPSIS; 587 if (style & SS_PATHELLIPSIS) 588 format |= DT_SINGLELINE | DT_PATH_ELLIPSIS; 589 if (style & SS_WORDELLIPSIS) 590 format |= DT_SINGLELINE | DT_WORD_ELLIPSIS; 591 } 592 593 if ((hFont = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ))) 594 hOldFont = SelectObject( hdc, hFont ); 595 596 /* SS_SIMPLE controls: WM_CTLCOLORSTATIC is sent, but the returned 597 brush is not used */ 598 hBrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); 599 600 if ((style & SS_TYPEMASK) != SS_SIMPLE) 601 { 602 FillRect( hdc, &rc, hBrush ); 603 if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); 604 } 605 606 buf_size = 256; 607 if (!(text = HeapAlloc( GetProcessHeap(), 0, buf_size * sizeof(WCHAR) ))) 608 goto no_TextOut; 609 610 while ((len = InternalGetWindowText( hwnd, text, buf_size )) == buf_size - 1) 611 { 612 buf_size *= 2; 613 if (!(text = HeapReAlloc( GetProcessHeap(), 0, text, buf_size * sizeof(WCHAR) ))) 614 goto no_TextOut; 615 } 616 617 if (!len) goto no_TextOut; 618 619 if (((style & SS_TYPEMASK) == SS_SIMPLE) && (style & SS_NOPREFIX)) 620 { 621 /* Windows uses the faster ExtTextOut() to draw the text and 622 to paint the whole client rectangle with the text background 623 color. Reference: "Static Controls" by Kyle Marsh, 1992 */ 624 ExtTextOutW( hdc, rc.left, rc.top, ETO_CLIPPED | ETO_OPAQUE, 625 &rc, text, len, NULL ); 626 } 627 else 628 { 629 DrawTextW( hdc, text, -1, &rc, format ); 630 } 631 632 no_TextOut: 633 HeapFree( GetProcessHeap(), 0, text ); 634 635 if (hFont) 636 SelectObject( hdc, hOldFont ); 637 } 638 639 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style ) 640 { 641 RECT rc; 642 HBRUSH hBrush; 643 644 GetClientRect( hwnd, &rc); 645 646 /* FIXME: send WM_CTLCOLORSTATIC */ 647 switch (style & SS_TYPEMASK) 648 { 649 case SS_BLACKRECT: 650 hBrush = CreateSolidBrush(comctl32_color.clr3dDkShadow); 651 FillRect( hdc, &rc, hBrush ); 652 break; 653 case SS_GRAYRECT: 654 hBrush = CreateSolidBrush(comctl32_color.clr3dShadow); 655 FillRect( hdc, &rc, hBrush ); 656 break; 657 case SS_WHITERECT: 658 hBrush = CreateSolidBrush(comctl32_color.clr3dHilight); 659 FillRect( hdc, &rc, hBrush ); 660 break; 661 case SS_BLACKFRAME: 662 hBrush = CreateSolidBrush(comctl32_color.clr3dDkShadow); 663 FrameRect( hdc, &rc, hBrush ); 664 break; 665 case SS_GRAYFRAME: 666 hBrush = CreateSolidBrush(comctl32_color.clr3dShadow); 667 FrameRect( hdc, &rc, hBrush ); 668 break; 669 case SS_WHITEFRAME: 670 hBrush = CreateSolidBrush(comctl32_color.clr3dHilight); 671 FrameRect( hdc, &rc, hBrush ); 672 break; 673 default: 674 return; 675 } 676 DeleteObject( hBrush ); 677 } 678 679 680 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style ) 681 { 682 RECT rc, iconRect; 683 HBRUSH hbrush; 684 HICON hIcon; 685 SIZE size; 686 687 GetClientRect( hwnd, &rc ); 688 hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); 689 hIcon = (HICON)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ); 690 if (!hIcon || !get_icon_size( hIcon, &size )) 691 { 692 FillRect(hdc, &rc, hbrush); 693 } 694 else 695 { 696 if (style & SS_CENTERIMAGE) 697 { 698 iconRect.left = (rc.right - rc.left) / 2 - size.cx / 2; 699 iconRect.top = (rc.bottom - rc.top) / 2 - size.cy / 2; 700 iconRect.right = iconRect.left + size.cx; 701 iconRect.bottom = iconRect.top + size.cy; 702 } 703 else 704 iconRect = rc; 705 FillRect( hdc, &rc, hbrush ); 706 DrawIconEx( hdc, iconRect.left, iconRect.top, hIcon, iconRect.right - iconRect.left, 707 iconRect.bottom - iconRect.top, 0, NULL, DI_NORMAL ); 708 } 709 } 710 711 static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style ) 712 { 713 HDC hMemDC; 714 HBITMAP hBitmap, oldbitmap; 715 HBRUSH hbrush; 716 717 /* message is still sent, even if the returned brush is not used */ 718 hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); 719 720 if ((hBitmap = (HBITMAP)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )) 721 && (GetObjectType(hBitmap) == OBJ_BITMAP) 722 && (hMemDC = CreateCompatibleDC( hdc ))) 723 { 724 BITMAP bm; 725 RECT rcClient; 726 LOGBRUSH brush; 727 728 GetObjectW(hBitmap, sizeof(bm), &bm); 729 oldbitmap = SelectObject(hMemDC, hBitmap); 730 731 /* Set the background color for monochrome bitmaps 732 to the color of the background brush */ 733 if (GetObjectW( hbrush, sizeof(brush), &brush )) 734 { 735 if (brush.lbStyle == BS_SOLID) 736 SetBkColor(hdc, brush.lbColor); 737 } 738 GetClientRect(hwnd, &rcClient); 739 if (style & SS_CENTERIMAGE) 740 { 741 FillRect( hdc, &rcClient, hbrush ); 742 rcClient.left = (rcClient.right - rcClient.left)/2 - bm.bmWidth/2; 743 rcClient.top = (rcClient.bottom - rcClient.top)/2 - bm.bmHeight/2; 744 rcClient.right = rcClient.left + bm.bmWidth; 745 rcClient.bottom = rcClient.top + bm.bmHeight; 746 } 747 StretchBlt(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left, 748 rcClient.bottom - rcClient.top, hMemDC, 749 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); 750 SelectObject(hMemDC, oldbitmap); 751 DeleteDC(hMemDC); 752 } 753 } 754 755 static void STATIC_PaintEnhMetafn(HWND hwnd, HDC hdc, DWORD style ) 756 { 757 HENHMETAFILE hEnhMetaFile; 758 RECT rc; 759 HBRUSH hbrush; 760 761 GetClientRect(hwnd, &rc); 762 hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); 763 FillRect(hdc, &rc, hbrush); 764 if ((hEnhMetaFile = (HENHMETAFILE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ))) 765 { 766 /* The control's current font is not selected into the 767 device context! */ 768 if (GetObjectType(hEnhMetaFile) == OBJ_ENHMETAFILE) 769 PlayEnhMetaFile(hdc, hEnhMetaFile, &rc); 770 } 771 } 772 773 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style ) 774 { 775 RECT rc; 776 777 /* FIXME: sometimes (not always) sends WM_CTLCOLORSTATIC */ 778 GetClientRect( hwnd, &rc ); 779 switch (style & SS_TYPEMASK) 780 { 781 case SS_ETCHEDHORZ: 782 DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP | BF_BOTTOM); 783 break; 784 case SS_ETCHEDVERT: 785 DrawEdge(hdc, &rc, EDGE_ETCHED, BF_LEFT | BF_RIGHT); 786 break; 787 case SS_ETCHEDFRAME: 788 DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT); 789 break; 790 } 791 } 792 793 void STATIC_Register(void) 794 { 795 WNDCLASSW wndClass; 796 797 memset(&wndClass, 0, sizeof(wndClass)); 798 wndClass.style = CS_DBLCLKS | CS_PARENTDC | CS_GLOBALCLASS; 799 wndClass.lpfnWndProc = STATIC_WindowProc; 800 wndClass.cbClsExtra = 0; 801 wndClass.cbWndExtra = STATIC_EXTRA_BYTES; 802 wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); 803 wndClass.hbrBackground = NULL; 804 wndClass.lpszClassName = WC_STATICW; 805 RegisterClassW(&wndClass); 806 } 807 808 #ifdef __REACTOS__ 809 void STATIC_Unregister(void) 810 { 811 UnregisterClassW(WC_STATICW, NULL); 812 } 813 #endif 814