2 * Interface code to StatusWindow widget/control
4 * Copyright 1996 Bruce Milner
5 * Copyright 1998, 1999 Eric Kohl
6 * Copyright 2002 Dimitrie O. Paun
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * 1) Implement all CCS_* styles.
24 * 2) Should we hide grip if the parent window is maximized?
30 #include "wine/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(statusbar
);
54 COLORREF clrBk
; /* background color */
55 BOOL bUnicode
; /* unicode flag */
56 BOOL NtfUnicode
; /* notify format */
57 STATUSWINDOWPART part0
; /* simple window */
58 STATUSWINDOWPART
* parts
;
62 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
63 * The second cdrom contains executables drawstat.exe, gettext.exe,
64 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
71 #define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongW (hwnd, 0))
75 STATUSBAR_SetPartBounds (STATUSWINDOWINFO
*infoPtr
);
77 static inline LPCSTR
debugstr_t(LPCWSTR text
, BOOL isW
)
79 return isW
? debugstr_w(text
) : debugstr_a((LPCSTR
)text
);
83 STATUSBAR_DrawSizeGrip (HDC hdc
, LPRECT lpRect
)
85 HPEN hPenFace
, hPenShadow
, hPenHighlight
, hOldPen
;
89 TRACE("draw size grip %d,%d - %d,%d\n", lpRect
->left
, lpRect
->top
, lpRect
->right
, lpRect
->bottom
);
91 pt
.x
= lpRect
->right
- 1;
92 pt
.y
= lpRect
->bottom
- 1;
94 hPenFace
= CreatePen( PS_SOLID
, 1, GetSysColor( COLOR_3DFACE
));
95 hOldPen
= SelectObject( hdc
, hPenFace
);
96 MoveToEx (hdc
, pt
.x
- 12, pt
.y
, NULL
);
97 LineTo (hdc
, pt
.x
, pt
.y
);
98 LineTo (hdc
, pt
.x
, pt
.y
- 13);
103 hPenShadow
= CreatePen( PS_SOLID
, 1, GetSysColor( COLOR_3DSHADOW
));
104 SelectObject( hdc
, hPenShadow
);
105 for (i
= 1; i
< 11; i
+= 4) {
106 MoveToEx (hdc
, pt
.x
- i
, pt
.y
, NULL
);
107 LineTo (hdc
, pt
.x
+ 1, pt
.y
- i
- 1);
109 MoveToEx (hdc
, pt
.x
- i
- 1, pt
.y
, NULL
);
110 LineTo (hdc
, pt
.x
+ 1, pt
.y
- i
- 2);
113 hPenHighlight
= CreatePen( PS_SOLID
, 1, GetSysColor( COLOR_3DHIGHLIGHT
));
114 SelectObject( hdc
, hPenHighlight
);
115 for (i
= 3; i
< 13; i
+= 4) {
116 MoveToEx (hdc
, pt
.x
- i
, pt
.y
, NULL
);
117 LineTo (hdc
, pt
.x
+ 1, pt
.y
- i
- 1);
120 SelectObject (hdc
, hOldPen
);
121 DeleteObject( hPenFace
);
122 DeleteObject( hPenShadow
);
123 DeleteObject( hPenHighlight
);
128 STATUSBAR_DrawPart (HDC hdc
, const STATUSWINDOWPART
*part
, const STATUSWINDOWINFO
*infoPtr
, int itemID
)
130 RECT r
= part
->bound
;
131 UINT border
= BDR_SUNKENOUTER
;
133 TRACE("part bound %d,%d - %d,%d\n", r
.left
, r
.top
, r
.right
, r
.bottom
);
134 if (part
->style
& SBT_POPOUT
)
135 border
= BDR_RAISEDOUTER
;
136 else if (part
->style
& SBT_NOBORDERS
)
139 DrawEdge(hdc
, &r
, border
, BF_RECT
|BF_ADJUST
);
141 if (part
->style
& SBT_OWNERDRAW
)
145 dis
.CtlID
= GetWindowLongW (infoPtr
->Self
, GWL_ID
);
147 dis
.hwndItem
= infoPtr
->Self
;
150 dis
.itemData
= (INT
)part
->text
;
151 SendMessageW (GetParent (infoPtr
->Self
), WM_DRAWITEM
,
152 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
158 INT cy
= r
.bottom
- r
.top
;
161 DrawIconEx (hdc
, r
.left
, r
.top
, part
->hIcon
, cy
, cy
, 0, 0, DI_NORMAL
);
164 DrawStatusTextW (hdc
, &r
, part
->text
, SBT_NOBORDERS
);
170 STATUSBAR_RefreshPart (const STATUSWINDOWINFO
*infoPtr
, const STATUSWINDOWPART
*part
, HDC hdc
, int itemID
)
175 TRACE("item %d\n", itemID
);
176 if (!IsWindowVisible (infoPtr
->Self
))
179 if (part
->bound
.right
< part
->bound
.left
) return;
181 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
182 hbrBk
= CreateSolidBrush (infoPtr
->clrBk
);
184 hbrBk
= GetSysColorBrush (COLOR_3DFACE
);
185 FillRect(hdc
, &part
->bound
, hbrBk
);
187 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
);
189 STATUSBAR_DrawPart (hdc
, part
, infoPtr
, itemID
);
191 SelectObject (hdc
, hOldFont
);
193 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
194 DeleteObject (hbrBk
);
196 if (GetWindowLongW (infoPtr
->Self
, GWL_STYLE
) & SBARS_SIZEGRIP
)
200 GetClientRect (infoPtr
->Self
, &rect
);
201 STATUSBAR_DrawSizeGrip (hdc
, &rect
);
207 STATUSBAR_Refresh (STATUSWINDOWINFO
*infoPtr
, HDC hdc
)
215 if (!IsWindowVisible(infoPtr
->Self
))
218 STATUSBAR_SetPartBounds(infoPtr
);
220 GetClientRect (infoPtr
->Self
, &rect
);
222 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
223 hbrBk
= CreateSolidBrush (infoPtr
->clrBk
);
225 hbrBk
= GetSysColorBrush (COLOR_3DFACE
);
226 FillRect(hdc
, &rect
, hbrBk
);
228 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
);
230 if (infoPtr
->simple
) {
231 STATUSBAR_RefreshPart (infoPtr
, &infoPtr
->part0
, hdc
, 0);
233 for (i
= 0; i
< infoPtr
->numParts
; i
++) {
234 STATUSBAR_RefreshPart (infoPtr
, &infoPtr
->parts
[i
], hdc
, i
);
238 SelectObject (hdc
, hOldFont
);
240 if (infoPtr
->clrBk
!= CLR_DEFAULT
)
241 DeleteObject (hbrBk
);
243 if (GetWindowLongW (infoPtr
->Self
, GWL_STYLE
) & SBARS_SIZEGRIP
)
244 STATUSBAR_DrawSizeGrip (hdc
, &rect
);
251 STATUSBAR_SetPartBounds (STATUSWINDOWINFO
*infoPtr
)
253 STATUSWINDOWPART
*part
;
257 /* get our window size */
258 GetClientRect (infoPtr
->Self
, &rect
);
259 TRACE("client wnd size is %d,%d - %d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
261 rect
.top
+= VERT_BORDER
;
263 /* set bounds for simple rectangle */
264 infoPtr
->part0
.bound
= rect
;
266 /* set bounds for non-simple rectangles */
267 for (i
= 0; i
< infoPtr
->numParts
; i
++) {
268 part
= &infoPtr
->parts
[i
];
269 r
= &infoPtr
->parts
[i
].bound
;
271 r
->bottom
= rect
.bottom
;
275 r
->left
= infoPtr
->parts
[i
-1].bound
.right
+ HORZ_GAP
;
277 r
->right
= rect
.right
;
281 if (infoPtr
->hwndToolTip
) {
284 ti
.cbSize
= sizeof(TTTOOLINFOW
);
285 ti
.hwnd
= infoPtr
->Self
;
288 SendMessageW (infoPtr
->hwndToolTip
, TTM_NEWTOOLRECTW
,
296 STATUSBAR_Relay2Tip (STATUSWINDOWINFO
*infoPtr
, UINT uMsg
,
297 WPARAM wParam
, LPARAM lParam
)
301 msg
.hwnd
= infoPtr
->Self
;
305 msg
.time
= GetMessageTime ();
306 msg
.pt
.x
= LOWORD(GetMessagePos ());
307 msg
.pt
.y
= HIWORD(GetMessagePos ());
309 return SendMessageW (infoPtr
->hwndToolTip
, TTM_RELAYEVENT
, 0, (LPARAM
)&msg
);
314 STATUSBAR_GetBorders (INT out
[])
317 out
[0] = HORZ_BORDER
; /* horizontal border width */
318 out
[1] = VERT_BORDER
; /* vertical border width */
319 out
[2] = HORZ_GAP
; /* width of border between rectangles */
326 STATUSBAR_GetIcon (STATUSWINDOWINFO
*infoPtr
, INT nPart
)
328 TRACE("%d\n", nPart
);
329 /* MSDN says: "simple parts are indexed with -1" */
330 if ((nPart
< -1) || (nPart
>= infoPtr
->numParts
))
334 return (infoPtr
->part0
.hIcon
);
336 return (infoPtr
->parts
[nPart
].hIcon
);
341 STATUSBAR_GetParts (STATUSWINDOWINFO
*infoPtr
, INT num_parts
, INT parts
[])
345 TRACE("(%d)\n", num_parts
);
347 for (i
= 0; i
< num_parts
; i
++) {
348 parts
[i
] = infoPtr
->parts
[i
].x
;
351 return infoPtr
->numParts
;
356 STATUSBAR_GetRect (STATUSWINDOWINFO
*infoPtr
, INT nPart
, LPRECT rect
)
358 TRACE("part %d\n", nPart
);
360 *rect
= infoPtr
->part0
.bound
;
362 *rect
= infoPtr
->parts
[nPart
].bound
;
368 STATUSBAR_GetTextA (STATUSWINDOWINFO
*infoPtr
, INT nPart
, LPSTR buf
)
370 STATUSWINDOWPART
*part
;
373 TRACE("part %d\n", nPart
);
375 /* MSDN says: "simple parts use index of 0", so this check is ok. */
376 if (nPart
< 0 || nPart
>= infoPtr
->numParts
) return 0;
379 part
= &infoPtr
->part0
;
381 part
= &infoPtr
->parts
[nPart
];
383 if (part
->style
& SBT_OWNERDRAW
)
384 result
= (LRESULT
)part
->text
;
386 DWORD len
= part
->text
? WideCharToMultiByte( CP_ACP
, 0, part
->text
, -1,
387 NULL
, 0, NULL
, NULL
) - 1 : 0;
388 result
= MAKELONG( len
, part
->style
);
389 if (part
->text
&& buf
)
390 WideCharToMultiByte( CP_ACP
, 0, part
->text
, -1, buf
, len
+1, NULL
, NULL
);
397 STATUSBAR_GetTextW (STATUSWINDOWINFO
*infoPtr
, INT nPart
, LPWSTR buf
)
399 STATUSWINDOWPART
*part
;
402 TRACE("part %d\n", nPart
);
403 if (nPart
< 0 || nPart
>= infoPtr
->numParts
) return 0;
406 part
= &infoPtr
->part0
;
408 part
= &infoPtr
->parts
[nPart
];
410 if (part
->style
& SBT_OWNERDRAW
)
411 result
= (LRESULT
)part
->text
;
413 result
= part
->text
? strlenW (part
->text
) : 0;
414 result
|= (part
->style
<< 16);
415 if (part
->text
&& buf
)
416 strcpyW (buf
, part
->text
);
423 STATUSBAR_GetTextLength (STATUSWINDOWINFO
*infoPtr
, INT nPart
)
425 STATUSWINDOWPART
*part
;
428 TRACE("part %d\n", nPart
);
430 /* MSDN says: "simple parts use index of 0", so this check is ok. */
431 if (nPart
< 0 || nPart
>= infoPtr
->numParts
) return 0;
434 part
= &infoPtr
->part0
;
436 part
= &infoPtr
->parts
[nPart
];
439 result
= strlenW(part
->text
);
443 result
|= (part
->style
<< 16);
448 STATUSBAR_GetTipTextA (STATUSWINDOWINFO
*infoPtr
, INT id
, LPSTR tip
, INT size
)
452 CHAR buf
[INFOTIPSIZE
];
455 if (infoPtr
->hwndToolTip
) {
457 ti
.cbSize
= sizeof(TTTOOLINFOA
);
458 ti
.hwnd
= infoPtr
->Self
;
461 SendMessageA (infoPtr
->hwndToolTip
, TTM_GETTEXTA
, 0, (LPARAM
)&ti
);
463 lstrcpynA (tip
, buf
, size
);
470 STATUSBAR_GetTipTextW (STATUSWINDOWINFO
*infoPtr
, INT id
, LPWSTR tip
, INT size
)
474 WCHAR buf
[INFOTIPSIZE
];
477 if (infoPtr
->hwndToolTip
) {
479 ti
.cbSize
= sizeof(TTTOOLINFOW
);
480 ti
.hwnd
= infoPtr
->Self
;
483 SendMessageW(infoPtr
->hwndToolTip
, TTM_GETTEXTW
, 0, (LPARAM
)&ti
);
485 lstrcpynW(tip
, buf
, size
);
493 STATUSBAR_SetBkColor (STATUSWINDOWINFO
*infoPtr
, COLORREF color
)
497 oldBkColor
= infoPtr
->clrBk
;
498 infoPtr
->clrBk
= color
;
499 InvalidateRect(infoPtr
->Self
, NULL
, FALSE
);
501 TRACE("CREF: %08lx -> %08lx\n", oldBkColor
, infoPtr
->clrBk
);
507 STATUSBAR_SetIcon (STATUSWINDOWINFO
*infoPtr
, INT nPart
, HICON hIcon
)
509 if ((nPart
< -1) || (nPart
>= infoPtr
->numParts
))
512 TRACE("setting part %d\n", nPart
);
514 /* FIXME: MSDN says "if nPart is -1, the status bar is assumed simple" */
516 if (infoPtr
->part0
.hIcon
== hIcon
) /* same as - no redraw */
518 infoPtr
->part0
.hIcon
= hIcon
;
520 InvalidateRect(infoPtr
->Self
, &infoPtr
->part0
.bound
, FALSE
);
522 if (infoPtr
->parts
[nPart
].hIcon
== hIcon
) /* same as - no redraw */
525 infoPtr
->parts
[nPart
].hIcon
= hIcon
;
526 if (!(infoPtr
->simple
))
527 InvalidateRect(infoPtr
->Self
, &infoPtr
->parts
[nPart
].bound
, FALSE
);
534 STATUSBAR_SetMinHeight (STATUSWINDOWINFO
*infoPtr
, INT height
)
537 TRACE("(height=%d)\n", height
);
538 if (IsWindowVisible (infoPtr
->Self
)) {
542 GetClientRect (GetParent (infoPtr
->Self
), &parent_rect
);
543 infoPtr
->height
= height
+ VERT_BORDER
;
544 width
= parent_rect
.right
- parent_rect
.left
;
545 x
= parent_rect
.left
;
546 y
= parent_rect
.bottom
- infoPtr
->height
;
547 MoveWindow (infoPtr
->Self
, parent_rect
.left
,
548 parent_rect
.bottom
- infoPtr
->height
,
549 width
, infoPtr
->height
, TRUE
);
550 STATUSBAR_SetPartBounds (infoPtr
);
558 STATUSBAR_SetParts (STATUSWINDOWINFO
*infoPtr
, INT count
, LPINT parts
)
560 STATUSWINDOWPART
*tmp
;
563 TRACE("(%d,%p)\n", count
, parts
);
565 oldNumParts
= infoPtr
->numParts
;
566 infoPtr
->numParts
= count
;
567 if (oldNumParts
> infoPtr
->numParts
) {
568 for (i
= infoPtr
->numParts
; i
< oldNumParts
; i
++) {
569 if (infoPtr
->parts
[i
].text
&& !(infoPtr
->parts
[i
].style
& SBT_OWNERDRAW
))
570 COMCTL32_Free (infoPtr
->parts
[i
].text
);
572 } else if (oldNumParts
< infoPtr
->numParts
) {
573 tmp
= COMCTL32_Alloc (sizeof(STATUSWINDOWPART
) * infoPtr
->numParts
);
574 if (!tmp
) return FALSE
;
575 for (i
= 0; i
< oldNumParts
; i
++) {
576 tmp
[i
] = infoPtr
->parts
[i
];
579 COMCTL32_Free (infoPtr
->parts
);
580 infoPtr
->parts
= tmp
;
582 if (oldNumParts
== infoPtr
->numParts
) {
583 for (i
=0; i
< oldNumParts
; i
++)
584 if (infoPtr
->parts
[i
].x
!= parts
[i
])
586 if (i
==oldNumParts
) /* Unchanged? no need to redraw! */
590 for (i
= 0; i
< infoPtr
->numParts
; i
++)
591 infoPtr
->parts
[i
].x
= parts
[i
];
593 if (infoPtr
->hwndToolTip
) {
597 ZeroMemory (&ti
, sizeof(TTTOOLINFOW
));
598 ti
.cbSize
= sizeof(TTTOOLINFOW
);
599 ti
.hwnd
= infoPtr
->Self
;
601 nTipCount
= SendMessageW (infoPtr
->hwndToolTip
, TTM_GETTOOLCOUNT
, 0, 0);
602 if (nTipCount
< infoPtr
->numParts
) {
604 for (i
= nTipCount
; i
< infoPtr
->numParts
; i
++) {
605 TRACE("add tool %d\n", i
);
607 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
,
611 else if (nTipCount
> infoPtr
->numParts
) {
613 for (i
= nTipCount
- 1; i
>= infoPtr
->numParts
; i
--) {
614 TRACE("delete tool %d\n", i
);
616 SendMessageW (infoPtr
->hwndToolTip
, TTM_DELTOOLW
,
621 STATUSBAR_SetPartBounds (infoPtr
);
622 InvalidateRect(infoPtr
->Self
, NULL
, FALSE
);
628 STATUSBAR_SetTextT (STATUSWINDOWINFO
*infoPtr
, INT nPart
, WORD style
,
629 LPCWSTR text
, BOOL isW
)
631 STATUSWINDOWPART
*part
=NULL
;
632 BOOL changed
= FALSE
;
634 if (style
& SBT_OWNERDRAW
) {
635 TRACE("part %d, text %p\n",nPart
,text
);
637 else TRACE("part %d, text %s\n", nPart
, debugstr_t(text
, isW
));
639 /* MSDN says: "If the parameter is set to SB_SIMPLEID (255), the status
640 * window is assumed to be a simple window */
642 if (nPart
== 0x00ff) {
643 part
= &infoPtr
->part0
;
645 if (infoPtr
->parts
&& nPart
>= 0 && nPart
< infoPtr
->numParts
) {
646 part
= &infoPtr
->parts
[nPart
];
649 if (!part
) return FALSE
;
651 if (part
->style
!= style
)
655 if (style
& SBT_OWNERDRAW
) {
656 if (part
->text
== text
)
658 part
->text
= (LPWSTR
)text
;
663 LPCSTR atxt
= (LPCSTR
)text
;
664 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, atxt
, -1, NULL
, 0 );
665 ntext
= COMCTL32_Alloc( (len
+ 1)*sizeof(WCHAR
) );
666 if (!ntext
) return FALSE
;
667 MultiByteToWideChar( CP_ACP
, 0, atxt
, -1, ntext
, len
);
669 ntext
= COMCTL32_Alloc( (strlenW(text
) + 1)*sizeof(WCHAR
) );
670 if (!ntext
) return FALSE
;
671 strcpyW (ntext
, text
);
674 /* check if text is unchanged -> no need to redraw */
676 if (!changed
&& part
->text
&& !lstrcmpW(ntext
, part
->text
)) {
677 if (!isW
) COMCTL32_Free(ntext
);
681 if (!changed
&& !part
->text
)
686 COMCTL32_Free (part
->text
);
689 InvalidateRect(infoPtr
->Self
, &part
->bound
, FALSE
);
696 STATUSBAR_SetTipTextA (STATUSWINDOWINFO
*infoPtr
, INT id
, LPSTR text
)
698 TRACE("part %d: \"%s\"\n", id
, text
);
699 if (infoPtr
->hwndToolTip
) {
701 ti
.cbSize
= sizeof(TTTOOLINFOA
);
702 ti
.hwnd
= infoPtr
->Self
;
706 SendMessageA (infoPtr
->hwndToolTip
, TTM_UPDATETIPTEXTA
,
715 STATUSBAR_SetTipTextW (STATUSWINDOWINFO
*infoPtr
, INT id
, LPWSTR text
)
717 TRACE("part %d: \"%s\"\n", id
, debugstr_w(text
));
718 if (infoPtr
->hwndToolTip
) {
720 ti
.cbSize
= sizeof(TTTOOLINFOW
);
721 ti
.hwnd
= infoPtr
->Self
;
725 SendMessageW (infoPtr
->hwndToolTip
, TTM_UPDATETIPTEXTW
,
733 inline static LRESULT
734 STATUSBAR_SetUnicodeFormat (STATUSWINDOWINFO
*infoPtr
, BOOL bUnicode
)
736 BOOL bOld
= infoPtr
->bUnicode
;
738 TRACE("(0x%x)\n", bUnicode
);
739 infoPtr
->bUnicode
= bUnicode
;
746 STATUSBAR_Simple (STATUSWINDOWINFO
*infoPtr
, BOOL simple
)
750 TRACE("(simple=%d)\n", simple
);
751 if (infoPtr
->simple
== simple
) /* no need to change */
754 infoPtr
->simple
= simple
;
756 /* send notification */
757 nmhdr
.hwndFrom
= infoPtr
->Self
;
758 nmhdr
.idFrom
= GetWindowLongW (infoPtr
->Self
, GWL_ID
);
759 nmhdr
.code
= SBN_SIMPLEMODECHANGE
;
760 SendMessageW (GetParent (infoPtr
->Self
), WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
761 InvalidateRect(infoPtr
->Self
, NULL
, FALSE
);
767 STATUSBAR_WMDestroy (STATUSWINDOWINFO
*infoPtr
)
772 for (i
= 0; i
< infoPtr
->numParts
; i
++) {
773 if (infoPtr
->parts
[i
].text
&& !(infoPtr
->parts
[i
].style
& SBT_OWNERDRAW
))
774 COMCTL32_Free (infoPtr
->parts
[i
].text
);
776 if (infoPtr
->part0
.text
&& !(infoPtr
->part0
.style
& SBT_OWNERDRAW
))
777 COMCTL32_Free (infoPtr
->part0
.text
);
778 COMCTL32_Free (infoPtr
->parts
);
780 /* delete default font */
781 if (infoPtr
->hDefaultFont
)
782 DeleteObject (infoPtr
->hDefaultFont
);
784 /* delete tool tip control */
785 if (infoPtr
->hwndToolTip
)
786 DestroyWindow (infoPtr
->hwndToolTip
);
788 COMCTL32_Free (infoPtr
);
789 SetWindowLongW(infoPtr
->Self
, 0, 0);
795 STATUSBAR_WMCreate (HWND hwnd
, LPCREATESTRUCTA lpCreate
)
797 STATUSWINDOWINFO
*infoPtr
;
798 NONCLIENTMETRICSW nclm
;
801 int i
, width
, len
, textHeight
= 0;
805 infoPtr
= (STATUSWINDOWINFO
*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO
));
806 if (!infoPtr
) goto create_fail
;
807 SetWindowLongW (hwnd
, 0, (DWORD
)infoPtr
);
809 infoPtr
->Self
= hwnd
;
810 infoPtr
->numParts
= 1;
812 infoPtr
->simple
= FALSE
;
813 infoPtr
->clrBk
= CLR_DEFAULT
;
816 i
= SendMessageW(GetParent (hwnd
), WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
817 infoPtr
->NtfUnicode
= (i
== NFR_UNICODE
);
819 GetClientRect (hwnd
, &rect
);
820 InvalidateRect (hwnd
, &rect
, 0);
823 ZeroMemory (&nclm
, sizeof(nclm
));
824 nclm
.cbSize
= sizeof(nclm
);
825 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, nclm
.cbSize
, &nclm
, 0);
826 infoPtr
->hDefaultFont
= CreateFontIndirectW (&nclm
.lfStatusFont
);
828 /* initialize simple case */
829 infoPtr
->part0
.bound
= rect
;
830 infoPtr
->part0
.text
= 0;
831 infoPtr
->part0
.x
= 0;
832 infoPtr
->part0
.style
= 0;
833 infoPtr
->part0
.hIcon
= 0;
835 /* initialize first part */
836 infoPtr
->parts
= COMCTL32_Alloc (sizeof(STATUSWINDOWPART
));
837 if (!infoPtr
->parts
) goto create_fail
;
838 infoPtr
->parts
[0].bound
= rect
;
839 infoPtr
->parts
[0].text
= 0;
840 infoPtr
->parts
[0].x
= -1;
841 infoPtr
->parts
[0].style
= 0;
842 infoPtr
->parts
[0].hIcon
= 0;
844 if (IsWindowUnicode (hwnd
)) {
845 infoPtr
->bUnicode
= TRUE
;
846 if (lpCreate
->lpszName
&&
847 (len
= strlenW ((LPCWSTR
)lpCreate
->lpszName
))) {
848 infoPtr
->parts
[0].text
= COMCTL32_Alloc ((len
+ 1)*sizeof(WCHAR
));
849 if (!infoPtr
->parts
[0].text
) goto create_fail
;
850 strcpyW (infoPtr
->parts
[0].text
, (LPCWSTR
)lpCreate
->lpszName
);
854 if (lpCreate
->lpszName
&&
855 (len
= strlen((LPCSTR
)lpCreate
->lpszName
))) {
856 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)lpCreate
->lpszName
, -1, NULL
, 0 );
857 infoPtr
->parts
[0].text
= COMCTL32_Alloc (lenW
*sizeof(WCHAR
));
858 if (!infoPtr
->parts
[0].text
) goto create_fail
;
859 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)lpCreate
->lpszName
, -1,
860 infoPtr
->parts
[0].text
, lenW
);
864 dwStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
866 /* statusbars on managed windows should not have SIZEGRIP style */
867 if ((dwStyle
& SBARS_SIZEGRIP
) && lpCreate
->hwndParent
)
868 if (GetWindowLongW (lpCreate
->hwndParent
, GWL_EXSTYLE
) & WS_EX_MANAGED
)
869 SetWindowLongW (hwnd
, GWL_STYLE
, dwStyle
& ~SBARS_SIZEGRIP
);
871 if ((hdc
= GetDC (0))) {
875 hOldFont
= SelectObject (hdc
, infoPtr
->hDefaultFont
);
876 GetTextMetricsW (hdc
, &tm
);
877 textHeight
= tm
.tmHeight
;
878 SelectObject (hdc
, hOldFont
);
881 TRACE(" textHeight=%d\n", textHeight
);
883 if (dwStyle
& SBT_TOOLTIPS
) {
884 infoPtr
->hwndToolTip
=
885 CreateWindowExW (0, TOOLTIPS_CLASSW
, NULL
, 0,
886 CW_USEDEFAULT
, CW_USEDEFAULT
,
887 CW_USEDEFAULT
, CW_USEDEFAULT
,
889 GetWindowLongW (hwnd
, GWL_HINSTANCE
), NULL
);
891 if (infoPtr
->hwndToolTip
) {
892 NMTOOLTIPSCREATED nmttc
;
894 nmttc
.hdr
.hwndFrom
= hwnd
;
895 nmttc
.hdr
.idFrom
= GetWindowLongW (hwnd
, GWL_ID
);
896 nmttc
.hdr
.code
= NM_TOOLTIPSCREATED
;
897 nmttc
.hwndToolTips
= infoPtr
->hwndToolTip
;
899 SendMessageW (lpCreate
->hwndParent
, WM_NOTIFY
,
900 (WPARAM
)nmttc
.hdr
.idFrom
, (LPARAM
)&nmttc
);
904 if (!(dwStyle
& CCS_NORESIZE
)) { /* don't resize wnd if it doesn't want it ! */
905 GetClientRect (GetParent (hwnd
), &rect
);
906 width
= rect
.right
- rect
.left
;
907 infoPtr
->height
= textHeight
+ 4 + VERT_BORDER
;
908 SetWindowPos(hwnd
, 0, lpCreate
->x
, lpCreate
->y
- 1,
909 width
, infoPtr
->height
, SWP_NOZORDER
);
910 STATUSBAR_SetPartBounds (infoPtr
);
917 if (infoPtr
) STATUSBAR_WMDestroy(infoPtr
);
922 /* in contrast to SB_GETTEXT*, WM_GETTEXT handles the text
923 * of the first part only (usual behaviour) */
925 STATUSBAR_WMGetText (STATUSWINDOWINFO
*infoPtr
, INT size
, LPWSTR buf
)
930 if (!(infoPtr
->parts
[0].text
))
932 if (infoPtr
->bUnicode
)
933 len
= strlenW (infoPtr
->parts
[0].text
);
935 len
= WideCharToMultiByte( CP_ACP
, 0, infoPtr
->parts
[0].text
, -1, NULL
, 0, NULL
, NULL
)-1;
938 if (infoPtr
->bUnicode
)
939 strcpyW (buf
, infoPtr
->parts
[0].text
);
941 WideCharToMultiByte( CP_ACP
, 0, infoPtr
->parts
[0].text
, -1,
942 (LPSTR
)buf
, len
+1, NULL
, NULL
);
951 STATUSBAR_WMNCHitTest (STATUSWINDOWINFO
*infoPtr
, INT x
, INT y
)
953 if (GetWindowLongW (infoPtr
->Self
, GWL_STYLE
) & SBARS_SIZEGRIP
) {
957 GetClientRect (infoPtr
->Self
, &rect
);
961 ScreenToClient (infoPtr
->Self
, &pt
);
963 rect
.left
= rect
.right
- 13;
966 if (PtInRect (&rect
, pt
))
967 return HTBOTTOMRIGHT
;
975 STATUSBAR_WMPaint (STATUSWINDOWINFO
*infoPtr
, HDC hdc
)
980 if (hdc
) return STATUSBAR_Refresh (infoPtr
, hdc
);
981 hdc
= BeginPaint (infoPtr
->Self
, &ps
);
982 STATUSBAR_Refresh (infoPtr
, hdc
);
983 EndPaint (infoPtr
->Self
, &ps
);
990 STATUSBAR_WMSetFont (STATUSWINDOWINFO
*infoPtr
, HFONT font
, BOOL redraw
)
992 infoPtr
->hFont
= font
;
993 TRACE("%04x\n", infoPtr
->hFont
);
995 InvalidateRect(infoPtr
->Self
, NULL
, FALSE
);
1002 STATUSBAR_WMSetText (STATUSWINDOWINFO
*infoPtr
, LPCSTR text
)
1004 STATUSWINDOWPART
*part
;
1008 if (infoPtr
->numParts
== 0)
1011 part
= &infoPtr
->parts
[0];
1012 /* duplicate string */
1014 COMCTL32_Free (part
->text
);
1016 if (infoPtr
->bUnicode
) {
1017 if (text
&& (len
= strlenW((LPCWSTR
)text
))) {
1018 part
->text
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1019 if (!part
->text
) return FALSE
;
1020 strcpyW (part
->text
, (LPCWSTR
)text
);
1024 if (text
&& (len
= lstrlenA(text
))) {
1025 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, text
, -1, NULL
, 0 );
1026 part
->text
= COMCTL32_Alloc (lenW
*sizeof(WCHAR
));
1027 if (!part
->text
) return FALSE
;
1028 MultiByteToWideChar( CP_ACP
, 0, text
, -1, part
->text
, lenW
);
1032 InvalidateRect(infoPtr
->Self
, &part
->bound
, FALSE
);
1039 STATUSBAR_WMSize (STATUSWINDOWINFO
*infoPtr
, WORD flags
)
1044 /* Need to resize width to match parent */
1045 TRACE("flags %04x\n", flags
);
1047 if (flags
!= SIZE_RESTORED
) {
1048 WARN("flags MUST be SIZE_RESTORED\n");
1051 if (GetWindowLongW(infoPtr
->Self
, GWL_STYLE
) & CCS_NORESIZE
) return FALSE
;
1053 /* width and height don't apply */
1054 GetClientRect (GetParent(infoPtr
->Self
), &parent_rect
);
1055 width
= parent_rect
.right
- parent_rect
.left
;
1056 x
= parent_rect
.left
;
1057 y
= parent_rect
.bottom
- infoPtr
->height
;
1058 MoveWindow (infoPtr
->Self
, parent_rect
.left
,
1059 parent_rect
.bottom
- infoPtr
->height
,
1060 width
, infoPtr
->height
, TRUE
);
1061 STATUSBAR_SetPartBounds (infoPtr
);
1067 STATUSBAR_NotifyFormat (STATUSWINDOWINFO
*infoPtr
, HWND from
, INT cmd
)
1069 if (cmd
== NF_REQUERY
) {
1070 INT i
= SendMessageW(from
, WM_NOTIFYFORMAT
, (WPARAM
)infoPtr
->Self
, NF_QUERY
);
1071 infoPtr
->NtfUnicode
= (i
== NFR_UNICODE
);
1073 return infoPtr
->NtfUnicode
? NFR_UNICODE
: NFR_ANSI
;
1078 STATUSBAR_SendNotify (HWND hwnd
, UINT code
)
1082 TRACE("code %04x\n", code
);
1083 nmhdr
.hwndFrom
= hwnd
;
1084 nmhdr
.idFrom
= GetWindowLongW (hwnd
, GWL_ID
);
1086 SendMessageW (GetParent (hwnd
), WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
1092 static LRESULT WINAPI
1093 StatusWindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1095 STATUSWINDOWINFO
*infoPtr
= STATUSBAR_GetInfoPtr(hwnd
);
1096 INT nPart
= ((INT
) wParam
) & 0x00ff;
1099 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1100 if (!infoPtr
&& msg
!= WM_CREATE
)
1101 return DefWindowProcW (hwnd
, msg
, wParam
, lParam
);
1105 return STATUSBAR_GetBorders ((INT
*)lParam
);
1108 return STATUSBAR_GetIcon (infoPtr
, nPart
);
1111 return STATUSBAR_GetParts (infoPtr
, (INT
)wParam
, (INT
*)lParam
);
1114 return STATUSBAR_GetRect (infoPtr
, nPart
, (LPRECT
)lParam
);
1117 return STATUSBAR_GetTextA (infoPtr
, nPart
, (LPSTR
)lParam
);
1120 return STATUSBAR_GetTextW (infoPtr
, nPart
, (LPWSTR
)lParam
);
1122 case SB_GETTEXTLENGTHA
:
1123 case SB_GETTEXTLENGTHW
:
1124 return STATUSBAR_GetTextLength (infoPtr
, nPart
);
1126 case SB_GETTIPTEXTA
:
1127 return STATUSBAR_GetTipTextA (infoPtr
, LOWORD(wParam
), (LPSTR
)lParam
, HIWORD(wParam
));
1129 case SB_GETTIPTEXTW
:
1130 return STATUSBAR_GetTipTextW (infoPtr
, LOWORD(wParam
), (LPWSTR
)lParam
, HIWORD(wParam
));
1132 case SB_GETUNICODEFORMAT
:
1133 return infoPtr
->bUnicode
;
1136 return infoPtr
->simple
;
1139 return STATUSBAR_SetBkColor (infoPtr
, (COLORREF
)lParam
);
1142 return STATUSBAR_SetIcon (infoPtr
, nPart
, (HICON
)lParam
);
1144 case SB_SETMINHEIGHT
:
1145 return STATUSBAR_SetMinHeight (infoPtr
, (INT
)wParam
);
1148 return STATUSBAR_SetParts (infoPtr
, (INT
)wParam
, (LPINT
)lParam
);
1151 return STATUSBAR_SetTextT (infoPtr
, nPart
, wParam
& 0xff00, (LPCWSTR
)lParam
, FALSE
);
1154 return STATUSBAR_SetTextT (infoPtr
, nPart
, wParam
& 0xff00, (LPCWSTR
)lParam
, TRUE
);
1156 case SB_SETTIPTEXTA
:
1157 return STATUSBAR_SetTipTextA (infoPtr
, (INT
)wParam
, (LPSTR
)lParam
);
1159 case SB_SETTIPTEXTW
:
1160 return STATUSBAR_SetTipTextW (infoPtr
, (INT
)wParam
, (LPWSTR
)lParam
);
1162 case SB_SETUNICODEFORMAT
:
1163 return STATUSBAR_SetUnicodeFormat (infoPtr
, (BOOL
)wParam
);
1166 return STATUSBAR_Simple (infoPtr
, (BOOL
)wParam
);
1169 return STATUSBAR_WMCreate (hwnd
, (LPCREATESTRUCTA
)lParam
);
1172 return STATUSBAR_WMDestroy (infoPtr
);
1175 return infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
;
1178 return STATUSBAR_WMGetText (infoPtr
, (INT
)wParam
, (LPWSTR
)lParam
);
1180 case WM_GETTEXTLENGTH
:
1181 return STATUSBAR_GetTextLength (infoPtr
, 0);
1183 case WM_LBUTTONDBLCLK
:
1184 return STATUSBAR_SendNotify (hwnd
, NM_DBLCLK
);
1187 return STATUSBAR_SendNotify (hwnd
, NM_CLICK
);
1190 return STATUSBAR_Relay2Tip (infoPtr
, msg
, wParam
, lParam
);
1193 res
= STATUSBAR_WMNCHitTest(infoPtr
, (INT
)LOWORD(lParam
),
1194 (INT
)HIWORD(lParam
));
1195 if (res
!= HTERROR
) return res
;
1196 return DefWindowProcW (hwnd
, msg
, wParam
, lParam
);
1198 case WM_NCLBUTTONUP
:
1199 case WM_NCLBUTTONDOWN
:
1200 PostMessageW (GetParent (hwnd
), msg
, wParam
, lParam
);
1203 case WM_NOTIFYFORMAT
:
1204 return STATUSBAR_NotifyFormat(infoPtr
, (HWND
)wParam
, (INT
)lParam
);
1207 return STATUSBAR_WMPaint (infoPtr
, (HDC
)wParam
);
1209 case WM_RBUTTONDBLCLK
:
1210 return STATUSBAR_SendNotify (hwnd
, NM_RDBLCLK
);
1213 return STATUSBAR_SendNotify (hwnd
, NM_RCLICK
);
1216 return STATUSBAR_WMSetFont (infoPtr
, (HFONT
)wParam
, LOWORD(lParam
));
1219 return STATUSBAR_WMSetText (infoPtr
, (LPCSTR
)lParam
);
1222 if (STATUSBAR_WMSize (infoPtr
, (WORD
)wParam
)) return 0;
1223 return DefWindowProcW (hwnd
, msg
, wParam
, lParam
);
1226 if ((msg
>= WM_USER
) && (msg
< WM_APP
))
1227 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1228 msg
, wParam
, lParam
);
1229 return DefWindowProcW (hwnd
, msg
, wParam
, lParam
);
1235 /***********************************************************************
1236 * STATUS_Register [Internal]
1238 * Registers the status window class.
1242 STATUS_Register (void)
1246 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
1247 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_VREDRAW
;
1248 wndClass
.lpfnWndProc
= (WNDPROC
)StatusWindowProc
;
1249 wndClass
.cbClsExtra
= 0;
1250 wndClass
.cbWndExtra
= sizeof(STATUSWINDOWINFO
*);
1251 wndClass
.hCursor
= LoadCursorW (0, IDC_ARROWW
);
1252 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
1253 wndClass
.lpszClassName
= STATUSCLASSNAMEW
;
1255 RegisterClassW (&wndClass
);
1259 /***********************************************************************
1260 * STATUS_Unregister [Internal]
1262 * Unregisters the status window class.
1266 STATUS_Unregister (void)
1268 UnregisterClassW (STATUSCLASSNAMEW
, (HINSTANCE
)NULL
);