1 /* 2 * Interface code to StatusWindow widget/control 3 * 4 * Copyright 1996 Bruce Milner 5 * Copyright 1998, 1999 Eric Kohl 6 * Copyright 2002 Dimitrie O. Paun 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 * 22 * NOTE 23 * 24 * This code was audited for completeness against the documented features 25 * of Comctl32.dll version 6.0 on Sep. 24, 2002, by Dimitrie O. Paun. 26 * 27 * Unless otherwise noted, we believe this code to be complete, as per 28 * the specification mentioned above. 29 * If you discover missing features, or bugs, please note them below. 30 * 31 * TODO: 32 * -- CCS_BOTTOM (default) 33 * -- CCS_LEFT 34 * -- CCS_NODIVIDER 35 * -- CCS_NOMOVEX 36 * -- CCS_NOMOVEY 37 * -- CCS_NOPARENTALIGN 38 * -- CCS_RIGHT 39 * -- CCS_TOP 40 * -- CCS_VERT (defaults to RIGHT) 41 */ 42 43 #include "comctl32.h" 44 45 WINE_DEFAULT_DEBUG_CHANNEL(statusbar); 46 47 typedef struct 48 { 49 INT x; 50 INT style; 51 RECT bound; 52 LPWSTR text; 53 HICON hIcon; 54 } STATUSWINDOWPART; 55 56 typedef struct 57 { 58 HWND Self; 59 HWND Notify; 60 WORD numParts; 61 UINT height; 62 UINT minHeight; /* at least MIN_PANE_HEIGHT, can be increased by SB_SETMINHEIGHT */ 63 BOOL simple; 64 HWND hwndToolTip; 65 HFONT hFont; 66 HFONT hDefaultFont; 67 COLORREF clrBk; /* background color */ 68 BOOL bUnicode; /* notify format. TRUE if notifies in Unicode */ 69 STATUSWINDOWPART part0; /* simple window */ 70 STATUSWINDOWPART* parts; 71 INT horizontalBorder; 72 INT verticalBorder; 73 INT horizontalGap; 74 } STATUS_INFO; 75 76 /* 77 * Run tests using Waite Group Windows95 API Bible Vol. 1&2 78 * The second cdrom contains executables drawstat.exe, gettext.exe, 79 * simple.exe, getparts.exe, setparts.exe, statwnd.exe 80 */ 81 82 #define HORZ_BORDER 0 83 #define VERT_BORDER 2 84 #define HORZ_GAP 2 85 86 static const WCHAR themeClass[] = { 'S','t','a','t','u','s',0 }; 87 88 /* prototype */ 89 static void 90 STATUSBAR_SetPartBounds (STATUS_INFO *infoPtr); 91 static LRESULT 92 STATUSBAR_NotifyFormat (STATUS_INFO *infoPtr, HWND from, INT cmd); 93 94 static inline LPCSTR debugstr_t(LPCWSTR text, BOOL isW) 95 { 96 return isW ? debugstr_w(text) : debugstr_a((LPCSTR)text); 97 } 98 99 static UINT 100 STATUSBAR_ComputeHeight(STATUS_INFO *infoPtr) 101 { 102 HTHEME theme; 103 UINT height; 104 TEXTMETRICW tm; 105 int margin; 106 107 COMCTL32_GetFontMetrics(infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont, &tm); 108 margin = (tm.tmInternalLeading ? tm.tmInternalLeading : 2); 109 height = max(tm.tmHeight + margin + 2*GetSystemMetrics(SM_CYBORDER), infoPtr->minHeight) + infoPtr->verticalBorder; 110 111 if ((theme = GetWindowTheme(infoPtr->Self))) 112 { 113 /* Determine bar height from theme such that the content area is 114 * textHeight pixels large */ 115 HDC hdc = GetDC(infoPtr->Self); 116 RECT r; 117 118 SetRect(&r, 0, 0, 0, max(infoPtr->minHeight, tm.tmHeight)); 119 if (SUCCEEDED(GetThemeBackgroundExtent(theme, hdc, SP_PANE, 0, &r, &r))) 120 { 121 height = r.bottom - r.top; 122 } 123 ReleaseDC(infoPtr->Self, hdc); 124 } 125 126 TRACE(" textHeight=%d+%d, final height=%d\n", tm.tmHeight, tm.tmInternalLeading, height); 127 return height; 128 } 129 130 static void 131 STATUSBAR_DrawSizeGrip (HTHEME theme, HDC hdc, LPRECT lpRect) 132 { 133 RECT rc = *lpRect; 134 135 TRACE("draw size grip %s\n", wine_dbgstr_rect(lpRect)); 136 137 if (theme) 138 { 139 SIZE gripperSize; 140 if (SUCCEEDED (GetThemePartSize (theme, hdc, SP_GRIPPER, 0, lpRect, 141 TS_DRAW, &gripperSize))) 142 { 143 rc.left = rc.right - gripperSize.cx; 144 rc.top = rc.bottom - gripperSize.cy; 145 if (SUCCEEDED (DrawThemeBackground(theme, hdc, SP_GRIPPER, 0, &rc, NULL))) 146 return; 147 } 148 } 149 150 rc.left = max( rc.left, rc.right - GetSystemMetrics(SM_CXVSCROLL) - 1 ); 151 rc.top = max( rc.top, rc.bottom - GetSystemMetrics(SM_CYHSCROLL) - 1 ); 152 DrawFrameControl( hdc, &rc, DFC_SCROLL, DFCS_SCROLLSIZEGRIP ); 153 } 154 155 156 static void 157 STATUSBAR_DrawPart (const STATUS_INFO *infoPtr, HDC hdc, const STATUSWINDOWPART *part, int itemID) 158 { 159 RECT r = part->bound; 160 UINT border = BDR_SUNKENOUTER; 161 HTHEME theme = GetWindowTheme (infoPtr->Self); 162 int themePart = SP_PANE; 163 int x = 0; 164 165 TRACE("part bound %s\n", wine_dbgstr_rect(&r)); 166 if (part->style & SBT_POPOUT) 167 border = BDR_RAISEDOUTER; 168 else if (part->style & SBT_NOBORDERS) 169 border = 0; 170 171 if (theme) 172 { 173 if ((GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) 174 && (infoPtr->simple || (itemID == (infoPtr->numParts-1)))) 175 themePart = SP_GRIPPERPANE; 176 DrawThemeBackground(theme, hdc, themePart, 0, &r, NULL); 177 } 178 else 179 DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST); 180 181 if (part->hIcon) { 182 INT cy = r.bottom - r.top; 183 DrawIconEx (hdc, r.left + 2, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL); 184 x = 2 + cy; 185 } 186 187 if (part->style & SBT_OWNERDRAW) { 188 DRAWITEMSTRUCT dis; 189 190 dis.CtlID = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); 191 dis.itemID = itemID; 192 dis.hwndItem = infoPtr->Self; 193 dis.hDC = hdc; 194 dis.rcItem = r; 195 dis.itemData = (ULONG_PTR)part->text; 196 SendMessageW (infoPtr->Notify, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); 197 } else { 198 r.left += x; 199 #ifdef __REACTOS__ 200 if (!theme) 201 DrawStatusTextW (hdc, &r, part->text, SBT_NOBORDERS); 202 else 203 DrawThemeText(theme, hdc, SP_PANE, 0, part->text, -1, DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX, 0, &r); 204 #else 205 DrawStatusTextW (hdc, &r, part->text, SBT_NOBORDERS); 206 #endif 207 } 208 } 209 210 211 static void 212 STATUSBAR_RefreshPart (const STATUS_INFO *infoPtr, HDC hdc, const STATUSWINDOWPART *part, int itemID) 213 { 214 HBRUSH hbrBk; 215 HTHEME theme; 216 217 TRACE("item %d\n", itemID); 218 219 if (part->bound.right < part->bound.left) return; 220 221 if (!RectVisible(hdc, &part->bound)) 222 return; 223 224 if ((theme = GetWindowTheme (infoPtr->Self))) 225 { 226 RECT cr; 227 GetClientRect (infoPtr->Self, &cr); 228 DrawThemeBackground(theme, hdc, 0, 0, &cr, &part->bound); 229 } 230 else 231 { 232 if (infoPtr->clrBk != CLR_DEFAULT) 233 hbrBk = CreateSolidBrush (infoPtr->clrBk); 234 else 235 hbrBk = GetSysColorBrush (COLOR_3DFACE); 236 FillRect(hdc, &part->bound, hbrBk); 237 if (infoPtr->clrBk != CLR_DEFAULT) 238 DeleteObject (hbrBk); 239 } 240 241 STATUSBAR_DrawPart (infoPtr, hdc, part, itemID); 242 } 243 244 245 static LRESULT 246 STATUSBAR_Refresh (STATUS_INFO *infoPtr, HDC hdc) 247 { 248 RECT rect; 249 HBRUSH hbrBk; 250 HFONT hOldFont; 251 HTHEME theme; 252 253 TRACE("\n"); 254 if (!IsWindowVisible(infoPtr->Self)) 255 return 0; 256 257 STATUSBAR_SetPartBounds(infoPtr); 258 259 GetClientRect (infoPtr->Self, &rect); 260 261 if ((theme = GetWindowTheme (infoPtr->Self))) 262 { 263 DrawThemeBackground(theme, hdc, 0, 0, &rect, NULL); 264 } 265 else 266 { 267 if (infoPtr->clrBk != CLR_DEFAULT) 268 hbrBk = CreateSolidBrush (infoPtr->clrBk); 269 else 270 hbrBk = GetSysColorBrush (COLOR_3DFACE); 271 FillRect(hdc, &rect, hbrBk); 272 if (infoPtr->clrBk != CLR_DEFAULT) 273 DeleteObject (hbrBk); 274 } 275 276 hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont); 277 278 if (infoPtr->simple) { 279 STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->part0, 0); 280 } else { 281 unsigned int i; 282 283 for (i = 0; i < infoPtr->numParts; i++) { 284 STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->parts[i], i); 285 } 286 } 287 288 SelectObject (hdc, hOldFont); 289 290 if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) 291 STATUSBAR_DrawSizeGrip (theme, hdc, &rect); 292 293 return 0; 294 } 295 296 297 static int 298 STATUSBAR_InternalHitTest(const STATUS_INFO *infoPtr, const POINT *pt) 299 { 300 unsigned int i; 301 302 if (infoPtr->simple) 303 return 255; 304 305 for (i = 0; i < infoPtr->numParts; i++) 306 if (pt->x >= infoPtr->parts[i].bound.left && pt->x <= infoPtr->parts[i].bound.right) 307 return i; 308 return -2; 309 } 310 311 312 static void 313 STATUSBAR_SetPartBounds (STATUS_INFO *infoPtr) 314 { 315 STATUSWINDOWPART *part; 316 RECT rect, *r; 317 UINT i; 318 319 /* get our window size */ 320 GetClientRect (infoPtr->Self, &rect); 321 TRACE("client wnd size is %s\n", wine_dbgstr_rect(&rect)); 322 323 rect.left += infoPtr->horizontalBorder; 324 rect.top += infoPtr->verticalBorder; 325 326 /* set bounds for simple rectangle */ 327 infoPtr->part0.bound = rect; 328 329 /* set bounds for non-simple rectangles */ 330 for (i = 0; i < infoPtr->numParts; i++) { 331 part = &infoPtr->parts[i]; 332 r = &infoPtr->parts[i].bound; 333 r->top = rect.top; 334 r->bottom = rect.bottom; 335 if (i == 0) 336 r->left = 0; 337 else 338 r->left = infoPtr->parts[i-1].bound.right + infoPtr->horizontalGap; 339 if (part->x == -1) 340 r->right = rect.right; 341 else 342 r->right = part->x; 343 344 if (infoPtr->hwndToolTip) { 345 TTTOOLINFOW ti; 346 347 ti.cbSize = sizeof(TTTOOLINFOW); 348 ti.hwnd = infoPtr->Self; 349 ti.uId = i; 350 ti.rect = *r; 351 SendMessageW (infoPtr->hwndToolTip, TTM_NEWTOOLRECTW, 352 0, (LPARAM)&ti); 353 } 354 } 355 } 356 357 358 static LRESULT 359 STATUSBAR_Relay2Tip (const STATUS_INFO *infoPtr, UINT uMsg, 360 WPARAM wParam, LPARAM lParam) 361 { 362 MSG msg; 363 364 msg.hwnd = infoPtr->Self; 365 msg.message = uMsg; 366 msg.wParam = wParam; 367 msg.lParam = lParam; 368 msg.time = GetMessageTime (); 369 msg.pt.x = (short)LOWORD(GetMessagePos ()); 370 msg.pt.y = (short)HIWORD(GetMessagePos ()); 371 372 return SendMessageW (infoPtr->hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg); 373 } 374 375 376 static BOOL 377 STATUSBAR_GetBorders (const STATUS_INFO *infoPtr, INT out[]) 378 { 379 TRACE("\n"); 380 out[0] = infoPtr->horizontalBorder; 381 out[1] = infoPtr->verticalBorder; 382 out[2] = infoPtr->horizontalGap; 383 384 return TRUE; 385 } 386 387 388 static BOOL 389 STATUSBAR_SetBorders (STATUS_INFO *infoPtr, const INT in[]) 390 { 391 TRACE("\n"); 392 infoPtr->horizontalBorder = in[0]; 393 infoPtr->verticalBorder = in[1]; 394 infoPtr->horizontalGap = in[2]; 395 InvalidateRect(infoPtr->Self, NULL, FALSE); 396 397 return TRUE; 398 } 399 400 401 static HICON 402 STATUSBAR_GetIcon (const STATUS_INFO *infoPtr, INT nPart) 403 { 404 TRACE("%d\n", nPart); 405 /* MSDN says: "simple parts are indexed with -1" */ 406 if ((nPart < -1) || (nPart >= infoPtr->numParts)) 407 return 0; 408 409 if (nPart == -1) 410 return (infoPtr->part0.hIcon); 411 else 412 return (infoPtr->parts[nPart].hIcon); 413 } 414 415 416 static INT 417 STATUSBAR_GetParts (const STATUS_INFO *infoPtr, INT num_parts, INT parts[]) 418 { 419 INT i; 420 421 TRACE("(%d)\n", num_parts); 422 if (parts) { 423 for (i = 0; i < num_parts; i++) { 424 parts[i] = infoPtr->parts[i].x; 425 } 426 } 427 return infoPtr->numParts; 428 } 429 430 431 static BOOL 432 STATUSBAR_GetRect (const STATUS_INFO *infoPtr, INT nPart, LPRECT rect) 433 { 434 TRACE("part %d\n", nPart); 435 if(nPart >= infoPtr->numParts || nPart < 0) 436 return FALSE; 437 if (infoPtr->simple) 438 *rect = infoPtr->part0.bound; 439 else 440 *rect = infoPtr->parts[nPart].bound; 441 return TRUE; 442 } 443 444 445 static LRESULT 446 STATUSBAR_GetTextA (STATUS_INFO *infoPtr, INT nPart, LPSTR buf) 447 { 448 STATUSWINDOWPART *part; 449 LRESULT result; 450 451 TRACE("part %d\n", nPart); 452 453 /* MSDN says: "simple parts use index of 0", so this check is ok. */ 454 if (nPart < 0 || nPart >= infoPtr->numParts) return 0; 455 456 if (infoPtr->simple) 457 part = &infoPtr->part0; 458 else 459 part = &infoPtr->parts[nPart]; 460 461 if (part->style & SBT_OWNERDRAW) 462 result = (LRESULT)part->text; 463 else { 464 DWORD len = part->text ? WideCharToMultiByte( CP_ACP, 0, part->text, -1, 465 NULL, 0, NULL, NULL ) - 1 : 0; 466 result = MAKELONG( len, part->style ); 467 if (part->text && buf) 468 WideCharToMultiByte( CP_ACP, 0, part->text, -1, buf, len+1, NULL, NULL ); 469 } 470 return result; 471 } 472 473 474 static LRESULT 475 STATUSBAR_GetTextW (STATUS_INFO *infoPtr, INT nPart, LPWSTR buf) 476 { 477 STATUSWINDOWPART *part; 478 LRESULT result; 479 480 TRACE("part %d\n", nPart); 481 if (nPart < 0 || nPart >= infoPtr->numParts) return 0; 482 483 if (infoPtr->simple) 484 part = &infoPtr->part0; 485 else 486 part = &infoPtr->parts[nPart]; 487 488 if (part->style & SBT_OWNERDRAW) 489 result = (LRESULT)part->text; 490 else { 491 result = part->text ? strlenW (part->text) : 0; 492 result |= (part->style << 16); 493 if (part->text && buf) 494 strcpyW (buf, part->text); 495 } 496 return result; 497 } 498 499 500 static LRESULT 501 STATUSBAR_GetTextLength (STATUS_INFO *infoPtr, INT nPart) 502 { 503 STATUSWINDOWPART *part; 504 DWORD result; 505 506 TRACE("part %d\n", nPart); 507 508 /* MSDN says: "simple parts use index of 0", so this check is ok. */ 509 if (nPart < 0 || nPart >= infoPtr->numParts) return 0; 510 511 if (infoPtr->simple) 512 part = &infoPtr->part0; 513 else 514 part = &infoPtr->parts[nPart]; 515 516 if ((~part->style & SBT_OWNERDRAW) && part->text) 517 result = strlenW(part->text); 518 else 519 result = 0; 520 521 result |= (part->style << 16); 522 return result; 523 } 524 525 static LRESULT 526 STATUSBAR_GetTipTextA (const STATUS_INFO *infoPtr, INT id, LPSTR tip, INT size) 527 { 528 TRACE("\n"); 529 if (tip) { 530 CHAR buf[INFOTIPSIZE]; 531 buf[0]='\0'; 532 533 if (infoPtr->hwndToolTip) { 534 TTTOOLINFOA ti; 535 ti.cbSize = sizeof(TTTOOLINFOA); 536 ti.hwnd = infoPtr->Self; 537 ti.uId = id; 538 ti.lpszText = buf; 539 SendMessageA (infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti); 540 } 541 lstrcpynA (tip, buf, size); 542 } 543 return 0; 544 } 545 546 547 static LRESULT 548 STATUSBAR_GetTipTextW (const STATUS_INFO *infoPtr, INT id, LPWSTR tip, INT size) 549 { 550 TRACE("\n"); 551 if (tip) { 552 WCHAR buf[INFOTIPSIZE]; 553 buf[0]=0; 554 555 if (infoPtr->hwndToolTip) { 556 TTTOOLINFOW ti; 557 ti.cbSize = sizeof(TTTOOLINFOW); 558 ti.hwnd = infoPtr->Self; 559 ti.uId = id; 560 ti.lpszText = buf; 561 SendMessageW(infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti); 562 } 563 lstrcpynW(tip, buf, size); 564 } 565 566 return 0; 567 } 568 569 570 static COLORREF 571 STATUSBAR_SetBkColor (STATUS_INFO *infoPtr, COLORREF color) 572 { 573 COLORREF oldBkColor; 574 575 oldBkColor = infoPtr->clrBk; 576 infoPtr->clrBk = color; 577 InvalidateRect(infoPtr->Self, NULL, FALSE); 578 579 TRACE("CREF: %08x -> %08x\n", oldBkColor, infoPtr->clrBk); 580 return oldBkColor; 581 } 582 583 584 static BOOL 585 STATUSBAR_SetIcon (STATUS_INFO *infoPtr, INT nPart, HICON hIcon) 586 { 587 if ((nPart < -1) || (nPart >= infoPtr->numParts)) 588 return FALSE; 589 590 TRACE("setting part %d\n", nPart); 591 592 /* FIXME: MSDN says "if nPart is -1, the status bar is assumed simple" */ 593 if (nPart == -1) { 594 if (infoPtr->part0.hIcon == hIcon) /* same as - no redraw */ 595 return TRUE; 596 infoPtr->part0.hIcon = hIcon; 597 if (infoPtr->simple) 598 InvalidateRect(infoPtr->Self, &infoPtr->part0.bound, FALSE); 599 } else { 600 if (infoPtr->parts[nPart].hIcon == hIcon) /* same as - no redraw */ 601 return TRUE; 602 603 infoPtr->parts[nPart].hIcon = hIcon; 604 if (!(infoPtr->simple)) 605 InvalidateRect(infoPtr->Self, &infoPtr->parts[nPart].bound, FALSE); 606 } 607 return TRUE; 608 } 609 610 611 static BOOL 612 STATUSBAR_SetMinHeight (STATUS_INFO *infoPtr, INT height) 613 { 614 DWORD ysize = GetSystemMetrics(SM_CYSIZE); 615 if (ysize & 1) ysize--; 616 infoPtr->minHeight = max(height, ysize); 617 infoPtr->height = STATUSBAR_ComputeHeight(infoPtr); 618 /* like native, don't resize the control */ 619 return TRUE; 620 } 621 622 623 static BOOL 624 STATUSBAR_SetParts (STATUS_INFO *infoPtr, INT count, LPINT parts) 625 { 626 STATUSWINDOWPART *tmp; 627 INT i, oldNumParts; 628 629 TRACE("(%d,%p)\n", count, parts); 630 631 if(!count) return FALSE; 632 633 oldNumParts = infoPtr->numParts; 634 infoPtr->numParts = count; 635 if (oldNumParts > infoPtr->numParts) { 636 for (i = infoPtr->numParts ; i < oldNumParts; i++) { 637 if (!(infoPtr->parts[i].style & SBT_OWNERDRAW)) 638 Free (infoPtr->parts[i].text); 639 } 640 } else if (oldNumParts < infoPtr->numParts) { 641 tmp = Alloc (sizeof(STATUSWINDOWPART) * infoPtr->numParts); 642 if (!tmp) return FALSE; 643 for (i = 0; i < oldNumParts; i++) { 644 tmp[i] = infoPtr->parts[i]; 645 } 646 Free (infoPtr->parts); 647 infoPtr->parts = tmp; 648 } 649 if (oldNumParts == infoPtr->numParts) { 650 for (i=0; i < oldNumParts; i++) 651 if (infoPtr->parts[i].x != parts[i]) 652 break; 653 if (i==oldNumParts) /* Unchanged? no need to redraw! */ 654 return TRUE; 655 } 656 657 for (i = 0; i < infoPtr->numParts; i++) 658 infoPtr->parts[i].x = parts[i]; 659 660 if (infoPtr->hwndToolTip) { 661 INT nTipCount; 662 TTTOOLINFOW ti; 663 WCHAR wEmpty = 0; 664 665 ZeroMemory (&ti, sizeof(TTTOOLINFOW)); 666 ti.cbSize = sizeof(TTTOOLINFOW); 667 ti.hwnd = infoPtr->Self; 668 ti.lpszText = &wEmpty; 669 670 nTipCount = SendMessageW (infoPtr->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0); 671 if (nTipCount < infoPtr->numParts) { 672 /* add tools */ 673 for (i = nTipCount; i < infoPtr->numParts; i++) { 674 TRACE("add tool %d\n", i); 675 ti.uId = i; 676 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, 677 0, (LPARAM)&ti); 678 } 679 } 680 else if (nTipCount > infoPtr->numParts) { 681 /* delete tools */ 682 for (i = nTipCount - 1; i >= infoPtr->numParts; i--) { 683 TRACE("delete tool %d\n", i); 684 ti.uId = i; 685 SendMessageW (infoPtr->hwndToolTip, TTM_DELTOOLW, 686 0, (LPARAM)&ti); 687 } 688 } 689 } 690 STATUSBAR_SetPartBounds (infoPtr); 691 InvalidateRect(infoPtr->Self, NULL, FALSE); 692 return TRUE; 693 } 694 695 696 static BOOL 697 STATUSBAR_SetTextT (STATUS_INFO *infoPtr, INT nPart, WORD style, 698 LPWSTR text, BOOL isW) 699 { 700 STATUSWINDOWPART *part=NULL; 701 BOOL changed = FALSE; 702 INT oldStyle; 703 704 if (style & SBT_OWNERDRAW) { 705 TRACE("part %d, text %p\n",nPart,text); 706 } 707 else TRACE("part %d, text %s\n", nPart, debugstr_t(text, isW)); 708 709 /* MSDN says: "If the parameter is set to SB_SIMPLEID (255), the status 710 * window is assumed to be a simple window */ 711 712 if (nPart == 0x00ff) { 713 part = &infoPtr->part0; 714 } else { 715 if (infoPtr->parts && nPart >= 0 && nPart < infoPtr->numParts) { 716 part = &infoPtr->parts[nPart]; 717 } 718 } 719 if (!part) return FALSE; 720 721 if (part->style != style) 722 changed = TRUE; 723 724 oldStyle = part->style; 725 part->style = style; 726 if (style & SBT_OWNERDRAW) { 727 if (!(oldStyle & SBT_OWNERDRAW)) 728 Free (part->text); 729 part->text = text; 730 } else { 731 LPWSTR ntext; 732 WCHAR *idx; 733 734 if (text && !isW) { 735 LPCSTR atxt = (LPCSTR)text; 736 DWORD len = MultiByteToWideChar( CP_ACP, 0, atxt, -1, NULL, 0 ); 737 ntext = Alloc( (len + 1)*sizeof(WCHAR) ); 738 if (!ntext) return FALSE; 739 MultiByteToWideChar( CP_ACP, 0, atxt, -1, ntext, len ); 740 } else if (text) { 741 ntext = Alloc( (strlenW(text) + 1)*sizeof(WCHAR) ); 742 if (!ntext) return FALSE; 743 strcpyW (ntext, text); 744 } else ntext = 0; 745 746 /* replace nonprintable characters with spaces */ 747 if (ntext) { 748 idx = ntext; 749 while (*idx) { 750 if(!isprintW(*idx)) 751 *idx = ' '; 752 idx++; 753 } 754 } 755 756 /* check if text is unchanged -> no need to redraw */ 757 if (text) { 758 if (!changed && part->text && !lstrcmpW(ntext, part->text)) { 759 Free(ntext); 760 return TRUE; 761 } 762 } else { 763 if (!changed && !part->text) 764 return TRUE; 765 } 766 767 if (!(oldStyle & SBT_OWNERDRAW)) 768 Free (part->text); 769 part->text = ntext; 770 } 771 InvalidateRect(infoPtr->Self, &part->bound, FALSE); 772 UpdateWindow(infoPtr->Self); 773 774 return TRUE; 775 } 776 777 778 static LRESULT 779 STATUSBAR_SetTipTextA (const STATUS_INFO *infoPtr, INT id, LPSTR text) 780 { 781 TRACE("part %d: \"%s\"\n", id, text); 782 if (infoPtr->hwndToolTip) { 783 TTTOOLINFOA ti; 784 ti.cbSize = sizeof(TTTOOLINFOA); 785 ti.hwnd = infoPtr->Self; 786 ti.uId = id; 787 ti.hinst = 0; 788 ti.lpszText = text; 789 SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA, 0, (LPARAM)&ti); 790 } 791 792 return 0; 793 } 794 795 796 static LRESULT 797 STATUSBAR_SetTipTextW (const STATUS_INFO *infoPtr, INT id, LPWSTR text) 798 { 799 TRACE("part %d: \"%s\"\n", id, debugstr_w(text)); 800 if (infoPtr->hwndToolTip) { 801 TTTOOLINFOW ti; 802 ti.cbSize = sizeof(TTTOOLINFOW); 803 ti.hwnd = infoPtr->Self; 804 ti.uId = id; 805 ti.hinst = 0; 806 ti.lpszText = text; 807 SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti); 808 } 809 810 return 0; 811 } 812 813 814 static inline LRESULT 815 STATUSBAR_SetUnicodeFormat (STATUS_INFO *infoPtr, BOOL bUnicode) 816 { 817 BOOL bOld = infoPtr->bUnicode; 818 819 TRACE("(0x%x)\n", bUnicode); 820 infoPtr->bUnicode = bUnicode; 821 822 return bOld; 823 } 824 825 826 static BOOL 827 STATUSBAR_Simple (STATUS_INFO *infoPtr, BOOL simple) 828 { 829 NMHDR nmhdr; 830 831 TRACE("(simple=%d)\n", simple); 832 if (infoPtr->simple == simple) /* no need to change */ 833 return TRUE; 834 835 infoPtr->simple = simple; 836 837 /* send notification */ 838 nmhdr.hwndFrom = infoPtr->Self; 839 nmhdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); 840 nmhdr.code = SBN_SIMPLEMODECHANGE; 841 SendMessageW (infoPtr->Notify, WM_NOTIFY, 0, (LPARAM)&nmhdr); 842 InvalidateRect(infoPtr->Self, NULL, FALSE); 843 return TRUE; 844 } 845 846 847 static LRESULT 848 STATUSBAR_WMDestroy (STATUS_INFO *infoPtr) 849 { 850 unsigned int i; 851 852 TRACE("\n"); 853 for (i = 0; i < infoPtr->numParts; i++) { 854 if (!(infoPtr->parts[i].style & SBT_OWNERDRAW)) 855 Free (infoPtr->parts[i].text); 856 } 857 if (!(infoPtr->part0.style & SBT_OWNERDRAW)) 858 Free (infoPtr->part0.text); 859 Free (infoPtr->parts); 860 861 /* delete default font */ 862 if (infoPtr->hDefaultFont) 863 DeleteObject (infoPtr->hDefaultFont); 864 865 /* delete tool tip control */ 866 if (infoPtr->hwndToolTip) 867 DestroyWindow (infoPtr->hwndToolTip); 868 869 CloseThemeData (GetWindowTheme (infoPtr->Self)); 870 871 SetWindowLongPtrW(infoPtr->Self, 0, 0); 872 Free (infoPtr); 873 return 0; 874 } 875 876 877 static LRESULT 878 STATUSBAR_WMCreate (HWND hwnd, const CREATESTRUCTA *lpCreate) 879 { 880 STATUS_INFO *infoPtr; 881 NONCLIENTMETRICSW nclm; 882 DWORD dwStyle; 883 RECT rect; 884 int len; 885 886 TRACE("\n"); 887 infoPtr = Alloc (sizeof(STATUS_INFO)); 888 if (!infoPtr) goto create_fail; 889 SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); 890 891 infoPtr->Self = hwnd; 892 infoPtr->Notify = lpCreate->hwndParent; 893 infoPtr->numParts = 1; 894 infoPtr->parts = 0; 895 infoPtr->simple = FALSE; 896 infoPtr->clrBk = CLR_DEFAULT; 897 infoPtr->hFont = 0; 898 infoPtr->horizontalBorder = HORZ_BORDER; 899 infoPtr->verticalBorder = VERT_BORDER; 900 infoPtr->horizontalGap = HORZ_GAP; 901 infoPtr->minHeight = GetSystemMetrics(SM_CYSIZE); 902 if (infoPtr->minHeight & 1) infoPtr->minHeight--; 903 904 STATUSBAR_NotifyFormat(infoPtr, infoPtr->Notify, NF_REQUERY); 905 906 ZeroMemory (&nclm, sizeof(nclm)); 907 nclm.cbSize = sizeof(nclm); 908 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0); 909 infoPtr->hDefaultFont = CreateFontIndirectW (&nclm.lfStatusFont); 910 911 GetClientRect (hwnd, &rect); 912 913 /* initialize simple case */ 914 infoPtr->part0.bound = rect; 915 infoPtr->part0.text = 0; 916 infoPtr->part0.x = 0; 917 infoPtr->part0.style = 0; 918 infoPtr->part0.hIcon = 0; 919 920 /* initialize first part */ 921 infoPtr->parts = Alloc (sizeof(STATUSWINDOWPART)); 922 if (!infoPtr->parts) goto create_fail; 923 infoPtr->parts[0].bound = rect; 924 infoPtr->parts[0].text = 0; 925 infoPtr->parts[0].x = -1; 926 infoPtr->parts[0].style = 0; 927 infoPtr->parts[0].hIcon = 0; 928 929 OpenThemeData (hwnd, themeClass); 930 931 if (lpCreate->lpszName && (len = strlenW ((LPCWSTR)lpCreate->lpszName))) 932 { 933 infoPtr->parts[0].text = Alloc ((len + 1)*sizeof(WCHAR)); 934 if (!infoPtr->parts[0].text) goto create_fail; 935 strcpyW (infoPtr->parts[0].text, (LPCWSTR)lpCreate->lpszName); 936 } 937 938 dwStyle = GetWindowLongW (hwnd, GWL_STYLE); 939 /* native seems to clear WS_BORDER, too */ 940 dwStyle &= ~WS_BORDER; 941 SetWindowLongW (hwnd, GWL_STYLE, dwStyle); 942 943 infoPtr->height = STATUSBAR_ComputeHeight(infoPtr); 944 945 if (dwStyle & SBT_TOOLTIPS) { 946 infoPtr->hwndToolTip = 947 CreateWindowExW (0, TOOLTIPS_CLASSW, NULL, WS_POPUP | TTS_ALWAYSTIP, 948 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 949 CW_USEDEFAULT, hwnd, 0, 950 (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE), NULL); 951 952 if (infoPtr->hwndToolTip) { 953 NMTOOLTIPSCREATED nmttc; 954 955 nmttc.hdr.hwndFrom = hwnd; 956 nmttc.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); 957 nmttc.hdr.code = NM_TOOLTIPSCREATED; 958 nmttc.hwndToolTips = infoPtr->hwndToolTip; 959 960 SendMessageW (lpCreate->hwndParent, WM_NOTIFY, nmttc.hdr.idFrom, (LPARAM)&nmttc); 961 } 962 } 963 964 return 0; 965 966 create_fail: 967 TRACE(" failed!\n"); 968 if (infoPtr) STATUSBAR_WMDestroy(infoPtr); 969 return -1; 970 } 971 972 973 /* in contrast to SB_GETTEXT*, WM_GETTEXT handles the text 974 * of the first part only (usual behaviour) */ 975 static INT 976 STATUSBAR_WMGetText (const STATUS_INFO *infoPtr, INT size, LPWSTR buf) 977 { 978 INT len; 979 980 TRACE("\n"); 981 if (!(infoPtr->parts[0].text)) 982 return 0; 983 984 len = strlenW (infoPtr->parts[0].text); 985 986 if (!size) 987 return len; 988 else if (size > len) { 989 strcpyW (buf, infoPtr->parts[0].text); 990 return len; 991 } 992 else { 993 memcpy (buf, infoPtr->parts[0].text, (size - 1) * sizeof(WCHAR)); 994 buf[size - 1] = 0; 995 return size - 1; 996 } 997 } 998 999 1000 static BOOL 1001 STATUSBAR_WMNCHitTest (const STATUS_INFO *infoPtr, INT x, INT y) 1002 { 1003 if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) { 1004 RECT rect; 1005 POINT pt; 1006 1007 GetClientRect (infoPtr->Self, &rect); 1008 1009 pt.x = x; 1010 pt.y = y; 1011 ScreenToClient (infoPtr->Self, &pt); 1012 1013 rect.left = rect.right - 13; 1014 rect.top += 2; 1015 1016 if (PtInRect (&rect, pt)) 1017 { 1018 if (GetWindowLongW( infoPtr->Self, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) return HTBOTTOMLEFT; 1019 else return HTBOTTOMRIGHT; 1020 } 1021 } 1022 1023 return HTERROR; 1024 } 1025 1026 1027 static LRESULT 1028 STATUSBAR_WMPaint (STATUS_INFO *infoPtr, HDC hdc) 1029 { 1030 PAINTSTRUCT ps; 1031 1032 TRACE("\n"); 1033 if (hdc) return STATUSBAR_Refresh (infoPtr, hdc); 1034 hdc = BeginPaint (infoPtr->Self, &ps); 1035 STATUSBAR_Refresh (infoPtr, hdc); 1036 EndPaint (infoPtr->Self, &ps); 1037 1038 return 0; 1039 } 1040 1041 1042 static LRESULT 1043 STATUSBAR_WMSetFont (STATUS_INFO *infoPtr, HFONT font, BOOL redraw) 1044 { 1045 infoPtr->hFont = font; 1046 TRACE("%p\n", infoPtr->hFont); 1047 1048 infoPtr->height = STATUSBAR_ComputeHeight(infoPtr); 1049 SendMessageW(infoPtr->Self, WM_SIZE, 0, 0); /* update size */ 1050 if (redraw) 1051 InvalidateRect(infoPtr->Self, NULL, FALSE); 1052 1053 return 0; 1054 } 1055 1056 1057 static BOOL 1058 STATUSBAR_WMSetText (const STATUS_INFO *infoPtr, LPCSTR text) 1059 { 1060 STATUSWINDOWPART *part; 1061 int len; 1062 1063 TRACE("\n"); 1064 if (infoPtr->numParts == 0) 1065 return FALSE; 1066 1067 part = &infoPtr->parts[0]; 1068 /* duplicate string */ 1069 Free (part->text); 1070 part->text = 0; 1071 1072 if (text && (len = strlenW((LPCWSTR)text))) { 1073 part->text = Alloc ((len+1)*sizeof(WCHAR)); 1074 if (!part->text) return FALSE; 1075 strcpyW (part->text, (LPCWSTR)text); 1076 } 1077 1078 InvalidateRect(infoPtr->Self, &part->bound, FALSE); 1079 1080 return TRUE; 1081 } 1082 1083 1084 static BOOL 1085 STATUSBAR_WMSize (STATUS_INFO *infoPtr, WORD flags) 1086 { 1087 INT width, x, y; 1088 RECT parent_rect; 1089 1090 /* Need to resize width to match parent */ 1091 TRACE("flags %04x\n", flags); 1092 1093 if (flags != SIZE_RESTORED && flags != SIZE_MAXIMIZED) { 1094 WARN("flags MUST be SIZE_RESTORED or SIZE_MAXIMIZED\n"); 1095 return FALSE; 1096 } 1097 1098 if (GetWindowLongW(infoPtr->Self, GWL_STYLE) & CCS_NORESIZE) return FALSE; 1099 1100 /* width and height don't apply */ 1101 if (!GetClientRect (infoPtr->Notify, &parent_rect)) 1102 return FALSE; 1103 1104 width = parent_rect.right - parent_rect.left; 1105 x = parent_rect.left; 1106 y = parent_rect.bottom - infoPtr->height; 1107 MoveWindow (infoPtr->Self, x, y, width, infoPtr->height, TRUE); 1108 STATUSBAR_SetPartBounds (infoPtr); 1109 return TRUE; 1110 } 1111 1112 1113 /* update theme after a WM_THEMECHANGED message */ 1114 static LRESULT theme_changed (const STATUS_INFO* infoPtr) 1115 { 1116 HTHEME theme = GetWindowTheme (infoPtr->Self); 1117 CloseThemeData (theme); 1118 OpenThemeData (infoPtr->Self, themeClass); 1119 return 0; 1120 } 1121 1122 1123 static LRESULT 1124 STATUSBAR_NotifyFormat (STATUS_INFO *infoPtr, HWND from, INT cmd) 1125 { 1126 if (cmd == NF_REQUERY) { 1127 INT i = SendMessageW(from, WM_NOTIFYFORMAT, (WPARAM)infoPtr->Self, NF_QUERY); 1128 infoPtr->bUnicode = (i == NFR_UNICODE); 1129 } 1130 return infoPtr->bUnicode ? NFR_UNICODE : NFR_ANSI; 1131 } 1132 1133 1134 static LRESULT 1135 STATUSBAR_SendMouseNotify(const STATUS_INFO *infoPtr, UINT code, UINT msg, WPARAM wParam, LPARAM lParam) 1136 { 1137 NMMOUSE nm; 1138 1139 TRACE("code %04x, lParam=%lx\n", code, lParam); 1140 nm.hdr.hwndFrom = infoPtr->Self; 1141 nm.hdr.idFrom = GetWindowLongPtrW(infoPtr->Self, GWLP_ID); 1142 nm.hdr.code = code; 1143 nm.pt.x = (short)LOWORD(lParam); 1144 nm.pt.y = (short)HIWORD(lParam); 1145 nm.dwItemSpec = STATUSBAR_InternalHitTest(infoPtr, &nm.pt); 1146 nm.dwItemData = 0; 1147 nm.dwHitInfo = 0x30000; /* seems constant */ 1148 1149 /* Do default processing if WM_NOTIFY returns zero */ 1150 if(!SendMessageW(infoPtr->Notify, WM_NOTIFY, nm.hdr.idFrom, (LPARAM)&nm)) 1151 { 1152 return DefWindowProcW(infoPtr->Self, msg, wParam, lParam); 1153 } 1154 return 0; 1155 } 1156 1157 1158 1159 static LRESULT WINAPI 1160 StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1161 { 1162 STATUS_INFO *infoPtr = (STATUS_INFO *)GetWindowLongPtrW (hwnd, 0); 1163 INT nPart = ((INT) wParam) & 0x00ff; 1164 LRESULT res; 1165 1166 TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hwnd, msg, wParam, lParam); 1167 if (!infoPtr && msg != WM_CREATE) 1168 return DefWindowProcW (hwnd, msg, wParam, lParam); 1169 1170 switch (msg) { 1171 case SB_GETBORDERS: 1172 return STATUSBAR_GetBorders (infoPtr, (INT *)lParam); 1173 1174 case SB_GETICON: 1175 return (LRESULT)STATUSBAR_GetIcon (infoPtr, nPart); 1176 1177 case SB_GETPARTS: 1178 return STATUSBAR_GetParts (infoPtr, (INT)wParam, (INT *)lParam); 1179 1180 case SB_GETRECT: 1181 return STATUSBAR_GetRect (infoPtr, nPart, (LPRECT)lParam); 1182 1183 case SB_GETTEXTA: 1184 return STATUSBAR_GetTextA (infoPtr, nPart, (LPSTR)lParam); 1185 1186 case SB_GETTEXTW: 1187 return STATUSBAR_GetTextW (infoPtr, nPart, (LPWSTR)lParam); 1188 1189 case SB_GETTEXTLENGTHA: 1190 case SB_GETTEXTLENGTHW: 1191 return STATUSBAR_GetTextLength (infoPtr, nPart); 1192 1193 case SB_GETTIPTEXTA: 1194 return STATUSBAR_GetTipTextA (infoPtr, LOWORD(wParam), (LPSTR)lParam, HIWORD(wParam)); 1195 1196 case SB_GETTIPTEXTW: 1197 return STATUSBAR_GetTipTextW (infoPtr, LOWORD(wParam), (LPWSTR)lParam, HIWORD(wParam)); 1198 1199 case SB_GETUNICODEFORMAT: 1200 return infoPtr->bUnicode; 1201 1202 case SB_ISSIMPLE: 1203 return infoPtr->simple; 1204 1205 case SB_SETBORDERS: 1206 return STATUSBAR_SetBorders (infoPtr, (INT *)lParam); 1207 1208 case SB_SETBKCOLOR: 1209 return STATUSBAR_SetBkColor (infoPtr, (COLORREF)lParam); 1210 1211 case SB_SETICON: 1212 return STATUSBAR_SetIcon (infoPtr, nPart, (HICON)lParam); 1213 1214 case SB_SETMINHEIGHT: 1215 return STATUSBAR_SetMinHeight (infoPtr, (INT)wParam); 1216 1217 case SB_SETPARTS: 1218 return STATUSBAR_SetParts (infoPtr, (INT)wParam, (LPINT)lParam); 1219 1220 case SB_SETTEXTA: 1221 return STATUSBAR_SetTextT (infoPtr, nPart, wParam & 0xff00, (LPWSTR)lParam, FALSE); 1222 1223 case SB_SETTEXTW: 1224 return STATUSBAR_SetTextT (infoPtr, nPart, wParam & 0xff00, (LPWSTR)lParam, TRUE); 1225 1226 case SB_SETTIPTEXTA: 1227 return STATUSBAR_SetTipTextA (infoPtr, (INT)wParam, (LPSTR)lParam); 1228 1229 case SB_SETTIPTEXTW: 1230 return STATUSBAR_SetTipTextW (infoPtr, (INT)wParam, (LPWSTR)lParam); 1231 1232 case SB_SETUNICODEFORMAT: 1233 return STATUSBAR_SetUnicodeFormat (infoPtr, (BOOL)wParam); 1234 1235 case SB_SIMPLE: 1236 return STATUSBAR_Simple (infoPtr, (BOOL)wParam); 1237 1238 case WM_CREATE: 1239 return STATUSBAR_WMCreate (hwnd, (LPCREATESTRUCTA)lParam); 1240 1241 case WM_DESTROY: 1242 return STATUSBAR_WMDestroy (infoPtr); 1243 1244 case WM_GETFONT: 1245 return (LRESULT)(infoPtr->hFont? infoPtr->hFont : infoPtr->hDefaultFont); 1246 1247 case WM_GETTEXT: 1248 return STATUSBAR_WMGetText (infoPtr, (INT)wParam, (LPWSTR)lParam); 1249 1250 case WM_GETTEXTLENGTH: 1251 return LOWORD(STATUSBAR_GetTextLength (infoPtr, 0)); 1252 1253 case WM_LBUTTONDBLCLK: 1254 return STATUSBAR_SendMouseNotify(infoPtr, NM_DBLCLK, msg, wParam, lParam); 1255 1256 case WM_LBUTTONUP: 1257 return STATUSBAR_SendMouseNotify(infoPtr, NM_CLICK, msg, wParam, lParam); 1258 1259 case WM_MOUSEMOVE: 1260 return STATUSBAR_Relay2Tip (infoPtr, msg, wParam, lParam); 1261 1262 case WM_NCHITTEST: 1263 res = STATUSBAR_WMNCHitTest(infoPtr, (short)LOWORD(lParam), 1264 (short)HIWORD(lParam)); 1265 if (res != HTERROR) return res; 1266 return DefWindowProcW (hwnd, msg, wParam, lParam); 1267 1268 case WM_NCLBUTTONUP: 1269 case WM_NCLBUTTONDOWN: 1270 PostMessageW (infoPtr->Notify, msg, wParam, lParam); 1271 return 0; 1272 1273 case WM_NOTIFYFORMAT: 1274 return STATUSBAR_NotifyFormat(infoPtr, (HWND)wParam, (INT)lParam); 1275 1276 case WM_PRINTCLIENT: 1277 case WM_PAINT: 1278 return STATUSBAR_WMPaint (infoPtr, (HDC)wParam); 1279 1280 case WM_RBUTTONDBLCLK: 1281 return STATUSBAR_SendMouseNotify(infoPtr, NM_RDBLCLK, msg, wParam, lParam); 1282 1283 case WM_RBUTTONUP: 1284 return STATUSBAR_SendMouseNotify(infoPtr, NM_RCLICK, msg, wParam, lParam); 1285 1286 case WM_SETFONT: 1287 return STATUSBAR_WMSetFont (infoPtr, (HFONT)wParam, LOWORD(lParam)); 1288 1289 case WM_SETTEXT: 1290 return STATUSBAR_WMSetText (infoPtr, (LPCSTR)lParam); 1291 1292 case WM_SIZE: 1293 if (STATUSBAR_WMSize (infoPtr, (WORD)wParam)) return 0; 1294 return DefWindowProcW (hwnd, msg, wParam, lParam); 1295 1296 case WM_SYSCOLORCHANGE: 1297 COMCTL32_RefreshSysColors(); 1298 return 0; 1299 1300 case WM_THEMECHANGED: 1301 return theme_changed (infoPtr); 1302 1303 default: 1304 if ((msg >= WM_USER) && (msg < WM_APP) && !COMCTL32_IsReflectedMessage(msg)) 1305 ERR("unknown msg %04x wp=%04lx lp=%08lx\n", 1306 msg, wParam, lParam); 1307 return DefWindowProcW (hwnd, msg, wParam, lParam); 1308 } 1309 } 1310 1311 1312 /*********************************************************************** 1313 * STATUS_Register [Internal] 1314 * 1315 * Registers the status window class. 1316 */ 1317 1318 void 1319 STATUS_Register (void) 1320 { 1321 WNDCLASSW wndClass; 1322 1323 ZeroMemory (&wndClass, sizeof(WNDCLASSW)); 1324 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW; 1325 wndClass.lpfnWndProc = StatusWindowProc; 1326 wndClass.cbClsExtra = 0; 1327 wndClass.cbWndExtra = sizeof(STATUS_INFO *); 1328 wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); 1329 wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 1330 wndClass.lpszClassName = STATUSCLASSNAMEW; 1331 1332 RegisterClassW (&wndClass); 1333 } 1334 1335 1336 /*********************************************************************** 1337 * STATUS_Unregister [Internal] 1338 * 1339 * Unregisters the status window class. 1340 */ 1341 1342 void 1343 STATUS_Unregister (void) 1344 { 1345 UnregisterClassW (STATUSCLASSNAMEW, NULL); 1346 } 1347