2 * Interface code to StatusWindow widget/control
4 * Copyright 1996 Bruce Milner
5 * Copyright 1998, 1999 Eric Kohl
9 * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
10 * 2) Tooltip support (almost done).
11 * 3) where else should we use infoPtr->hwndParent instead of GetParent() ?
12 * 4) send WM_QUERYFORMAT
17 #include "wine/unicode.h"
19 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(statusbar
);
42 COLORREF clrBk
; /* background color */
43 BOOL bUnicode
; /* unicode flag */
44 STATUSWINDOWPART part0
; /* simple window */
45 STATUSWINDOWPART
*parts
;
49 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
50 * The second cdrom contains executables drawstat.exe, gettext.exe,
51 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
55 #define _MAX(a,b) (((a)>(b))?(a):(b))
56 #define _MIN(a,b) (((a)>(b))?(b):(a))
62 #define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
66 STATUSBAR_SetPartBounds (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
);
69 STATUSBAR_DrawSizeGrip (HDC hdc
, LPRECT lpRect
)
75 TRACE("draw size grip %d,%d - %d,%d\n", lpRect
->left
, lpRect
->top
, lpRect
->right
, lpRect
->bottom
);
76 pt
.x
= lpRect
->right
- 1;
77 pt
.y
= lpRect
->bottom
- 1;
79 hOldPen
= SelectObject (hdc
, GetSysColorPen (COLOR_3DFACE
));
80 MoveToEx (hdc
, pt
.x
- 12, pt
.y
, NULL
);
81 LineTo (hdc
, pt
.x
, pt
.y
);
82 LineTo (hdc
, pt
.x
, pt
.y
- 12);
87 SelectObject (hdc
, GetSysColorPen (COLOR_3DSHADOW
));
88 for (i
= 1; i
< 11; i
+= 4) {
89 MoveToEx (hdc
, pt
.x
- i
, pt
.y
, NULL
);
90 LineTo (hdc
, pt
.x
, pt
.y
- i
);
92 MoveToEx (hdc
, pt
.x
- i
-1, pt
.y
, NULL
);
93 LineTo (hdc
, pt
.x
, pt
.y
- i
-1);
96 SelectObject (hdc
, GetSysColorPen (COLOR_3DHIGHLIGHT
));
97 for (i
= 3; i
< 13; i
+= 4) {
98 MoveToEx (hdc
, pt
.x
- i
, pt
.y
, NULL
);
99 LineTo (hdc
, pt
.x
, pt
.y
- i
);
102 SelectObject (hdc
, hOldPen
);
107 STATUSBAR_DrawPart (HDC hdc
, STATUSWINDOWPART
*part
)
109 RECT r
= part
->bound
;
110 UINT border
= BDR_SUNKENOUTER
;
112 TRACE("part bound %d,%d - %d,%d\n", r
.left
, r
.top
, r
.right
, r
.bottom
);
113 if (part
->style
& SBT_POPOUT
)
114 border
= BDR_RAISEDOUTER
;
115 else if (part
->style
& SBT_NOBORDERS
)
118 DrawEdge(hdc
, &r
, border
, BF_RECT
|BF_ADJUST
);
122 INT cy
= r
.bottom
- r
.top
;
125 DrawIconEx (hdc
, r
.left
, r
.top
, part
->hIcon
, cy
, cy
, 0, 0, DI_NORMAL
);
131 int oldbkmode
= SetBkMode(hdc
, TRANSPARENT
);
132 LPWSTR p
= (LPWSTR
)part
->text
;
133 UINT align
= DT_LEFT
;
144 TRACE("%s at %d,%d - %d,%d\n", debugstr_w(p
), r
.left
, r
.top
, r
.right
, r
.bottom
);
145 DrawTextW (hdc
, p
, -1, &r
, align
|DT_VCENTER
|DT_SINGLELINE
);
146 if (oldbkmode
!= TRANSPARENT
)
147 SetBkMode(hdc
, oldbkmode
);
153 STATUSBAR_RefreshPart (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, STATUSWINDOWPART
*part
, HDC hdc
, int itemID
)
158 TRACE("item %d\n", itemID
);
159 if (!IsWindowVisible (hwnd
))
162 if (part
->bound
.right
< part
->bound
.left
) return;
164 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
165 hbrBk
= CreateSolidBrush (infoPtr
->clrBk
);
167 hbrBk
= GetSysColorBrush (COLOR_3DFACE
);
168 FillRect(hdc
, &part
->bound
, hbrBk
);
170 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
);
172 if (part
->style
& SBT_OWNERDRAW
) {
175 dis
.CtlID
= GetWindowLongA (hwnd
, GWL_ID
);
179 dis
.rcItem
= part
->bound
;
180 dis
.itemData
= (INT
)part
->text
;
181 SendMessageA (GetParent (hwnd
), WM_DRAWITEM
,
182 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
184 STATUSBAR_DrawPart (hdc
, part
);
186 SelectObject (hdc
, hOldFont
);
188 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
189 DeleteObject (hbrBk
);
191 if (GetWindowLongA (hwnd
, GWL_STYLE
) & SBARS_SIZEGRIP
) {
194 GetClientRect (hwnd
, &rect
);
195 STATUSBAR_DrawSizeGrip (hdc
, &rect
);
201 STATUSBAR_Refresh (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, HDC hdc
)
209 if (!IsWindowVisible(hwnd
))
212 STATUSBAR_SetPartBounds(infoPtr
, hwnd
);
214 GetClientRect (hwnd
, &rect
);
216 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
217 hbrBk
= CreateSolidBrush (infoPtr
->clrBk
);
219 hbrBk
= GetSysColorBrush (COLOR_3DFACE
);
220 FillRect(hdc
, &rect
, hbrBk
);
222 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
);
224 if (infoPtr
->simple
) {
225 STATUSBAR_RefreshPart (infoPtr
, hwnd
, &infoPtr
->part0
, hdc
, 0);
227 for (i
= 0; i
< infoPtr
->numParts
; i
++) {
228 if (infoPtr
->parts
[i
].style
& SBT_OWNERDRAW
) {
231 dis
.CtlID
= GetWindowLongA (hwnd
, GWL_ID
);
235 dis
.rcItem
= infoPtr
->parts
[i
].bound
;
236 dis
.itemData
= (INT
)infoPtr
->parts
[i
].text
;
237 SendMessageA (GetParent (hwnd
), WM_DRAWITEM
,
238 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
240 STATUSBAR_RefreshPart (infoPtr
, hwnd
, &infoPtr
->parts
[i
], hdc
, i
);
244 SelectObject (hdc
, hOldFont
);
246 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
247 DeleteObject (hbrBk
);
249 if (GetWindowLongA(hwnd
, GWL_STYLE
) & SBARS_SIZEGRIP
)
250 STATUSBAR_DrawSizeGrip (hdc
, &rect
);
257 STATUSBAR_SetPartBounds (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
)
259 STATUSWINDOWPART
*part
;
263 /* get our window size */
264 GetClientRect (hwnd
, &rect
);
265 TRACE("client wnd size is %d,%d - %d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
267 rect
.top
+= VERT_BORDER
;
269 /* set bounds for simple rectangle */
270 infoPtr
->part0
.bound
= rect
;
272 /* set bounds for non-simple rectangles */
273 for (i
= 0; i
< infoPtr
->numParts
; i
++) {
274 part
= &infoPtr
->parts
[i
];
275 r
= &infoPtr
->parts
[i
].bound
;
277 r
->bottom
= rect
.bottom
;
281 r
->left
= infoPtr
->parts
[i
-1].bound
.right
+ HORZ_GAP
;
283 r
->right
= rect
.right
;
287 if (infoPtr
->hwndToolTip
) {
290 ti
.cbSize
= sizeof(TTTOOLINFOA
);
294 SendMessageA (infoPtr
->hwndToolTip
, TTM_NEWTOOLRECTA
,
302 STATUSBAR_RelayEvent (HWND hwndTip
, HWND hwndMsg
, UINT uMsg
,
303 WPARAM wParam
, LPARAM lParam
)
311 msg
.time
= GetMessageTime ();
312 msg
.pt
.x
= LOWORD(GetMessagePos ());
313 msg
.pt
.y
= HIWORD(GetMessagePos ());
315 SendMessageA (hwndTip
, TTM_RELAYEVENT
, 0, (LPARAM
)&msg
);
319 inline static LRESULT
320 STATUSBAR_GetBorders (LPARAM lParam
)
322 LPINT out
= (LPINT
) lParam
;
325 out
[0] = HORZ_BORDER
; /* horizontal border width */
326 out
[1] = VERT_BORDER
; /* vertical border width */
327 out
[2] = HORZ_GAP
; /* width of border between rectangles */
334 STATUSBAR_GetIcon (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
)
338 nPart
= (INT
)wParam
& 0x00ff;
339 TRACE("%d\n", nPart
);
340 if ((nPart
< -1) || (nPart
>= infoPtr
->numParts
))
344 return (infoPtr
->part0
.hIcon
);
346 return (infoPtr
->parts
[nPart
].hIcon
);
351 STATUSBAR_GetParts (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
357 num_parts
= (INT
) wParam
;
358 TRACE("(%d)\n", num_parts
);
359 parts
= (LPINT
) lParam
;
361 for (i
= 0; i
< num_parts
; i
++) {
362 parts
[i
] = infoPtr
->parts
[i
].x
;
365 return (infoPtr
->numParts
);
370 STATUSBAR_GetRect (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
375 nPart
= ((INT
) wParam
) & 0x00ff;
376 TRACE("part %d\n", nPart
);
377 rect
= (LPRECT
) lParam
;
379 *rect
= infoPtr
->part0
.bound
;
381 *rect
= infoPtr
->parts
[nPart
].bound
;
387 STATUSBAR_GetTextA (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
389 STATUSWINDOWPART
*part
;
393 nPart
= ((INT
) wParam
) & 0x00ff;
394 TRACE("part %d\n", nPart
);
396 part
= &infoPtr
->part0
;
398 part
= &infoPtr
->parts
[nPart
];
400 if (part
->style
& SBT_OWNERDRAW
)
401 result
= (LRESULT
)part
->text
;
403 DWORD len
= part
->text
? WideCharToMultiByte( CP_ACP
, 0, part
->text
, -1,
404 NULL
, 0, NULL
, NULL
) - 1 : 0;
405 result
= MAKELONG( len
, part
->style
);
407 WideCharToMultiByte( CP_ACP
, 0, part
->text
, -1, (LPSTR
)lParam
, len
+1, NULL
, NULL
);
414 STATUSBAR_GetTextW (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
416 STATUSWINDOWPART
*part
;
420 nPart
= ((INT
)wParam
) & 0x00ff;
421 TRACE("part %d\n", nPart
);
423 part
= &infoPtr
->part0
;
425 part
= &infoPtr
->parts
[nPart
];
427 if (part
->style
& SBT_OWNERDRAW
)
428 result
= (LRESULT
)part
->text
;
430 result
= part
->text
? strlenW (part
->text
) : 0;
431 result
|= (part
->style
<< 16);
432 if (part
->text
&& lParam
)
433 strcpyW ((LPWSTR
)lParam
, part
->text
);
440 STATUSBAR_GetTextLength (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
)
442 STATUSWINDOWPART
*part
;
446 nPart
= ((INT
) wParam
) & 0x00ff;
448 TRACE("part %d\n", nPart
);
450 part
= &infoPtr
->part0
;
452 part
= &infoPtr
->parts
[nPart
];
455 result
= strlenW(part
->text
);
459 result
|= (part
->style
<< 16);
465 STATUSBAR_GetTipTextA (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
467 LPSTR tip
= (LPSTR
)lParam
;
470 CHAR buf
[INFOTIPSIZE
];
473 if (infoPtr
->hwndToolTip
) {
475 ti
.cbSize
= sizeof(TTTOOLINFOA
);
477 ti
.uId
= LOWORD(wParam
);
479 SendMessageA(infoPtr
->hwndToolTip
, TTM_GETTEXTA
, 0, (LPARAM
)&ti
);
481 lstrcpynA(tip
, buf
, HIWORD(wParam
));
488 STATUSBAR_GetTipTextW (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
490 LPWSTR tip
= (LPWSTR
)lParam
;
494 WCHAR buf
[INFOTIPSIZE
];
497 if (infoPtr
->hwndToolTip
) {
499 ti
.cbSize
= sizeof(TTTOOLINFOW
);
501 ti
.uId
= LOWORD(wParam
);
503 SendMessageW(infoPtr
->hwndToolTip
, TTM_GETTEXTW
, 0, (LPARAM
)&ti
);
505 lstrcpynW(tip
, buf
, HIWORD(wParam
));
512 inline static LRESULT
513 STATUSBAR_GetUnicodeFormat (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
)
515 return infoPtr
->bUnicode
;
519 inline static LRESULT
520 STATUSBAR_IsSimple (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
)
522 return infoPtr
->simple
;
527 STATUSBAR_SetBkColor (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
531 oldBkColor
= infoPtr
->clrBk
;
532 infoPtr
->clrBk
= (COLORREF
)lParam
;
533 InvalidateRect(hwnd
, NULL
, FALSE
);
535 TRACE("CREF: %08lx -> %08lx\n", oldBkColor
, infoPtr
->clrBk
);
541 STATUSBAR_SetIcon (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
543 INT nPart
= (INT
)wParam
& 0x00ff;
545 if ((nPart
< -1) || (nPart
>= infoPtr
->numParts
))
548 TRACE("setting part %d, icon %lx\n",nPart
,lParam
);
551 if (infoPtr
->part0
.hIcon
== (HICON
)lParam
) /* same as - no redraw */
553 infoPtr
->part0
.hIcon
= (HICON
)lParam
;
555 InvalidateRect(hwnd
, &infoPtr
->part0
.bound
, FALSE
);
557 if (infoPtr
->parts
[nPart
].hIcon
== (HICON
)lParam
) /* same as - no redraw */
560 infoPtr
->parts
[nPart
].hIcon
= (HICON
)lParam
;
561 if (!(infoPtr
->simple
))
562 InvalidateRect(hwnd
, &infoPtr
->parts
[nPart
].bound
, FALSE
);
569 STATUSBAR_SetMinHeight (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
573 if (IsWindowVisible (hwnd
)) {
574 HWND parent
= GetParent (hwnd
);
578 GetClientRect (parent
, &parent_rect
);
579 infoPtr
->height
= (INT
)wParam
+ VERT_BORDER
;
580 width
= parent_rect
.right
- parent_rect
.left
;
581 x
= parent_rect
.left
;
582 y
= parent_rect
.bottom
- infoPtr
->height
;
583 MoveWindow (hwnd
, parent_rect
.left
,
584 parent_rect
.bottom
- infoPtr
->height
,
585 width
, infoPtr
->height
, TRUE
);
586 STATUSBAR_SetPartBounds (infoPtr
, hwnd
);
594 STATUSBAR_SetParts (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
596 STATUSWINDOWPART
*tmp
;
601 TRACE("(%d,%p)\n",wParam
,(LPVOID
)lParam
);
603 /* FIXME: should return FALSE sometimes (maybe when wParam == 0 ?) */
605 infoPtr
->simple
= FALSE
;
607 oldNumParts
= infoPtr
->numParts
;
608 infoPtr
->numParts
= (INT
) wParam
;
609 parts
= (LPINT
) lParam
;
610 if (oldNumParts
> infoPtr
->numParts
) {
611 for (i
= infoPtr
->numParts
; i
< oldNumParts
; i
++) {
612 if (infoPtr
->parts
[i
].text
&& !(infoPtr
->parts
[i
].style
& SBT_OWNERDRAW
))
613 COMCTL32_Free (infoPtr
->parts
[i
].text
);
616 if (oldNumParts
< infoPtr
->numParts
) {
617 tmp
= COMCTL32_Alloc (sizeof(STATUSWINDOWPART
) * infoPtr
->numParts
);
618 for (i
= 0; i
< oldNumParts
; i
++) {
619 tmp
[i
] = infoPtr
->parts
[i
];
622 COMCTL32_Free (infoPtr
->parts
);
623 infoPtr
->parts
= tmp
;
625 if (oldNumParts
== infoPtr
->numParts
) {
626 for (i
=0;i
<oldNumParts
;i
++)
627 if (infoPtr
->parts
[i
].x
!= parts
[i
])
629 if (i
==oldNumParts
) /* Unchanged? no need to redraw! */
633 for (i
= 0; i
< infoPtr
->numParts
; i
++)
634 infoPtr
->parts
[i
].x
= parts
[i
];
636 if (infoPtr
->hwndToolTip
) {
638 SendMessageA (infoPtr
->hwndToolTip
, TTM_GETTOOLCOUNT
, 0, 0);
640 if (nTipCount
< infoPtr
->numParts
) {
645 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
646 ti
.cbSize
= sizeof(TTTOOLINFOA
);
648 for (i
= nTipCount
; i
< infoPtr
->numParts
; i
++) {
649 TRACE("add tool %d\n", i
);
651 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
,
655 else if (nTipCount
> infoPtr
->numParts
) {
659 for (i
= nTipCount
- 1; i
>= infoPtr
->numParts
; i
--) {
660 FIXME("delete tool %d\n", i
);
664 STATUSBAR_SetPartBounds (infoPtr
, hwnd
);
665 InvalidateRect(hwnd
, NULL
, FALSE
);
671 STATUSBAR_SetTextA (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
673 STATUSWINDOWPART
*part
=NULL
;
677 BOOL changed
= FALSE
;
679 text
= (LPSTR
) lParam
;
680 nPart
= ((INT
) wParam
) & 0x00ff;
681 style
= ((INT
) wParam
) & 0xff00;
683 TRACE("part %d, text %s\n",nPart
,debugstr_a(text
));
686 part
= &infoPtr
->part0
;
687 else if (!infoPtr
->simple
&& infoPtr
->parts
!=NULL
)
688 part
= &infoPtr
->parts
[nPart
];
689 if (!part
) return FALSE
;
691 if (part
->style
!= style
)
695 if (style
& SBT_OWNERDRAW
) {
696 if (part
->text
== (LPWSTR
)text
)
698 part
->text
= (LPWSTR
)text
;
702 /* check if text is unchanged -> no need to redraw */
704 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, text
, -1, NULL
, 0 );
705 LPWSTR tmptext
= COMCTL32_Alloc(len
*sizeof(WCHAR
));
706 MultiByteToWideChar( CP_ACP
, 0, text
, -1, tmptext
, len
);
708 if (!changed
&& part
->text
&& !lstrcmpW(tmptext
,part
->text
)) {
709 COMCTL32_Free(tmptext
);
714 if (!changed
&& !part
->text
)
720 COMCTL32_Free (part
->text
);
723 InvalidateRect(hwnd
, &part
->bound
, FALSE
);
730 STATUSBAR_SetTextW (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
732 STATUSWINDOWPART
*part
;
733 INT nPart
, style
, len
;
735 BOOL bRedraw
= FALSE
;
737 text
= (LPWSTR
) lParam
;
738 nPart
= ((INT
) wParam
) & 0x00ff;
739 style
= ((INT
) wParam
) & 0xff00;
741 TRACE("part %d -> '%s' with style %04x\n", nPart
, debugstr_w(text
), style
);
742 if ((infoPtr
->simple
) || (infoPtr
->parts
==NULL
) || (nPart
==255))
743 part
= &infoPtr
->part0
;
745 part
= &infoPtr
->parts
[nPart
];
746 if (!part
) return FALSE
;
748 if(part
->style
!= style
)
753 /* FIXME: not sure how/if we can check for change in string with ownerdraw(remove this if we can't)... */
754 if (style
& SBT_OWNERDRAW
)
762 COMCTL32_Free(part
->text
);
766 } else if(!part
->text
|| strcmpW(part
->text
, text
)) /* see if the new string differs from the existing string */
768 if(part
->text
) COMCTL32_Free(part
->text
);
771 part
->text
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
772 strcpyW(part
->text
, text
);
777 InvalidateRect(hwnd
, &part
->bound
, FALSE
);
784 STATUSBAR_SetTipTextA (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
786 TRACE("part %d: \"%s\"\n", (INT
)wParam
, (LPSTR
)lParam
);
787 if (infoPtr
->hwndToolTip
) {
789 ti
.cbSize
= sizeof(TTTOOLINFOA
);
791 ti
.uId
= (INT
)wParam
;
793 ti
.lpszText
= (LPSTR
)lParam
;
794 SendMessageA (infoPtr
->hwndToolTip
, TTM_UPDATETIPTEXTA
,
803 STATUSBAR_SetTipTextW (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
805 TRACE("part %d: \"%s\"\n", (INT
)wParam
, (LPSTR
)lParam
);
806 if (infoPtr
->hwndToolTip
) {
808 ti
.cbSize
= sizeof(TTTOOLINFOW
);
810 ti
.uId
= (INT
)wParam
;
812 ti
.lpszText
= (LPWSTR
)lParam
;
813 SendMessageW (infoPtr
->hwndToolTip
, TTM_UPDATETIPTEXTW
,
821 inline static LRESULT
822 STATUSBAR_SetUnicodeFormat (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
)
824 BOOL bOld
= infoPtr
->bUnicode
;
826 TRACE("(0x%x)\n", (BOOL
)wParam
);
827 infoPtr
->bUnicode
= (BOOL
)wParam
;
834 STATUSBAR_Simple (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
838 TRACE("(is simple: %d)\n", wParam
);
839 if (infoPtr
->simple
== wParam
) /* no need to change */
842 infoPtr
->simple
= (BOOL
)wParam
;
844 /* send notification */
845 nmhdr
.hwndFrom
= hwnd
;
846 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
847 nmhdr
.code
= SBN_SIMPLEMODECHANGE
;
848 SendMessageA (GetParent (hwnd
), WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
849 InvalidateRect(hwnd
, NULL
, FALSE
);
855 STATUSBAR_WMCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
857 LPCREATESTRUCTA lpCreate
= (LPCREATESTRUCTA
)lParam
;
858 NONCLIENTMETRICSA nclm
;
863 STATUSWINDOWINFO
*infoPtr
;
866 infoPtr
= (STATUSWINDOWINFO
*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO
));
867 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
869 infoPtr
->hwndParent
= lpCreate
->hwndParent
;
870 infoPtr
->numParts
= 1;
872 infoPtr
->simple
= FALSE
;
873 infoPtr
->clrBk
= CLR_DEFAULT
;
876 /* TODO: send unicode parent notification query (WM_QUERYFORMAT) here */
878 GetClientRect (hwnd
, &rect
);
879 InvalidateRect (hwnd
, &rect
, 0);
882 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
883 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, nclm
.cbSize
, &nclm
, 0);
884 infoPtr
->hDefaultFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
886 /* initialize simple case */
887 infoPtr
->part0
.bound
= rect
;
888 infoPtr
->part0
.text
= 0;
889 infoPtr
->part0
.x
= 0;
890 infoPtr
->part0
.style
= 0;
891 infoPtr
->part0
.hIcon
= 0;
893 /* initialize first part */
894 infoPtr
->parts
= COMCTL32_Alloc (sizeof(STATUSWINDOWPART
));
895 infoPtr
->parts
[0].bound
= rect
;
896 infoPtr
->parts
[0].text
= 0;
897 infoPtr
->parts
[0].x
= -1;
898 infoPtr
->parts
[0].style
= 0;
899 infoPtr
->parts
[0].hIcon
= 0;
901 if (IsWindowUnicode (hwnd
)) {
902 infoPtr
->bUnicode
= TRUE
;
903 if (lpCreate
->lpszName
&&
904 (len
= strlenW ((LPCWSTR
)lpCreate
->lpszName
))) {
905 infoPtr
->parts
[0].text
= COMCTL32_Alloc ((len
+ 1)*sizeof(WCHAR
));
906 strcpyW (infoPtr
->parts
[0].text
, (LPCWSTR
)lpCreate
->lpszName
);
910 if (lpCreate
->lpszName
&&
911 (len
= strlen((LPCSTR
)lpCreate
->lpszName
))) {
912 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)lpCreate
->lpszName
, -1, NULL
, 0 );
913 infoPtr
->parts
[0].text
= COMCTL32_Alloc (lenW
*sizeof(WCHAR
));
914 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)lpCreate
->lpszName
, -1,
915 infoPtr
->parts
[0].text
, lenW
);
919 dwStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
921 /* statusbars on managed windows should not have SIZEGRIP style */
922 if ((dwStyle
& SBARS_SIZEGRIP
) && lpCreate
->hwndParent
)
923 if (GetWindowLongA(lpCreate
->hwndParent
, GWL_EXSTYLE
) & WS_EX_MANAGED
)
924 SetWindowLongA (hwnd
, GWL_STYLE
, dwStyle
& ~SBARS_SIZEGRIP
);
926 if ((hdc
= GetDC (0))) {
930 hOldFont
= SelectObject (hdc
,infoPtr
->hDefaultFont
);
931 GetTextMetricsA(hdc
, &tm
);
932 infoPtr
->textHeight
= tm
.tmHeight
;
933 SelectObject (hdc
, hOldFont
);
937 if (dwStyle
& SBT_TOOLTIPS
) {
938 infoPtr
->hwndToolTip
=
939 CreateWindowExA (0, TOOLTIPS_CLASSA
, NULL
, 0,
940 CW_USEDEFAULT
, CW_USEDEFAULT
,
941 CW_USEDEFAULT
, CW_USEDEFAULT
,
943 GetWindowLongA (hwnd
, GWL_HINSTANCE
), NULL
);
945 if (infoPtr
->hwndToolTip
) {
946 NMTOOLTIPSCREATED nmttc
;
948 nmttc
.hdr
.hwndFrom
= hwnd
;
949 nmttc
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
950 nmttc
.hdr
.code
= NM_TOOLTIPSCREATED
;
951 nmttc
.hwndToolTips
= infoPtr
->hwndToolTip
;
953 SendMessageA (lpCreate
->hwndParent
, WM_NOTIFY
,
954 (WPARAM
)nmttc
.hdr
.idFrom
, (LPARAM
)&nmttc
);
958 if (!dwStyle
& CCS_NORESIZE
) /* don't resize wnd if it doesn't want it ! */
960 GetClientRect (GetParent (hwnd
), &rect
);
961 width
= rect
.right
- rect
.left
;
962 infoPtr
->height
= infoPtr
->textHeight
+ 4 + VERT_BORDER
;
963 SetWindowPos(hwnd
, 0, lpCreate
->x
, lpCreate
->y
- 1,
964 width
, infoPtr
->height
, SWP_NOZORDER
);
965 STATUSBAR_SetPartBounds (infoPtr
, hwnd
);
973 STATUSBAR_WMDestroy (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
)
978 for (i
= 0; i
< infoPtr
->numParts
; i
++) {
979 if (infoPtr
->parts
[i
].text
&& !(infoPtr
->parts
[i
].style
& SBT_OWNERDRAW
))
980 COMCTL32_Free (infoPtr
->parts
[i
].text
);
982 if (infoPtr
->part0
.text
&& !(infoPtr
->part0
.style
& SBT_OWNERDRAW
))
983 COMCTL32_Free (infoPtr
->part0
.text
);
984 COMCTL32_Free (infoPtr
->parts
);
986 /* delete default font */
987 if (infoPtr
->hDefaultFont
)
988 DeleteObject (infoPtr
->hDefaultFont
);
990 /* delete tool tip control */
991 if (infoPtr
->hwndToolTip
)
992 DestroyWindow (infoPtr
->hwndToolTip
);
994 COMCTL32_Free (infoPtr
);
995 SetWindowLongA(hwnd
, 0, 0);
1000 static inline LRESULT
1001 STATUSBAR_WMGetFont (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
)
1004 return infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
;
1008 /* in contrast to SB_GETTEXT*, WM_GETTEXT handles the text
1009 * of the first part only (usual behaviour) */
1011 STATUSBAR_WMGetText (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1016 if (!(infoPtr
->parts
[0].text
))
1018 if (infoPtr
->bUnicode
)
1019 len
= strlenW (infoPtr
->parts
[0].text
);
1021 len
= WideCharToMultiByte( CP_ACP
, 0, infoPtr
->parts
[0].text
, -1, NULL
, 0, NULL
, NULL
)-1;
1024 if (infoPtr
->bUnicode
)
1025 strcpyW ((LPWSTR
)lParam
, infoPtr
->parts
[0].text
);
1027 WideCharToMultiByte( CP_ACP
, 0, infoPtr
->parts
[0].text
, -1,
1028 (LPSTR
)lParam
, len
+1, NULL
, NULL
);
1036 inline static LRESULT
1037 STATUSBAR_WMMouseMove (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1039 if (infoPtr
->hwndToolTip
)
1040 STATUSBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
1041 WM_MOUSEMOVE
, wParam
, lParam
);
1047 STATUSBAR_WMNCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1049 if (GetWindowLongA (hwnd
, GWL_STYLE
) & SBARS_SIZEGRIP
) {
1053 GetClientRect (hwnd
, &rect
);
1055 pt
.x
= (INT
)LOWORD(lParam
);
1056 pt
.y
= (INT
)HIWORD(lParam
);
1057 ScreenToClient (hwnd
, &pt
);
1059 rect
.left
= rect
.right
- 13;
1062 if (PtInRect (&rect
, pt
))
1063 return HTBOTTOMRIGHT
;
1066 /* FIXME: instead check result in StatusWindowProc and call if needed ? */
1067 return DefWindowProcA (hwnd
, WM_NCHITTEST
, wParam
, lParam
);
1071 static inline LRESULT
1072 STATUSBAR_WMNCLButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1075 PostMessageA (GetParent (hwnd
), WM_NCLBUTTONDOWN
, wParam
, lParam
);
1080 static inline LRESULT
1081 STATUSBAR_WMNCLButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1084 PostMessageA (GetParent (hwnd
), WM_NCLBUTTONUP
, wParam
, lParam
);
1090 STATUSBAR_WMPaint (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
)
1096 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1097 STATUSBAR_Refresh (infoPtr
, hwnd
, hdc
);
1099 EndPaint (hwnd
, &ps
);
1106 STATUSBAR_WMSetFont (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1108 infoPtr
->hFont
= (HFONT
)wParam
;
1109 TRACE("%04x\n", infoPtr
->hFont
);
1110 if (LOWORD(lParam
) == TRUE
)
1111 InvalidateRect(hwnd
, NULL
, FALSE
);
1118 STATUSBAR_WMSetText (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1120 STATUSWINDOWPART
*part
;
1124 if (infoPtr
->numParts
== 0)
1127 part
= &infoPtr
->parts
[0];
1128 /* duplicate string */
1130 COMCTL32_Free (part
->text
);
1132 if (infoPtr
->bUnicode
) {
1133 if (lParam
&& (len
= strlenW((LPCWSTR
)lParam
))) {
1134 part
->text
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1135 strcpyW (part
->text
, (LPCWSTR
)lParam
);
1139 if (lParam
&& (len
= lstrlenA((LPCSTR
)lParam
))) {
1140 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)lParam
, -1, NULL
, 0 );
1141 part
->text
= COMCTL32_Alloc (lenW
*sizeof(WCHAR
));
1142 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)lParam
, -1, part
->text
, lenW
);
1146 InvalidateRect(hwnd
, &part
->bound
, FALSE
);
1153 STATUSBAR_WMSize (STATUSWINDOWINFO
*infoPtr
, HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1155 INT width
, x
, y
, flags
;
1159 /* Need to resize width to match parent */
1160 flags
= (INT
) wParam
;
1162 TRACE("flags %04x\n", flags
);
1163 /* FIXME for flags =
1164 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
1167 dwStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
1168 if (!dwStyle
& CCS_NORESIZE
) /* don't resize wnd if it doesn't want it ! */
1170 if (flags
== SIZE_RESTORED
) {
1171 /* width and height don't apply */
1172 GetClientRect (infoPtr
->hwndParent
, &parent_rect
);
1173 width
= parent_rect
.right
- parent_rect
.left
;
1174 x
= parent_rect
.left
;
1175 y
= parent_rect
.bottom
- infoPtr
->height
;
1176 MoveWindow (hwnd
, parent_rect
.left
,
1177 parent_rect
.bottom
- infoPtr
->height
,
1178 width
, infoPtr
->height
, TRUE
);
1179 STATUSBAR_SetPartBounds (infoPtr
, hwnd
);
1181 return 0; /* FIXME: ok to return here ? */
1184 /* FIXME: instead check result in StatusWindowProc and call if needed ? */
1185 return DefWindowProcA (hwnd
, WM_SIZE
, wParam
, lParam
);
1190 STATUSBAR_SendNotify (HWND hwnd
, UINT code
)
1194 TRACE("code %04x\n", code
);
1195 nmhdr
.hwndFrom
= hwnd
;
1196 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
1198 SendMessageA (GetParent (hwnd
), WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
1204 static LRESULT WINAPI
1205 StatusWindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1207 STATUSWINDOWINFO
*infoPtr
= STATUSBAR_GetInfoPtr(hwnd
);
1209 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1210 if (!(infoPtr
) && (msg
!= WM_CREATE
))
1211 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1215 return STATUSBAR_GetBorders (lParam
);
1218 return STATUSBAR_GetIcon (infoPtr
, hwnd
, wParam
);
1221 return STATUSBAR_GetParts (infoPtr
, hwnd
, wParam
, lParam
);
1224 return STATUSBAR_GetRect (infoPtr
, hwnd
, wParam
, lParam
);
1227 return STATUSBAR_GetTextA (infoPtr
, hwnd
, wParam
, lParam
);
1230 return STATUSBAR_GetTextW (infoPtr
, hwnd
, wParam
, lParam
);
1232 case SB_GETTEXTLENGTHA
:
1233 case SB_GETTEXTLENGTHW
:
1234 return STATUSBAR_GetTextLength (infoPtr
, hwnd
, wParam
);
1236 case SB_GETTIPTEXTA
:
1237 return STATUSBAR_GetTipTextA (infoPtr
, hwnd
, wParam
, lParam
);
1239 case SB_GETTIPTEXTW
:
1240 return STATUSBAR_GetTipTextW (infoPtr
, hwnd
, wParam
, lParam
);
1242 case SB_GETUNICODEFORMAT
:
1243 return STATUSBAR_GetUnicodeFormat (infoPtr
, hwnd
);
1246 return STATUSBAR_IsSimple (infoPtr
, hwnd
);
1249 return STATUSBAR_SetBkColor (infoPtr
, hwnd
, wParam
, lParam
);
1252 return STATUSBAR_SetIcon (infoPtr
, hwnd
, wParam
, lParam
);
1254 case SB_SETMINHEIGHT
:
1255 return STATUSBAR_SetMinHeight (infoPtr
, hwnd
, wParam
, lParam
);
1258 return STATUSBAR_SetParts (infoPtr
, hwnd
, wParam
, lParam
);
1261 return STATUSBAR_SetTextA (infoPtr
, hwnd
, wParam
, lParam
);
1264 return STATUSBAR_SetTextW (infoPtr
, hwnd
, wParam
, lParam
);
1266 case SB_SETTIPTEXTA
:
1267 return STATUSBAR_SetTipTextA (infoPtr
, hwnd
, wParam
, lParam
);
1269 case SB_SETTIPTEXTW
:
1270 return STATUSBAR_SetTipTextW (infoPtr
, hwnd
, wParam
, lParam
);
1272 case SB_SETUNICODEFORMAT
:
1273 return STATUSBAR_SetUnicodeFormat (infoPtr
, hwnd
, wParam
);
1276 return STATUSBAR_Simple (infoPtr
, hwnd
, wParam
, lParam
);
1280 return STATUSBAR_WMCreate (hwnd
, wParam
, lParam
);
1283 return STATUSBAR_WMDestroy (infoPtr
, hwnd
);
1286 return STATUSBAR_WMGetFont (infoPtr
, hwnd
);
1289 return STATUSBAR_WMGetText (infoPtr
, hwnd
, wParam
, lParam
);
1291 case WM_GETTEXTLENGTH
:
1292 return STATUSBAR_GetTextLength (infoPtr
, hwnd
, 0);
1294 case WM_LBUTTONDBLCLK
:
1295 return STATUSBAR_SendNotify (hwnd
, NM_DBLCLK
);
1298 return STATUSBAR_SendNotify (hwnd
, NM_CLICK
);
1301 return STATUSBAR_WMMouseMove (infoPtr
, hwnd
, wParam
, lParam
);
1304 return STATUSBAR_WMNCHitTest (hwnd
, wParam
, lParam
);
1306 case WM_NCLBUTTONDOWN
:
1307 return STATUSBAR_WMNCLButtonDown (hwnd
, wParam
, lParam
);
1309 case WM_NCLBUTTONUP
:
1310 return STATUSBAR_WMNCLButtonUp (hwnd
, wParam
, lParam
);
1313 return STATUSBAR_WMPaint (infoPtr
, hwnd
, wParam
);
1315 case WM_RBUTTONDBLCLK
:
1316 return STATUSBAR_SendNotify (hwnd
, NM_RDBLCLK
);
1319 return STATUSBAR_SendNotify (hwnd
, NM_RCLICK
);
1322 return STATUSBAR_WMSetFont (infoPtr
, hwnd
, wParam
, lParam
);
1325 return STATUSBAR_WMSetText (infoPtr
, hwnd
, wParam
, lParam
);
1328 return STATUSBAR_WMSize (infoPtr
, hwnd
, wParam
, lParam
);
1332 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1333 msg
, wParam
, lParam
);
1334 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1340 /***********************************************************************
1341 * STATUS_Register [Internal]
1343 * Registers the status window class.
1347 STATUS_Register (void)
1351 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1352 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_VREDRAW
;
1353 wndClass
.lpfnWndProc
= (WNDPROC
)StatusWindowProc
;
1354 wndClass
.cbClsExtra
= 0;
1355 wndClass
.cbWndExtra
= sizeof(STATUSWINDOWINFO
*);
1356 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
1357 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
1358 wndClass
.lpszClassName
= STATUSCLASSNAMEA
;
1360 RegisterClassA (&wndClass
);
1364 /***********************************************************************
1365 * STATUS_Unregister [Internal]
1367 * Unregisters the status window class.
1371 STATUS_Unregister (void)
1373 UnregisterClassA (STATUSCLASSNAMEA
, (HINSTANCE
)NULL
);