Release 980822
[wine/multimedia.git] / controls / status.c
blob6536fa9f9d43c0a9116761c8a6b080b3abb2f7a8
1 /*
2 * Interface code to StatusWindow widget/control
4 * Copyright 1996 Bruce Milner
5 * Copyright 1998 Eric Kohl
6 */
8 #include "windows.h"
9 #include "status.h"
10 #include "commctrl.h"
11 #include "heap.h"
12 #include "win.h"
13 #include "debug.h"
16 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
17 * The second cdrom contains executables drawstat.exe,gettext.exe,
18 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
22 * Fixme/Todo
23 * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
24 + 2) Tooltip support (almost done).
27 #define _MAX(a,b) (((a)>(b))?(a):(b))
28 #define _MIN(a,b) (((a)>(b))?(b):(a))
30 #define HORZ_BORDER 0
31 #define VERT_BORDER 2
32 #define HORZ_GAP 2
34 #define STATUSBAR_GetInfoPtr(wndPtr) ((STATUSWINDOWINFO *)wndPtr->wExtra[0])
37 static void
38 STATUSBAR_DrawSizeGrip (HDC32 hdc, LPRECT32 lpRect)
40 HPEN32 hOldPen;
41 POINT32 pt;
42 INT32 i;
44 pt.x = lpRect->right - 1;
45 pt.y = lpRect->bottom - 1;
47 hOldPen = SelectObject32 (hdc, GetSysColorPen32 (COLOR_3DFACE));
48 MoveToEx32 (hdc, pt.x - 12, pt.y, NULL);
49 LineTo32 (hdc, pt.x, pt.y);
50 LineTo32 (hdc, pt.x, pt.y - 12);
52 pt.x--;
53 pt.y--;
55 SelectObject32 (hdc, GetSysColorPen32 (COLOR_3DSHADOW));
56 for (i = 1; i < 11; i += 4) {
57 MoveToEx32 (hdc, pt.x - i, pt.y, NULL);
58 LineTo32 (hdc, pt.x, pt.y - i);
60 MoveToEx32 (hdc, pt.x - i-1, pt.y, NULL);
61 LineTo32 (hdc, pt.x, pt.y - i-1);
64 SelectObject32 (hdc, GetSysColorPen32 (COLOR_3DHIGHLIGHT));
65 for (i = 3; i < 13; i += 4) {
66 MoveToEx32 (hdc, pt.x - i, pt.y, NULL);
67 LineTo32 (hdc, pt.x, pt.y - i);
70 SelectObject32 (hdc, hOldPen);
74 static void
75 STATUSBAR_DrawPart (HDC32 hdc, STATUSWINDOWPART *part)
77 RECT32 r = part->bound;
78 UINT32 border = BDR_SUNKENOUTER;
80 if (part->style==SBT_POPOUT)
81 border = BDR_RAISEDOUTER;
82 else if (part->style==SBT_NOBORDERS)
83 border = 0;
85 DrawEdge32(hdc, &r, border, BF_RECT|BF_ADJUST);
87 /* draw the icon */
88 if (part->hIcon) {
89 INT32 cy = r.bottom - r.top;
91 r.left += 2;
92 DrawIconEx32 (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
93 r.left += cy;
96 /* now draw text */
97 if (part->text) {
98 int oldbkmode = SetBkMode32(hdc, TRANSPARENT);
99 LPSTR p = (LPSTR)part->text;
100 UINT32 align = DT_LEFT;
101 if (*p == '\t') {
102 p++;
103 align = DT_CENTER;
105 if (*p == '\t') {
106 p++;
107 align = DT_RIGHT;
110 r.left += 3;
111 DrawText32A(hdc, p, lstrlen32A(p), &r, align|DT_VCENTER|DT_SINGLELINE);
112 if (oldbkmode != TRANSPARENT)
113 SetBkMode32(hdc, oldbkmode);
118 static VOID
119 STATUSBAR_RefreshPart (WND *wndPtr, STATUSWINDOWPART *part, HDC32 hdc)
121 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
122 HBRUSH32 hbrBk;
123 HFONT32 hOldFont;
125 if (!IsWindowVisible32(wndPtr->hwndSelf))
126 return;
128 if (self->clrBk != CLR_DEFAULT)
129 hbrBk = CreateSolidBrush32 (self->clrBk);
130 else
131 hbrBk = GetSysColorBrush32 (COLOR_3DFACE);
132 FillRect32(hdc, &part->bound, hbrBk);
134 hOldFont = SelectObject32 (hdc, self->hFont ? self->hFont : self->hDefaultFont);
136 if (part->style == SBT_OWNERDRAW) {
137 DRAWITEMSTRUCT32 dis;
139 dis.CtlID = wndPtr->wIDmenu;
140 dis.itemID = -1;
141 dis.hwndItem = wndPtr->hwndSelf;
142 dis.hDC = hdc;
143 dis.rcItem = part->bound;
144 dis.itemData = (INT32)part->text;
145 SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_DRAWITEM,
146 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&dis);
148 else
149 STATUSBAR_DrawPart (hdc, part);
151 SelectObject32 (hdc, hOldFont);
153 if (self->clrBk != CLR_DEFAULT)
154 DeleteObject32 (hbrBk);
156 if (wndPtr->dwStyle & SBARS_SIZEGRIP) {
157 RECT32 rect;
159 GetClientRect32 (wndPtr->hwndSelf, &rect);
160 STATUSBAR_DrawSizeGrip (hdc, &rect);
165 static BOOL32
166 STATUSBAR_Refresh (WND *wndPtr, HDC32 hdc)
168 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
169 int i;
170 RECT32 rect;
171 HBRUSH32 hbrBk;
172 HFONT32 hOldFont;
174 if (!IsWindowVisible32(wndPtr->hwndSelf))
175 return (TRUE);
177 GetClientRect32 (wndPtr->hwndSelf, &rect);
179 if (self->clrBk != CLR_DEFAULT)
180 hbrBk = CreateSolidBrush32 (self->clrBk);
181 else
182 hbrBk = GetSysColorBrush32 (COLOR_3DFACE);
183 FillRect32(hdc, &rect, hbrBk);
185 hOldFont = SelectObject32 (hdc, self->hFont ? self->hFont : self->hDefaultFont);
187 if (self->simple) {
188 STATUSBAR_DrawPart (hdc, &self->part0);
190 else {
191 for (i = 0; i < self->numParts; i++) {
192 if (self->parts[i].style == SBT_OWNERDRAW) {
193 DRAWITEMSTRUCT32 dis;
195 dis.CtlID = wndPtr->wIDmenu;
196 dis.itemID = -1;
197 dis.hwndItem = wndPtr->hwndSelf;
198 dis.hDC = hdc;
199 dis.rcItem = self->parts[i].bound;
200 dis.itemData = (INT32)self->parts[i].text;
201 SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_DRAWITEM,
202 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&dis);
204 else
205 STATUSBAR_DrawPart (hdc, &self->parts[i]);
209 SelectObject32 (hdc, hOldFont);
211 if (self->clrBk != CLR_DEFAULT)
212 DeleteObject32 (hbrBk);
214 if (wndPtr->dwStyle & SBARS_SIZEGRIP)
215 STATUSBAR_DrawSizeGrip (hdc, &rect);
217 return TRUE;
221 static void
222 STATUSBAR_SetPartBounds (WND *wndPtr)
224 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
225 STATUSWINDOWPART *part;
226 RECT32 rect, *r;
227 int i;
229 /* get our window size */
230 GetClientRect32 (wndPtr->hwndSelf, &rect);
232 rect.top += VERT_BORDER;
234 /* set bounds for simple rectangle */
235 self->part0.bound = rect;
237 /* set bounds for non-simple rectangles */
238 for (i = 0; i < self->numParts; i++) {
239 part = &self->parts[i];
240 r = &self->parts[i].bound;
241 r->top = rect.top;
242 r->bottom = rect.bottom;
243 if (i == 0)
244 r->left = 0;
245 else
246 r->left = self->parts[i-1].bound.right + HORZ_GAP;
247 if (part->x == -1)
248 r->right = rect.right;
249 else
250 r->right = part->x;
252 if (self->hwndToolTip) {
253 TTTOOLINFO32A ti;
255 ti.cbSize = sizeof(TTTOOLINFO32A);
256 ti.hwnd = wndPtr->hwndSelf;
257 ti.uId = i;
258 ti.rect = *r;
259 SendMessage32A (self->hwndToolTip, TTM_NEWTOOLRECT32A,
260 0, (LPARAM)&ti);
266 static VOID
267 STATUSBAR_RelayEvent (HWND32 hwndTip, HWND32 hwndMsg, UINT32 uMsg,
268 WPARAM32 wParam, LPARAM lParam)
270 MSG32 msg;
272 msg.hwnd = hwndMsg;
273 msg.message = uMsg;
274 msg.wParam = wParam;
275 msg.lParam = lParam;
276 msg.time = GetMessageTime ();
277 msg.pt.x = LOWORD(GetMessagePos ());
278 msg.pt.y = HIWORD(GetMessagePos ());
280 SendMessage32A (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
284 __inline__ static LRESULT
285 STATUSBAR_GetBorders (LPARAM lParam)
287 LPINT32 out = (LPINT32) lParam;
289 out[0] = HORZ_BORDER; /* horizontal border width */
290 out[1] = VERT_BORDER; /* vertical border width */
291 out[2] = HORZ_GAP; /* width of border between rectangles */
293 return TRUE;
297 static LRESULT
298 STATUSBAR_GetIcon (WND *wndPtr, WPARAM32 wParam)
300 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
301 INT32 nPart;
303 nPart = (INT32)wParam & 0x00ff;
304 if ((nPart < -1) || (nPart >= self->numParts)) return 0;
306 if (nPart == -1)
307 return (self->part0.hIcon);
308 else
309 return (self->parts[nPart].hIcon);
313 static LRESULT
314 STATUSBAR_GetParts (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
316 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
317 LPINT32 parts;
318 INT32 num_parts;
319 int i;
321 num_parts = (INT32) wParam;
322 parts = (LPINT32) lParam;
323 if (parts) {
324 return (self->numParts);
325 for (i = 0; i < num_parts; i++) {
326 parts[i] = self->parts[i].x;
329 return (self->numParts);
333 static LRESULT
334 STATUSBAR_GetRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
336 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
337 int part_num;
338 LPRECT32 rect;
340 part_num = ((INT32) wParam) & 0x00ff;
341 rect = (LPRECT32) lParam;
342 if (self->simple)
343 *rect = self->part0.bound;
344 else
345 *rect = self->parts[part_num].bound;
346 return TRUE;
350 static LRESULT
351 STATUSBAR_GetText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
353 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
354 STATUSWINDOWPART *part;
355 int part_num;
356 LRESULT result;
357 LPSTR out_text;
359 part_num = ((INT32) wParam) & 0x00ff;
360 out_text = (LPSTR) lParam;
361 if (self->simple)
362 part = &self->part0;
363 else
364 part = &self->parts[part_num];
366 if (part->style == SBT_OWNERDRAW)
367 result = (LRESULT) part->text;
368 else {
369 result = part->text ? lstrlen32A(part->text) : 0;
370 result |= (part->style << 16);
371 if (out_text) {
372 lstrcpy32A(out_text, part->text);
375 return result;
379 // << STATUSBAR_GetText32W >>
382 static LRESULT
383 STATUSBAR_GetTextLength32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
385 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
386 STATUSWINDOWPART *part;
387 int part_num;
388 DWORD result;
390 part_num = ((INT32) wParam) & 0x00ff;
392 if (self->simple)
393 part = &self->part0;
394 else
395 part = &self->parts[part_num];
397 if (part->text)
398 result = lstrlen32A(part->text);
399 else
400 result = 0;
402 result |= (part->style << 16);
403 return result;
407 // << STATUSBAR_GetTextLength32W >>
410 static LRESULT
411 STATUSBAR_GetTipText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
413 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (wndPtr);
415 if (infoPtr->hwndToolTip) {
416 TTTOOLINFO32A ti;
418 ti.cbSize = sizeof(TTTOOLINFO32A);
419 ti.hwnd = wndPtr->hwndSelf;
420 ti.uId = LOWORD(wParam);
421 SendMessage32A (infoPtr->hwndToolTip, TTM_GETTEXT32A, 0, (LPARAM)&ti);
423 if (ti.lpszText)
424 lstrcpyn32A ((LPSTR)lParam, ti.lpszText, HIWORD(wParam));
427 return 0;
431 // << STATUSBAR_GetTipText32W >>
432 // << STATUSBAR_GetUnicodeFormat >>
435 __inline__ static LRESULT
436 STATUSBAR_IsSimple (WND *wndPtr)
438 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
440 return self->simple;
444 static LRESULT
445 STATUSBAR_SetBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
447 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
448 COLORREF oldBkColor;
449 HDC32 hdc;
451 oldBkColor = self->clrBk;
452 self->clrBk = (COLORREF)lParam;
453 hdc = GetDC32 (wndPtr->hwndSelf);
454 STATUSBAR_Refresh (wndPtr, hdc);
455 ReleaseDC32 (wndPtr->hwndSelf, hdc);
457 return oldBkColor;
461 static LRESULT
462 STATUSBAR_SetIcon (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
464 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
465 INT32 nPart = (INT32)wParam & 0x00ff;
466 HDC32 hdc;
468 if ((nPart < -1) || (nPart >= self->numParts)) return FALSE;
470 hdc = GetDC32 (wndPtr->hwndSelf);
471 if (nPart == -1) {
472 self->part0.hIcon = (HICON32)lParam;
473 if (self->simple)
474 STATUSBAR_RefreshPart (wndPtr, &self->part0, hdc);
476 else {
477 self->parts[nPart].hIcon = (HICON32)lParam;
478 if (!(self->simple))
479 STATUSBAR_RefreshPart (wndPtr, &self->parts[nPart], hdc);
481 ReleaseDC32 (wndPtr->hwndSelf, hdc);
483 return TRUE;
487 static LRESULT
488 STATUSBAR_SetMinHeight (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
490 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
492 if (IsWindowVisible32 (wndPtr->hwndSelf)) {
493 HWND32 parent = GetParent32 (wndPtr->hwndSelf);
494 INT32 width, x, y;
495 RECT32 parent_rect;
497 GetClientRect32 (parent, &parent_rect);
498 self->height = (INT32)wParam + VERT_BORDER;
499 width = parent_rect.right - parent_rect.left;
500 x = parent_rect.left;
501 y = parent_rect.bottom - self->height;
502 MoveWindow32 (wndPtr->hwndSelf, parent_rect.left,
503 parent_rect.bottom - self->height,
504 width, self->height, TRUE);
505 STATUSBAR_SetPartBounds (wndPtr);
508 return TRUE;
512 static LRESULT
513 STATUSBAR_SetParts (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
515 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
516 HDC32 hdc;
517 LPINT32 parts;
518 STATUSWINDOWPART * tmp;
519 int i;
520 int oldNumParts;
522 if (self->simple)
523 self->simple = FALSE;
525 oldNumParts = self->numParts;
526 self->numParts = (INT32) wParam;
527 parts = (LPINT32) lParam;
528 if (oldNumParts > self->numParts) {
529 for (i = self->numParts ; i < oldNumParts; i++) {
530 if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
531 HeapFree(GetProcessHeap (), 0, self->parts[i].text);
534 else if (oldNumParts < self->numParts) {
535 tmp = HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY,
536 sizeof(STATUSWINDOWPART) * self->numParts);
537 for (i = 0; i < oldNumParts; i++) {
538 tmp[i] = self->parts[i];
540 if (self->parts)
541 HeapFree(GetProcessHeap (), 0, self->parts);
542 self->parts = tmp;
545 for (i = 0; i < self->numParts; i++) {
546 self->parts[i].x = parts[i];
549 if (self->hwndToolTip) {
550 INT32 nTipCount =
551 SendMessage32A (self->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
553 if (nTipCount < self->numParts) {
554 /* add tools */
555 TTTOOLINFO32A ti;
556 INT32 i;
558 ZeroMemory (&ti, sizeof(TTTOOLINFO32A));
559 ti.cbSize = sizeof(TTTOOLINFO32A);
560 ti.hwnd = wndPtr->hwndSelf;
561 for (i = nTipCount; i < self->numParts; i++) {
562 TRACE (statusbar, "add tool %d\n", i);
563 ti.uId = i;
564 SendMessage32A (self->hwndToolTip, TTM_ADDTOOL32A,
565 0, (LPARAM)&ti);
568 else if (nTipCount > self->numParts) {
569 /* delete tools */
570 INT32 i;
572 for (i = nTipCount - 1; i >= self->numParts; i--) {
574 TRACE (statusbar, "delete tool %d\n", i);
580 STATUSBAR_SetPartBounds (wndPtr);
582 hdc = GetDC32 (wndPtr->hwndSelf);
583 STATUSBAR_Refresh (wndPtr, hdc);
584 ReleaseDC32 (wndPtr->hwndSelf, hdc);
586 return TRUE;
590 static LRESULT
591 STATUSBAR_SetText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
593 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
594 STATUSWINDOWPART *part;
595 int part_num;
596 int style;
597 LPSTR text;
598 int len;
599 HDC32 hdc;
601 text = (LPSTR) lParam;
602 part_num = ((INT32) wParam) & 0x00ff;
603 style = ((INT32) wParam) & 0xff00;
605 if ((self->simple) || (self->parts==NULL) || (part_num==255))
606 part = &self->part0;
607 else
608 part = &self->parts[part_num];
609 if (!part) return FALSE;
610 part->style = style;
611 if (style == SBT_OWNERDRAW) {
612 part->text = text;
614 else {
615 /* duplicate string */
616 if (part->text)
617 HeapFree (GetProcessHeap (), 0, part->text);
618 part->text = 0;
619 if (text && (len = lstrlen32A(text))) {
620 part->text = HeapAlloc (GetProcessHeap (), 0, len+1);
621 lstrcpy32A(part->text, text);
625 hdc = GetDC32 (wndPtr->hwndSelf);
626 STATUSBAR_RefreshPart (wndPtr, part, hdc);
627 ReleaseDC32 (wndPtr->hwndSelf, hdc);
629 return TRUE;
633 // << STATUSBAR_SetText32W >>
636 static LRESULT
637 STATUSBAR_SetTipText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
639 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
640 TTTOOLINFO32A ti;
642 TRACE (statusbar, "part %d: \"%s\"\n", (INT32)wParam, (LPSTR)lParam);
643 if (self->hwndToolTip) {
644 ti.cbSize = sizeof(TTTOOLINFO32A);
645 ti.hwnd = wndPtr->hwndSelf;
646 ti.uId = (INT32)wParam;
647 ti.hinst = 0;
648 ti.lpszText = (LPSTR)lParam;
649 SendMessage32A (self->hwndToolTip, TTM_UPDATETIPTEXT32A,
650 0, (LPARAM)&ti);
653 return 0;
657 // << STATUSBAR_SetTipText32W >>
658 // << STATUSBAR_SetUnicodeFormat >>
661 static LRESULT
662 STATUSBAR_Simple (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
664 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
665 BOOL32 simple;
666 HDC32 hdc;
667 NMHDR nmhdr;
669 simple = (BOOL32) wParam;
670 self->simple = simple;
672 /* send notification */
673 nmhdr.hwndFrom = wndPtr->hwndSelf;
674 nmhdr.idFrom = wndPtr->wIDmenu;
675 nmhdr.code = SBN_SIMPLEMODECHANGE;
676 SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
677 0, (LPARAM)&nmhdr);
679 hdc = GetDC32 (wndPtr->hwndSelf);
680 STATUSBAR_Refresh (wndPtr, hdc);
681 ReleaseDC32 (wndPtr->hwndSelf, hdc);
683 return TRUE;
687 static LRESULT
688 STATUSBAR_WMCreate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
690 LPCREATESTRUCT32A lpCreate = (LPCREATESTRUCT32A) lParam;
691 NONCLIENTMETRICS32A nclm;
692 RECT32 rect;
693 int width, len;
694 HDC32 hdc;
695 STATUSWINDOWINFO *self;
697 self = (STATUSWINDOWINFO*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
698 sizeof(STATUSWINDOWINFO));
699 wndPtr->wExtra[0] = (DWORD)self;
701 self->numParts = 1;
702 self->parts = 0;
703 self->simple = FALSE;
704 self->clrBk = CLR_DEFAULT;
705 self->hFont = 0;
706 GetClientRect32 (wndPtr->hwndSelf, &rect);
708 nclm.cbSize = sizeof(NONCLIENTMETRICS32A);
709 SystemParametersInfo32A (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
710 self->hDefaultFont = CreateFontIndirect32A (&nclm.lfStatusFont);
712 /* initialize simple case */
713 self->part0.bound = rect;
714 self->part0.text = 0;
715 self->part0.x = 0;
716 self->part0.style = 0;
717 self->part0.hIcon = 0;
719 /* initialize first part */
720 self->parts = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
721 sizeof(STATUSWINDOWPART));
722 self->parts[0].bound = rect;
723 self->parts[0].text = 0;
724 self->parts[0].x = -1;
725 self->parts[0].style = 0;
726 self->parts[0].hIcon = 0;
728 if ((len = lstrlen32A (lpCreate->lpszName))) {
729 self->parts[0].text = HeapAlloc (GetProcessHeap (), 0, len + 1);
730 lstrcpy32A (self->parts[0].text, lpCreate->lpszName);
733 if ((hdc = GetDC32 (0))) {
734 TEXTMETRIC32A tm;
735 HFONT32 hOldFont;
737 hOldFont = SelectObject32 (hdc,self->hDefaultFont);
738 GetTextMetrics32A(hdc, &tm);
739 self->textHeight = tm.tmHeight;
740 SelectObject32 (hdc, hOldFont);
741 ReleaseDC32(0, hdc);
744 if (wndPtr->dwStyle & SBT_TOOLTIPS) {
745 self->hwndToolTip =
746 CreateWindowEx32A (0, TOOLTIPS_CLASS32A, NULL, 0,
747 CW_USEDEFAULT32, CW_USEDEFAULT32,
748 CW_USEDEFAULT32, CW_USEDEFAULT32,
749 wndPtr->hwndSelf, 0,
750 wndPtr->hInstance, NULL);
752 if (self->hwndToolTip) {
753 NMTOOLTIPSCREATED nmttc;
755 nmttc.hdr.hwndFrom = wndPtr->hwndSelf;
756 nmttc.hdr.idFrom = wndPtr->wIDmenu;
757 nmttc.hdr.code = NM_TOOLTIPSCREATED;
758 nmttc.hwndToolTips = self->hwndToolTip;
760 SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
761 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmttc);
765 GetClientRect32 (GetParent32 (wndPtr->hwndSelf), &rect);
766 width = rect.right - rect.left;
767 self->height = self->textHeight + 4 + VERT_BORDER;
768 MoveWindow32 (wndPtr->hwndSelf, lpCreate->x, lpCreate->y-1,
769 width, self->height, FALSE);
770 STATUSBAR_SetPartBounds (wndPtr);
772 return 0;
776 static LRESULT
777 STATUSBAR_WMDestroy (WND *wndPtr)
779 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
780 int i;
782 for (i = 0; i < self->numParts; i++) {
783 if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
784 HeapFree(GetProcessHeap (), 0, self->parts[i].text);
786 if (self->part0.text && (self->part0.style != SBT_OWNERDRAW))
787 HeapFree(GetProcessHeap (), 0, self->part0.text);
788 HeapFree(GetProcessHeap (), 0, self->parts);
790 /* delete default font */
791 if (self->hDefaultFont)
792 DeleteObject32 (self->hDefaultFont);
794 /* delete tool tip control */
795 if (self->hwndToolTip)
796 DestroyWindow32 (self->hwndToolTip);
798 HeapFree(GetProcessHeap (), 0, self);
800 return 0;
804 static __inline__ LRESULT
805 STATUSBAR_WMGetFont (WND *wndPtr)
807 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
809 return self->hFont;
813 static LRESULT
814 STATUSBAR_WMGetText (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
816 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
817 INT32 len;
819 if (!(self->parts[0].text))
820 return 0;
821 len = lstrlen32A (self->parts[0].text);
822 if (wParam > len) {
823 lstrcpy32A ((LPSTR)lParam, self->parts[0].text);
824 return len;
826 else
827 return -1;
831 static LRESULT
832 STATUSBAR_WMGetTextLength (WND *wndPtr)
834 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
836 if (!(self->parts[0].text))
837 return 0;
839 return (lstrlen32A (self->parts[0].text));
843 __inline__ static LRESULT
844 STATUSBAR_WMMouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
846 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
848 if (self->hwndToolTip)
849 STATUSBAR_RelayEvent (self->hwndToolTip, wndPtr->hwndSelf,
850 WM_MOUSEMOVE, wParam, lParam);
851 return 0;
855 static LRESULT
856 STATUSBAR_WMNCHitTest (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
858 if (wndPtr->dwStyle & SBARS_SIZEGRIP) {
859 RECT32 rect;
860 POINT32 pt;
862 GetClientRect32 (wndPtr->hwndSelf, &rect);
864 pt.x = (INT32)LOWORD(lParam);
865 pt.y = (INT32)HIWORD(lParam);
866 ScreenToClient32 (wndPtr->hwndSelf, &pt);
868 rect.left = rect.right - 13;
869 rect.top += 2;
871 if (PtInRect32 (&rect, pt))
872 return HTBOTTOMRIGHT;
875 return DefWindowProc32A (wndPtr->hwndSelf, WM_NCHITTEST, wParam, lParam);
879 static __inline__ LRESULT
880 STATUSBAR_WMNCLButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
882 PostMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NCLBUTTONDOWN,
883 wParam, lParam);
884 return 0;
888 static __inline__ LRESULT
889 STATUSBAR_WMNCLButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
891 PostMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NCLBUTTONUP,
892 wParam, lParam);
893 return 0;
897 static LRESULT
898 STATUSBAR_WMPaint (WND *wndPtr, WPARAM32 wParam)
900 HDC32 hdc;
901 PAINTSTRUCT32 ps;
903 hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
904 STATUSBAR_Refresh (wndPtr, hdc);
905 if (!wParam)
906 EndPaint32 (wndPtr->hwndSelf, &ps);
908 return 0;
912 static LRESULT
913 STATUSBAR_WMSetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
915 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
917 self->hFont = (HFONT32)wParam;
918 if (LOWORD(lParam) == TRUE) {
919 HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
920 STATUSBAR_Refresh (wndPtr, hdc);
921 ReleaseDC32 (wndPtr->hwndSelf, hdc);
924 return 0;
928 static LRESULT
929 STATUSBAR_WMSetText (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
931 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
932 STATUSWINDOWPART *part;
933 int len;
934 HDC32 hdc;
936 if (self->numParts == 0)
937 return FALSE;
939 part = &self->parts[0];
940 /* duplicate string */
941 if (part->text)
942 HeapFree(GetProcessHeap (), 0, part->text);
943 part->text = 0;
944 if (lParam && (len = lstrlen32A((LPCSTR)lParam))) {
945 part->text = HeapAlloc (GetProcessHeap (), 0, len+1);
946 lstrcpy32A (part->text, (LPCSTR)lParam);
949 hdc = GetDC32 (wndPtr->hwndSelf);
950 STATUSBAR_RefreshPart (wndPtr, part, hdc);
951 ReleaseDC32 (wndPtr->hwndSelf, hdc);
953 return TRUE;
957 static LRESULT
958 STATUSBAR_WMSize (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
960 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
961 INT32 width, x, y, flags;
962 RECT32 parent_rect;
963 HWND32 parent;
965 /* Need to resize width to match parent */
966 flags = (INT32) wParam;
968 /* FIXME for flags =
969 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
972 if (flags == SIZE_RESTORED) {
973 /* width and height don't apply */
974 parent = GetParent32 (wndPtr->hwndSelf);
975 GetClientRect32 (parent, &parent_rect);
976 width = parent_rect.right - parent_rect.left;
977 x = parent_rect.left;
978 y = parent_rect.bottom - self->height;
979 MoveWindow32 (wndPtr->hwndSelf, parent_rect.left,
980 parent_rect.bottom - self->height,
981 width, self->height, TRUE);
982 STATUSBAR_SetPartBounds (wndPtr);
984 return 0;
988 static LRESULT
989 STATUSBAR_SendNotify (WND *wndPtr, UINT32 code)
991 NMHDR nmhdr;
993 nmhdr.hwndFrom = wndPtr->hwndSelf;
994 nmhdr.idFrom = wndPtr->wIDmenu;
995 nmhdr.code = code;
996 SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
997 0, (LPARAM)&nmhdr);
998 return 0;
1003 LRESULT WINAPI
1004 StatusWindowProc (HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
1006 WND *wndPtr = WIN_FindWndPtr (hwnd);
1008 switch (msg) {
1009 case SB_GETBORDERS:
1010 return STATUSBAR_GetBorders (lParam);
1012 case SB_GETICON:
1013 return STATUSBAR_GetIcon (wndPtr, wParam);
1015 case SB_GETPARTS:
1016 return STATUSBAR_GetParts (wndPtr, wParam, lParam);
1018 case SB_GETRECT:
1019 return STATUSBAR_GetRect (wndPtr, wParam, lParam);
1021 case SB_GETTEXT32A:
1022 return STATUSBAR_GetText32A (wndPtr, wParam, lParam);
1024 // case SB_GETTEXT32W:
1026 case SB_GETTEXTLENGTH32A:
1027 return STATUSBAR_GetTextLength32A (wndPtr, wParam, lParam);
1029 // case SB_GETTEXTLENGHT32W:
1031 case SB_GETTIPTEXT32A:
1032 return STATUSBAR_GetTipText32A (wndPtr, wParam, lParam);
1034 // case SB_GETTIPTEXT32W:
1035 // case SB_GETUNICODEFORMAT:
1037 case SB_ISSIMPLE:
1038 return STATUSBAR_IsSimple (wndPtr);
1040 case SB_SETBKCOLOR:
1041 return STATUSBAR_SetBkColor (wndPtr, wParam, lParam);
1043 case SB_SETICON:
1044 return STATUSBAR_SetIcon (wndPtr, wParam, lParam);
1046 case SB_SETMINHEIGHT:
1047 return STATUSBAR_SetMinHeight (wndPtr, wParam, lParam);
1049 case SB_SETPARTS:
1050 return STATUSBAR_SetParts (wndPtr, wParam, lParam);
1052 case SB_SETTEXT32A:
1053 return STATUSBAR_SetText32A (wndPtr, wParam, lParam);
1055 // case SB_SETTEXT32W:
1057 case SB_SETTIPTEXT32A:
1058 return STATUSBAR_SetTipText32A (wndPtr, wParam, lParam);
1060 // case SB_SETTIPTEXT32W:
1061 // case SB_SETUNICODEFORMAT:
1063 case SB_SIMPLE:
1064 return STATUSBAR_Simple (wndPtr, wParam, lParam);
1067 case WM_CREATE:
1068 return STATUSBAR_WMCreate (wndPtr, wParam, lParam);
1070 case WM_DESTROY:
1071 return STATUSBAR_WMDestroy (wndPtr);
1073 case WM_GETFONT:
1074 return STATUSBAR_WMGetFont (wndPtr);
1076 case WM_GETTEXT:
1077 return STATUSBAR_WMGetText (wndPtr, wParam, lParam);
1079 case WM_GETTEXTLENGTH:
1080 return STATUSBAR_WMGetTextLength (wndPtr);
1082 case WM_LBUTTONDBLCLK:
1083 return STATUSBAR_SendNotify (wndPtr, NM_DBLCLK);
1085 case WM_LBUTTONUP:
1086 return STATUSBAR_SendNotify (wndPtr, NM_CLICK);
1088 case WM_MOUSEMOVE:
1089 return STATUSBAR_WMMouseMove (wndPtr, wParam, lParam);
1091 case WM_NCHITTEST:
1092 return STATUSBAR_WMNCHitTest (wndPtr, wParam, lParam);
1094 case WM_NCLBUTTONDOWN:
1095 return STATUSBAR_WMNCLButtonDown (wndPtr, wParam, lParam);
1097 case WM_NCLBUTTONUP:
1098 return STATUSBAR_WMNCLButtonUp (wndPtr, wParam, lParam);
1100 case WM_PAINT:
1101 return STATUSBAR_WMPaint (wndPtr, wParam);
1103 case WM_RBUTTONDBLCLK:
1104 return STATUSBAR_SendNotify (wndPtr, NM_RDBLCLK);
1106 case WM_RBUTTONUP:
1107 return STATUSBAR_SendNotify (wndPtr, NM_RCLICK);
1109 case WM_SETFONT:
1110 return STATUSBAR_WMSetFont (wndPtr, wParam, lParam);
1112 case WM_SETTEXT:
1113 return STATUSBAR_WMSetText (wndPtr, wParam, lParam);
1115 case WM_SIZE:
1116 return STATUSBAR_WMSize (wndPtr, wParam, lParam);
1118 default:
1119 if (msg >= WM_USER)
1120 ERR (statusbar, "unknown msg %04x wp=%04x lp=%08lx\n",
1121 msg, wParam, lParam);
1122 return DefWindowProc32A (hwnd, msg, wParam, lParam);
1124 return 0;
1128 /***********************************************************************
1129 * STATUS_Register [Internal]
1131 * Registers the status window class.
1133 void STATUS_Register (void)
1135 WNDCLASS32A wndClass;
1137 if (GlobalFindAtom32A (STATUSCLASSNAME32A)) return;
1139 ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
1140 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1141 wndClass.lpfnWndProc = (WNDPROC32)StatusWindowProc;
1142 wndClass.cbClsExtra = 0;
1143 wndClass.cbWndExtra = sizeof(STATUSWINDOWINFO *);
1144 wndClass.hCursor = LoadCursor32A (0, IDC_ARROW32A);
1145 wndClass.hbrBackground = (HBRUSH32)(COLOR_3DFACE + 1);
1146 wndClass.lpszClassName = STATUSCLASSNAME32A;
1148 RegisterClass32A (&wndClass);