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