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