2 * Interface code to StatusWindow widget/control
4 * Copyright 1996 Bruce Milner
5 * Copyright 1998, 1999 Eric Kohl
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
24 * 2) Tooltip support (almost done).
25 * 3) where else should we use infoPtr->hwndParent instead of GetParent() ?
26 * 4) send WM_QUERYFORMAT
31 #include "wine/unicode.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(statusbar);
56 COLORREF clrBk; /* background color */
57 BOOL bUnicode; /* unicode flag */
58 STATUSWINDOWPART part0; /* simple window */
59 STATUSWINDOWPART *parts;
63 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
64 * The second cdrom contains executables drawstat.exe, gettext.exe,
65 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
72 #define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
76 STATUSBAR_SetPartBounds (STATUSWINDOWINFO *infoPtr, HWND hwnd);
79 STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
85 TRACE("draw size grip %d,%d - %d,%d\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
86 pt.x = lpRect->right - 1;
87 pt.y = lpRect->bottom - 1;
89 hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
90 MoveToEx (hdc, pt.x - 12, pt.y, NULL);
91 LineTo (hdc, pt.x, pt.y);
92 LineTo (hdc, pt.x, pt.y - 12);
97 SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
98 for (i = 1; i < 11; i += 4) {
99 MoveToEx (hdc, pt.x - i, pt.y, NULL);
100 LineTo (hdc, pt.x, pt.y - i);
102 MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
103 LineTo (hdc, pt.x, pt.y - i-1);
106 SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
107 for (i = 3; i < 13; i += 4) {
108 MoveToEx (hdc, pt.x - i, pt.y, NULL);
109 LineTo (hdc, pt.x, pt.y - i);
112 SelectObject (hdc, hOldPen);
117 STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
119 RECT r = part->bound;
120 UINT border = BDR_SUNKENOUTER;
122 TRACE("part bound %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom);
123 if (part->style & SBT_POPOUT)
124 border = BDR_RAISEDOUTER;
125 else if (part->style & SBT_NOBORDERS)
128 DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
132 INT cy = r.bottom - r.top;
135 DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
141 int oldbkmode = SetBkMode(hdc, TRANSPARENT);
142 LPWSTR p = (LPWSTR)part->text;
143 UINT align = DT_LEFT;
154 TRACE("%s at %d,%d - %d,%d\n", debugstr_w(p), r.left, r.top, r.right, r.bottom);
155 DrawTextW (hdc, p, -1, &r, align|DT_VCENTER|DT_SINGLELINE);
156 if (oldbkmode != TRANSPARENT)
157 SetBkMode(hdc, oldbkmode);
163 STATUSBAR_RefreshPart (STATUSWINDOWINFO *infoPtr, HWND hwnd, STATUSWINDOWPART *part, HDC hdc, int itemID)
168 TRACE("item %d\n", itemID);
169 if (!IsWindowVisible (hwnd))
172 if (part->bound.right < part->bound.left) return;
174 if (infoPtr->clrBk != CLR_DEFAULT)
175 hbrBk = CreateSolidBrush (infoPtr->clrBk);
177 hbrBk = GetSysColorBrush (COLOR_3DFACE);
178 FillRect(hdc, &part->bound, hbrBk);
180 hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
182 if (part->style & SBT_OWNERDRAW) {
185 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
189 dis.rcItem = part->bound;
190 dis.itemData = (INT)part->text;
191 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
192 (WPARAM)dis.CtlID, (LPARAM)&dis);
194 STATUSBAR_DrawPart (hdc, part);
196 SelectObject (hdc, hOldFont);
198 if (infoPtr->clrBk != CLR_DEFAULT)
199 DeleteObject (hbrBk);
201 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
204 GetClientRect (hwnd, &rect);
205 STATUSBAR_DrawSizeGrip (hdc, &rect);
211 STATUSBAR_Refresh (STATUSWINDOWINFO *infoPtr, HWND hwnd, HDC hdc)
219 if (!IsWindowVisible(hwnd))
222 STATUSBAR_SetPartBounds(infoPtr, hwnd);
224 GetClientRect (hwnd, &rect);
226 if (infoPtr->clrBk != CLR_DEFAULT)
227 hbrBk = CreateSolidBrush (infoPtr->clrBk);
229 hbrBk = GetSysColorBrush (COLOR_3DFACE);
230 FillRect(hdc, &rect, hbrBk);
232 hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
234 if (infoPtr->simple) {
235 STATUSBAR_RefreshPart (infoPtr, hwnd, &infoPtr->part0, hdc, 0);
237 for (i = 0; i < infoPtr->numParts; i++) {
238 if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
241 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
245 dis.rcItem = infoPtr->parts[i].bound;
246 dis.itemData = (INT)infoPtr->parts[i].text;
247 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
248 (WPARAM)dis.CtlID, (LPARAM)&dis);
250 STATUSBAR_RefreshPart (infoPtr, hwnd, &infoPtr->parts[i], hdc, i);
254 SelectObject (hdc, hOldFont);
256 if (infoPtr->clrBk != CLR_DEFAULT)
257 DeleteObject (hbrBk);
259 if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
260 STATUSBAR_DrawSizeGrip (hdc, &rect);
267 STATUSBAR_SetPartBounds (STATUSWINDOWINFO *infoPtr, HWND hwnd)
269 STATUSWINDOWPART *part;
273 /* get our window size */
274 GetClientRect (hwnd, &rect);
275 TRACE("client wnd size is %d,%d - %d,%d\n", rect.left, rect.top, rect.right, rect.bottom);
277 rect.top += VERT_BORDER;
279 /* set bounds for simple rectangle */
280 infoPtr->part0.bound = rect;
282 /* set bounds for non-simple rectangles */
283 for (i = 0; i < infoPtr->numParts; i++) {
284 part = &infoPtr->parts[i];
285 r = &infoPtr->parts[i].bound;
287 r->bottom = rect.bottom;
291 r->left = infoPtr->parts[i-1].bound.right + HORZ_GAP;
293 r->right = rect.right;
297 if (infoPtr->hwndToolTip) {
300 ti.cbSize = sizeof(TTTOOLINFOA);
304 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
312 STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
313 WPARAM wParam, LPARAM lParam)
321 msg.time = GetMessageTime ();
322 msg.pt.x = LOWORD(GetMessagePos ());
323 msg.pt.y = HIWORD(GetMessagePos ());
325 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
329 inline static LRESULT
330 STATUSBAR_GetBorders (LPARAM lParam)
332 LPINT out = (LPINT) lParam;
335 out[0] = HORZ_BORDER; /* horizontal border width */
336 out[1] = VERT_BORDER; /* vertical border width */
337 out[2] = HORZ_GAP; /* width of border between rectangles */
344 STATUSBAR_GetIcon (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
348 nPart = (INT)wParam & 0x00ff;
349 TRACE("%d\n", nPart);
350 if ((nPart < -1) || (nPart >= infoPtr->numParts))
354 return (infoPtr->part0.hIcon);
356 return (infoPtr->parts[nPart].hIcon);
361 STATUSBAR_GetParts (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
367 num_parts = (INT) wParam;
368 TRACE("(%d)\n", num_parts);
369 parts = (LPINT) lParam;
371 for (i = 0; i < num_parts; i++) {
372 parts[i] = infoPtr->parts[i].x;
375 return (infoPtr->numParts);
380 STATUSBAR_GetRect (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
385 nPart = ((INT) wParam) & 0x00ff;
386 TRACE("part %d\n", nPart);
387 rect = (LPRECT) lParam;
389 *rect = infoPtr->part0.bound;
391 *rect = infoPtr->parts[nPart].bound;
397 STATUSBAR_GetTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
399 STATUSWINDOWPART *part;
403 nPart = ((INT) wParam) & 0x00ff;
404 TRACE("part %d\n", nPart);
406 part = &infoPtr->part0;
408 part = &infoPtr->parts[nPart];
410 if (part->style & SBT_OWNERDRAW)
411 result = (LRESULT)part->text;
413 DWORD len = part->text ? WideCharToMultiByte( CP_ACP, 0, part->text, -1,
414 NULL, 0, NULL, NULL ) - 1 : 0;
415 result = MAKELONG( len, part->style );
417 WideCharToMultiByte( CP_ACP, 0, part->text, -1, (LPSTR)lParam, len+1, NULL, NULL );
424 STATUSBAR_GetTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
426 STATUSWINDOWPART *part;
430 nPart = ((INT)wParam) & 0x00ff;
431 TRACE("part %d\n", nPart);
433 part = &infoPtr->part0;
435 part = &infoPtr->parts[nPart];
437 if (part->style & SBT_OWNERDRAW)
438 result = (LRESULT)part->text;
440 result = part->text ? strlenW (part->text) : 0;
441 result |= (part->style << 16);
442 if (part->text && lParam)
443 strcpyW ((LPWSTR)lParam, part->text);
450 STATUSBAR_GetTextLength (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
452 STATUSWINDOWPART *part;
456 nPart = ((INT) wParam) & 0x00ff;
458 TRACE("part %d\n", nPart);
460 part = &infoPtr->part0;
462 part = &infoPtr->parts[nPart];
465 result = strlenW(part->text);
469 result |= (part->style << 16);
475 STATUSBAR_GetTipTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
477 LPSTR tip = (LPSTR)lParam;
480 CHAR buf[INFOTIPSIZE];
483 if (infoPtr->hwndToolTip) {
485 ti.cbSize = sizeof(TTTOOLINFOA);
487 ti.uId = LOWORD(wParam);
489 SendMessageA(infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
491 lstrcpynA(tip, buf, HIWORD(wParam));
498 STATUSBAR_GetTipTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
500 LPWSTR tip = (LPWSTR)lParam;
504 WCHAR buf[INFOTIPSIZE];
507 if (infoPtr->hwndToolTip) {
509 ti.cbSize = sizeof(TTTOOLINFOW);
511 ti.uId = LOWORD(wParam);
513 SendMessageW(infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
515 lstrcpynW(tip, buf, HIWORD(wParam));
522 inline static LRESULT
523 STATUSBAR_GetUnicodeFormat (STATUSWINDOWINFO *infoPtr, HWND hwnd)
525 return infoPtr->bUnicode;
529 inline static LRESULT
530 STATUSBAR_IsSimple (STATUSWINDOWINFO *infoPtr, HWND hwnd)
532 return infoPtr->simple;
537 STATUSBAR_SetBkColor (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
541 oldBkColor = infoPtr->clrBk;
542 infoPtr->clrBk = (COLORREF)lParam;
543 InvalidateRect(hwnd, NULL, FALSE);
545 TRACE("CREF: %08lx -> %08lx\n", oldBkColor, infoPtr->clrBk);
551 STATUSBAR_SetIcon (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
553 INT nPart = (INT)wParam & 0x00ff;
555 if ((nPart < -1) || (nPart >= infoPtr->numParts))
558 TRACE("setting part %d, icon %lx\n",nPart,lParam);
561 if (infoPtr->part0.hIcon == (HICON)lParam) /* same as - no redraw */
563 infoPtr->part0.hIcon = (HICON)lParam;
565 InvalidateRect(hwnd, &infoPtr->part0.bound, FALSE);
567 if (infoPtr->parts[nPart].hIcon == (HICON)lParam) /* same as - no redraw */
570 infoPtr->parts[nPart].hIcon = (HICON)lParam;
571 if (!(infoPtr->simple))
572 InvalidateRect(hwnd, &infoPtr->parts[nPart].bound, FALSE);
579 STATUSBAR_SetMinHeight (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
583 if (IsWindowVisible (hwnd)) {
584 HWND parent = GetParent (hwnd);
588 GetClientRect (parent, &parent_rect);
589 infoPtr->height = (INT)wParam + VERT_BORDER;
590 width = parent_rect.right - parent_rect.left;
591 x = parent_rect.left;
592 y = parent_rect.bottom - infoPtr->height;
593 MoveWindow (hwnd, parent_rect.left,
594 parent_rect.bottom - infoPtr->height,
595 width, infoPtr->height, TRUE);
596 STATUSBAR_SetPartBounds (infoPtr, hwnd);
604 STATUSBAR_SetParts (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
606 STATUSWINDOWPART *tmp;
611 TRACE("(%d,%p)\n",wParam,(LPVOID)lParam);
613 /* FIXME: should return FALSE sometimes (maybe when wParam == 0 ?) */
615 infoPtr->simple = FALSE;
617 oldNumParts = infoPtr->numParts;
618 infoPtr->numParts = (INT) wParam;
619 parts = (LPINT) lParam;
620 if (oldNumParts > infoPtr->numParts) {
621 for (i = infoPtr->numParts ; i < oldNumParts; i++) {
622 if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW))
623 COMCTL32_Free (infoPtr->parts[i].text);
626 if (oldNumParts < infoPtr->numParts) {
627 tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * infoPtr->numParts);
628 for (i = 0; i < oldNumParts; i++) {
629 tmp[i] = infoPtr->parts[i];
632 COMCTL32_Free (infoPtr->parts);
633 infoPtr->parts = tmp;
635 if (oldNumParts == infoPtr->numParts) {
636 for (i=0;i<oldNumParts;i++)
637 if (infoPtr->parts[i].x != parts[i])
639 if (i==oldNumParts) /* Unchanged? no need to redraw! */
643 for (i = 0; i < infoPtr->numParts; i++)
644 infoPtr->parts[i].x = parts[i];
646 if (infoPtr->hwndToolTip) {
648 SendMessageA (infoPtr->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
650 if (nTipCount < infoPtr->numParts) {
655 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
656 ti.cbSize = sizeof(TTTOOLINFOA);
658 for (i = nTipCount; i < infoPtr->numParts; i++) {
659 TRACE("add tool %d\n", i);
661 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
665 else if (nTipCount > infoPtr->numParts) {
669 for (i = nTipCount - 1; i >= infoPtr->numParts; i--) {
670 FIXME("delete tool %d\n", i);
674 STATUSBAR_SetPartBounds (infoPtr, hwnd);
675 InvalidateRect(hwnd, NULL, FALSE);
681 STATUSBAR_SetTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
683 STATUSWINDOWPART *part=NULL;
687 BOOL changed = FALSE;
689 text = (LPSTR) lParam;
690 nPart = ((INT) wParam) & 0x00ff;
691 style = ((INT) wParam) & 0xff00;
693 TRACE("part %d, text %s\n",nPart,debugstr_a(text));
696 part = &infoPtr->part0;
697 else if (!infoPtr->simple && infoPtr->parts!=NULL)
698 part = &infoPtr->parts[nPart];
699 if (!part) return FALSE;
701 if (part->style != style)
705 if (style & SBT_OWNERDRAW) {
706 if (part->text == (LPWSTR)text)
708 part->text = (LPWSTR)text;
712 /* check if text is unchanged -> no need to redraw */
714 DWORD len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
715 LPWSTR tmptext = COMCTL32_Alloc(len*sizeof(WCHAR));
716 MultiByteToWideChar( CP_ACP, 0, text, -1, tmptext, len );
718 if (!changed && part->text && !lstrcmpW(tmptext,part->text)) {
719 COMCTL32_Free(tmptext);
724 if (!changed && !part->text)
730 COMCTL32_Free (part->text);
733 InvalidateRect(hwnd, &part->bound, FALSE);
740 STATUSBAR_SetTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
742 STATUSWINDOWPART *part;
743 INT nPart, style, len;
745 BOOL bRedraw = FALSE;
747 text = (LPWSTR) lParam;
748 nPart = ((INT) wParam) & 0x00ff;
749 style = ((INT) wParam) & 0xff00;
751 TRACE("part %d -> %s with style %04x\n", nPart, debugstr_w(text), style);
752 if ((infoPtr->simple) || (infoPtr->parts==NULL) || (nPart==255))
753 part = &infoPtr->part0;
755 part = &infoPtr->parts[nPart];
756 if (!part) return FALSE;
758 if(part->style != style)
763 /* FIXME: not sure how/if we can check for change in string with ownerdraw(remove this if we can't)... */
764 if (style & SBT_OWNERDRAW)
772 COMCTL32_Free(part->text);
776 } else if(!part->text || strcmpW(part->text, text)) /* see if the new string differs from the existing string */
778 if(part->text) COMCTL32_Free(part->text);
781 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
782 strcpyW(part->text, text);
787 InvalidateRect(hwnd, &part->bound, FALSE);
794 STATUSBAR_SetTipTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
796 TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
797 if (infoPtr->hwndToolTip) {
799 ti.cbSize = sizeof(TTTOOLINFOA);
801 ti.uId = (INT)wParam;
803 ti.lpszText = (LPSTR)lParam;
804 SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
813 STATUSBAR_SetTipTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
815 TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
816 if (infoPtr->hwndToolTip) {
818 ti.cbSize = sizeof(TTTOOLINFOW);
820 ti.uId = (INT)wParam;
822 ti.lpszText = (LPWSTR)lParam;
823 SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW,
831 inline static LRESULT
832 STATUSBAR_SetUnicodeFormat (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
834 BOOL bOld = infoPtr->bUnicode;
836 TRACE("(0x%x)\n", (BOOL)wParam);
837 infoPtr->bUnicode = (BOOL)wParam;
844 STATUSBAR_Simple (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
848 TRACE("(is simple: %d)\n", wParam);
849 if (infoPtr->simple == wParam) /* no need to change */
852 infoPtr->simple = (BOOL)wParam;
854 /* send notification */
855 nmhdr.hwndFrom = hwnd;
856 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
857 nmhdr.code = SBN_SIMPLEMODECHANGE;
858 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
859 InvalidateRect(hwnd, NULL, FALSE);
865 STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
867 LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
868 NONCLIENTMETRICSA nclm;
873 STATUSWINDOWINFO *infoPtr;
876 infoPtr = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
877 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
879 infoPtr->hwndParent = lpCreate->hwndParent;
880 infoPtr->numParts = 1;
882 infoPtr->simple = FALSE;
883 infoPtr->clrBk = CLR_DEFAULT;
886 /* TODO: send unicode parent notification query (WM_QUERYFORMAT) here */
888 GetClientRect (hwnd, &rect);
889 InvalidateRect (hwnd, &rect, 0);
892 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
893 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0);
894 infoPtr->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
896 /* initialize simple case */
897 infoPtr->part0.bound = rect;
898 infoPtr->part0.text = 0;
899 infoPtr->part0.x = 0;
900 infoPtr->part0.style = 0;
901 infoPtr->part0.hIcon = 0;
903 /* initialize first part */
904 infoPtr->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
905 infoPtr->parts[0].bound = rect;
906 infoPtr->parts[0].text = 0;
907 infoPtr->parts[0].x = -1;
908 infoPtr->parts[0].style = 0;
909 infoPtr->parts[0].hIcon = 0;
911 if (IsWindowUnicode (hwnd)) {
912 infoPtr->bUnicode = TRUE;
913 if (lpCreate->lpszName &&
914 (len = strlenW ((LPCWSTR)lpCreate->lpszName))) {
915 infoPtr->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
916 strcpyW (infoPtr->parts[0].text, (LPCWSTR)lpCreate->lpszName);
920 if (lpCreate->lpszName &&
921 (len = strlen((LPCSTR)lpCreate->lpszName))) {
922 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1, NULL, 0 );
923 infoPtr->parts[0].text = COMCTL32_Alloc (lenW*sizeof(WCHAR));
924 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1,
925 infoPtr->parts[0].text, lenW );
929 dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
931 /* statusbars on managed windows should not have SIZEGRIP style */
932 if ((dwStyle & SBARS_SIZEGRIP) && lpCreate->hwndParent)
933 if (GetWindowLongA(lpCreate->hwndParent, GWL_EXSTYLE) & WS_EX_MANAGED)
934 SetWindowLongA (hwnd, GWL_STYLE, dwStyle & ~SBARS_SIZEGRIP);
936 if ((hdc = GetDC (0))) {
940 hOldFont = SelectObject (hdc,infoPtr->hDefaultFont);
941 GetTextMetricsA(hdc, &tm);
942 infoPtr->textHeight = tm.tmHeight;
943 SelectObject (hdc, hOldFont);
947 if (dwStyle & SBT_TOOLTIPS) {
948 infoPtr->hwndToolTip =
949 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
950 CW_USEDEFAULT, CW_USEDEFAULT,
951 CW_USEDEFAULT, CW_USEDEFAULT,
953 GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
955 if (infoPtr->hwndToolTip) {
956 NMTOOLTIPSCREATED nmttc;
958 nmttc.hdr.hwndFrom = hwnd;
959 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
960 nmttc.hdr.code = NM_TOOLTIPSCREATED;
961 nmttc.hwndToolTips = infoPtr->hwndToolTip;
963 SendMessageA (lpCreate->hwndParent, WM_NOTIFY,
964 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
968 if (!(dwStyle & CCS_NORESIZE)) /* don't resize wnd if it doesn't want it ! */
970 GetClientRect (GetParent (hwnd), &rect);
971 width = rect.right - rect.left;
972 infoPtr->height = infoPtr->textHeight + 4 + VERT_BORDER;
973 SetWindowPos(hwnd, 0, lpCreate->x, lpCreate->y - 1,
974 width, infoPtr->height, SWP_NOZORDER);
975 STATUSBAR_SetPartBounds (infoPtr, hwnd);
983 STATUSBAR_WMDestroy (STATUSWINDOWINFO *infoPtr, HWND hwnd)
988 for (i = 0; i < infoPtr->numParts; i++) {
989 if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW))
990 COMCTL32_Free (infoPtr->parts[i].text);
992 if (infoPtr->part0.text && !(infoPtr->part0.style & SBT_OWNERDRAW))
993 COMCTL32_Free (infoPtr->part0.text);
994 COMCTL32_Free (infoPtr->parts);
996 /* delete default font */
997 if (infoPtr->hDefaultFont)
998 DeleteObject (infoPtr->hDefaultFont);
1000 /* delete tool tip control */
1001 if (infoPtr->hwndToolTip)
1002 DestroyWindow (infoPtr->hwndToolTip);
1004 COMCTL32_Free (infoPtr);
1005 SetWindowLongA(hwnd, 0, 0);
1010 static inline LRESULT
1011 STATUSBAR_WMGetFont (STATUSWINDOWINFO *infoPtr, HWND hwnd)
1014 return infoPtr->hFont? infoPtr->hFont : infoPtr->hDefaultFont;
1018 /* in contrast to SB_GETTEXT*, WM_GETTEXT handles the text
1019 * of the first part only (usual behaviour) */
1021 STATUSBAR_WMGetText (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1026 if (!(infoPtr->parts[0].text))
1028 if (infoPtr->bUnicode)
1029 len = strlenW (infoPtr->parts[0].text);
1031 len = WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1, NULL, 0, NULL, NULL )-1;
1034 if (infoPtr->bUnicode)
1035 strcpyW ((LPWSTR)lParam, infoPtr->parts[0].text);
1037 WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1,
1038 (LPSTR)lParam, len+1, NULL, NULL );
1046 inline static LRESULT
1047 STATUSBAR_WMMouseMove (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1049 if (infoPtr->hwndToolTip)
1050 STATUSBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
1051 WM_MOUSEMOVE, wParam, lParam);
1057 STATUSBAR_WMNCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1059 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
1063 GetClientRect (hwnd, &rect);
1065 pt.x = (INT)LOWORD(lParam);
1066 pt.y = (INT)HIWORD(lParam);
1067 ScreenToClient (hwnd, &pt);
1069 rect.left = rect.right - 13;
1072 if (PtInRect (&rect, pt))
1073 return HTBOTTOMRIGHT;
1076 /* FIXME: instead check result in StatusWindowProc and call if needed ? */
1077 return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
1081 static inline LRESULT
1082 STATUSBAR_WMNCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1085 PostMessageA (GetParent (hwnd), WM_NCLBUTTONDOWN, wParam, lParam);
1090 static inline LRESULT
1091 STATUSBAR_WMNCLButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1094 PostMessageA (GetParent (hwnd), WM_NCLBUTTONUP, wParam, lParam);
1100 STATUSBAR_WMPaint (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
1106 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1107 STATUSBAR_Refresh (infoPtr, hwnd, hdc);
1109 EndPaint (hwnd, &ps);
1116 STATUSBAR_WMSetFont (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1118 infoPtr->hFont = (HFONT)wParam;
1119 TRACE("%04x\n", infoPtr->hFont);
1120 if (LOWORD(lParam) == TRUE)
1121 InvalidateRect(hwnd, NULL, FALSE);
1128 STATUSBAR_WMSetText (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1130 STATUSWINDOWPART *part;
1134 if (infoPtr->numParts == 0)
1137 part = &infoPtr->parts[0];
1138 /* duplicate string */
1140 COMCTL32_Free (part->text);
1142 if (infoPtr->bUnicode) {
1143 if (lParam && (len = strlenW((LPCWSTR)lParam))) {
1144 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1145 strcpyW (part->text, (LPCWSTR)lParam);
1149 if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
1150 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lParam, -1, NULL, 0 );
1151 part->text = COMCTL32_Alloc (lenW*sizeof(WCHAR));
1152 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lParam, -1, part->text, lenW );
1156 InvalidateRect(hwnd, &part->bound, FALSE);
1163 STATUSBAR_WMSize (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1165 INT width, x, y, flags;
1169 /* Need to resize width to match parent */
1170 flags = (INT) wParam;
1172 TRACE("flags %04x\n", flags);
1173 /* FIXME for flags =
1174 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
1177 dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
1178 if (!(dwStyle & CCS_NORESIZE)) /* don't resize wnd if it doesn't want it ! */
1180 if (flags == SIZE_RESTORED) {
1181 /* width and height don't apply */
1182 GetClientRect (infoPtr->hwndParent, &parent_rect);
1183 width = parent_rect.right - parent_rect.left;
1184 x = parent_rect.left;
1185 y = parent_rect.bottom - infoPtr->height;
1186 MoveWindow (hwnd, parent_rect.left,
1187 parent_rect.bottom - infoPtr->height,
1188 width, infoPtr->height, TRUE);
1189 STATUSBAR_SetPartBounds (infoPtr, hwnd);
1191 return 0; /* FIXME: ok to return here ? */
1194 /* FIXME: instead check result in StatusWindowProc and call if needed ? */
1195 return DefWindowProcA (hwnd, WM_SIZE, wParam, lParam);
1200 STATUSBAR_SendNotify (HWND hwnd, UINT code)
1204 TRACE("code %04x\n", code);
1205 nmhdr.hwndFrom = hwnd;
1206 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1208 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
1214 static LRESULT WINAPI
1215 StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1217 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr(hwnd);
1219 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, msg, wParam, lParam);
1220 if (!(infoPtr) && (msg != WM_CREATE))
1221 return DefWindowProcA (hwnd, msg, wParam, lParam);
1225 return STATUSBAR_GetBorders (lParam);
1228 return STATUSBAR_GetIcon (infoPtr, hwnd, wParam);
1231 return STATUSBAR_GetParts (infoPtr, hwnd, wParam, lParam);
1234 return STATUSBAR_GetRect (infoPtr, hwnd, wParam, lParam);
1237 return STATUSBAR_GetTextA (infoPtr, hwnd, wParam, lParam);
1240 return STATUSBAR_GetTextW (infoPtr, hwnd, wParam, lParam);
1242 case SB_GETTEXTLENGTHA:
1243 case SB_GETTEXTLENGTHW:
1244 return STATUSBAR_GetTextLength (infoPtr, hwnd, wParam);
1246 case SB_GETTIPTEXTA:
1247 return STATUSBAR_GetTipTextA (infoPtr, hwnd, wParam, lParam);
1249 case SB_GETTIPTEXTW:
1250 return STATUSBAR_GetTipTextW (infoPtr, hwnd, wParam, lParam);
1252 case SB_GETUNICODEFORMAT:
1253 return STATUSBAR_GetUnicodeFormat (infoPtr, hwnd);
1256 return STATUSBAR_IsSimple (infoPtr, hwnd);
1259 return STATUSBAR_SetBkColor (infoPtr, hwnd, wParam, lParam);
1262 return STATUSBAR_SetIcon (infoPtr, hwnd, wParam, lParam);
1264 case SB_SETMINHEIGHT:
1265 return STATUSBAR_SetMinHeight (infoPtr, hwnd, wParam, lParam);
1268 return STATUSBAR_SetParts (infoPtr, hwnd, wParam, lParam);
1271 return STATUSBAR_SetTextA (infoPtr, hwnd, wParam, lParam);
1274 return STATUSBAR_SetTextW (infoPtr, hwnd, wParam, lParam);
1276 case SB_SETTIPTEXTA:
1277 return STATUSBAR_SetTipTextA (infoPtr, hwnd, wParam, lParam);
1279 case SB_SETTIPTEXTW:
1280 return STATUSBAR_SetTipTextW (infoPtr, hwnd, wParam, lParam);
1282 case SB_SETUNICODEFORMAT:
1283 return STATUSBAR_SetUnicodeFormat (infoPtr, hwnd, wParam);
1286 return STATUSBAR_Simple (infoPtr, hwnd, wParam, lParam);
1290 return STATUSBAR_WMCreate (hwnd, wParam, lParam);
1293 return STATUSBAR_WMDestroy (infoPtr, hwnd);
1296 return STATUSBAR_WMGetFont (infoPtr, hwnd);
1299 return STATUSBAR_WMGetText (infoPtr, hwnd, wParam, lParam);
1301 case WM_GETTEXTLENGTH:
1302 return STATUSBAR_GetTextLength (infoPtr, hwnd, 0);
1304 case WM_LBUTTONDBLCLK:
1305 return STATUSBAR_SendNotify (hwnd, NM_DBLCLK);
1308 return STATUSBAR_SendNotify (hwnd, NM_CLICK);
1311 return STATUSBAR_WMMouseMove (infoPtr, hwnd, wParam, lParam);
1314 return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
1316 case WM_NCLBUTTONDOWN:
1317 return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
1319 case WM_NCLBUTTONUP:
1320 return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
1323 return STATUSBAR_WMPaint (infoPtr, hwnd, wParam);
1325 case WM_RBUTTONDBLCLK:
1326 return STATUSBAR_SendNotify (hwnd, NM_RDBLCLK);
1329 return STATUSBAR_SendNotify (hwnd, NM_RCLICK);
1332 return STATUSBAR_WMSetFont (infoPtr, hwnd, wParam, lParam);
1335 return STATUSBAR_WMSetText (infoPtr, hwnd, wParam, lParam);
1338 return STATUSBAR_WMSize (infoPtr, hwnd, wParam, lParam);
1342 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1343 msg, wParam, lParam);
1344 return DefWindowProcA (hwnd, msg, wParam, lParam);
1350 /***********************************************************************
1351 * STATUS_Register [Internal]
1353 * Registers the status window class.
1357 STATUS_Register (void)
1361 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1362 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1363 wndClass.lpfnWndProc = (WNDPROC)StatusWindowProc;
1364 wndClass.cbClsExtra = 0;
1365 wndClass.cbWndExtra = sizeof(STATUSWINDOWINFO *);
1366 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1367 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1368 wndClass.lpszClassName = STATUSCLASSNAMEA;
1370 RegisterClassA (&wndClass);
1374 /***********************************************************************
1375 * STATUS_Unregister [Internal]
1377 * Unregisters the status window class.
1381 STATUS_Unregister (void)
1383 UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);