Fixed a silly VGA-emulation palette bug.
[wine/multimedia.git] / dlls / comctl32 / status.c
blob3677d08441a727d09ca0a54798e61a7a3ba75aca
1 /*
2 * Interface code to StatusWindow widget/control
4 * Copyright 1996 Bruce Milner
5 * Copyright 1998, 1999 Eric Kohl
6 */
8 #include "commctrl.h"
9 #include "status.h"
10 #include "win.h"
11 #include "debug.h"
14 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
15 * The second cdrom contains executables drawstat.exe,gettext.exe,
16 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
20 * Fixme/Todo
21 * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
22 * 2) Tooltip support (almost done).
25 #define _MAX(a,b) (((a)>(b))?(a):(b))
26 #define _MIN(a,b) (((a)>(b))?(b):(a))
28 #define HORZ_BORDER 0
29 #define VERT_BORDER 2
30 #define HORZ_GAP 2
32 #define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
35 static void
36 STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
38 HPEN hOldPen;
39 POINT pt;
40 INT i;
42 pt.x = lpRect->right - 1;
43 pt.y = lpRect->bottom - 1;
45 hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
46 MoveToEx (hdc, pt.x - 12, pt.y, NULL);
47 LineTo (hdc, pt.x, pt.y);
48 LineTo (hdc, pt.x, pt.y - 12);
50 pt.x--;
51 pt.y--;
53 SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
54 for (i = 1; i < 11; i += 4) {
55 MoveToEx (hdc, pt.x - i, pt.y, NULL);
56 LineTo (hdc, pt.x, pt.y - i);
58 MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
59 LineTo (hdc, pt.x, pt.y - i-1);
62 SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
63 for (i = 3; i < 13; i += 4) {
64 MoveToEx (hdc, pt.x - i, pt.y, NULL);
65 LineTo (hdc, pt.x, pt.y - i);
68 SelectObject (hdc, hOldPen);
72 static void
73 STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
75 RECT r = part->bound;
76 UINT border = BDR_SUNKENOUTER;
78 if (part->style==SBT_POPOUT)
79 border = BDR_RAISEDOUTER;
80 else if (part->style==SBT_NOBORDERS)
81 border = 0;
83 DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
85 /* draw the icon */
86 if (part->hIcon) {
87 INT cy = r.bottom - r.top;
89 r.left += 2;
90 DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
91 r.left += cy;
94 /* now draw text */
95 if (part->text) {
96 int oldbkmode = SetBkMode(hdc, TRANSPARENT);
97 LPWSTR p = (LPWSTR)part->text;
98 UINT align = DT_LEFT;
99 if (*p == L'\t') {
100 p++;
101 align = DT_CENTER;
103 if (*p == L'\t') {
104 p++;
105 align = DT_RIGHT;
108 r.left += 3;
109 DrawTextW (hdc, p, lstrlenW (p), &r, align|DT_VCENTER|DT_SINGLELINE);
110 if (oldbkmode != TRANSPARENT)
111 SetBkMode(hdc, oldbkmode);
116 static VOID
117 STATUSBAR_RefreshPart (HWND hwnd, STATUSWINDOWPART *part, HDC hdc)
119 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
120 HBRUSH hbrBk;
121 HFONT hOldFont;
123 if (!IsWindowVisible (hwnd))
124 return;
126 if (self->clrBk != CLR_DEFAULT)
127 hbrBk = CreateSolidBrush (self->clrBk);
128 else
129 hbrBk = GetSysColorBrush (COLOR_3DFACE);
130 FillRect(hdc, &part->bound, hbrBk);
132 hOldFont = SelectObject (hdc, self->hFont ? self->hFont : self->hDefaultFont);
134 if (part->style == SBT_OWNERDRAW) {
135 DRAWITEMSTRUCT dis;
137 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
138 dis.itemID = -1;
139 dis.hwndItem = hwnd;
140 dis.hDC = hdc;
141 dis.rcItem = part->bound;
142 dis.itemData = (INT)part->text;
143 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
144 (WPARAM)dis.CtlID, (LPARAM)&dis);
146 else
147 STATUSBAR_DrawPart (hdc, part);
149 SelectObject (hdc, hOldFont);
151 if (self->clrBk != CLR_DEFAULT)
152 DeleteObject (hbrBk);
154 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
155 RECT rect;
157 GetClientRect (hwnd, &rect);
158 STATUSBAR_DrawSizeGrip (hdc, &rect);
163 static BOOL
164 STATUSBAR_Refresh (HWND hwnd, HDC hdc)
166 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
167 int i;
168 RECT rect;
169 HBRUSH hbrBk;
170 HFONT hOldFont;
172 if (!IsWindowVisible(hwnd))
173 return (TRUE);
175 GetClientRect (hwnd, &rect);
177 if (infoPtr->clrBk != CLR_DEFAULT)
178 hbrBk = CreateSolidBrush (infoPtr->clrBk);
179 else
180 hbrBk = GetSysColorBrush (COLOR_3DFACE);
181 FillRect(hdc, &rect, hbrBk);
183 hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
185 if (infoPtr->simple) {
186 STATUSBAR_DrawPart (hdc, &infoPtr->part0);
188 else {
189 for (i = 0; i < infoPtr->numParts; i++) {
190 if (infoPtr->parts[i].style == SBT_OWNERDRAW) {
191 DRAWITEMSTRUCT dis;
193 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
194 dis.itemID = -1;
195 dis.hwndItem = hwnd;
196 dis.hDC = hdc;
197 dis.rcItem = infoPtr->parts[i].bound;
198 dis.itemData = (INT)infoPtr->parts[i].text;
199 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
200 (WPARAM)dis.CtlID, (LPARAM)&dis);
202 else
203 STATUSBAR_DrawPart (hdc, &infoPtr->parts[i]);
207 SelectObject (hdc, hOldFont);
209 if (infoPtr->clrBk != CLR_DEFAULT)
210 DeleteObject (hbrBk);
212 if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
213 STATUSBAR_DrawSizeGrip (hdc, &rect);
215 return TRUE;
219 static void
220 STATUSBAR_SetPartBounds (HWND hwnd)
222 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
223 STATUSWINDOWPART *part;
224 RECT rect, *r;
225 int i;
227 /* get our window size */
228 GetClientRect (hwnd, &rect);
230 rect.top += VERT_BORDER;
232 /* set bounds for simple rectangle */
233 self->part0.bound = rect;
235 /* set bounds for non-simple rectangles */
236 for (i = 0; i < self->numParts; i++) {
237 part = &self->parts[i];
238 r = &self->parts[i].bound;
239 r->top = rect.top;
240 r->bottom = rect.bottom;
241 if (i == 0)
242 r->left = 0;
243 else
244 r->left = self->parts[i-1].bound.right + HORZ_GAP;
245 if (part->x == -1)
246 r->right = rect.right;
247 else
248 r->right = part->x;
250 if (self->hwndToolTip) {
251 TTTOOLINFOA ti;
253 ti.cbSize = sizeof(TTTOOLINFOA);
254 ti.hwnd = hwnd;
255 ti.uId = i;
256 ti.rect = *r;
257 SendMessageA (self->hwndToolTip, TTM_NEWTOOLRECTA,
258 0, (LPARAM)&ti);
264 static VOID
265 STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
266 WPARAM wParam, LPARAM lParam)
268 MSG msg;
270 msg.hwnd = hwndMsg;
271 msg.message = uMsg;
272 msg.wParam = wParam;
273 msg.lParam = lParam;
274 msg.time = GetMessageTime ();
275 msg.pt.x = LOWORD(GetMessagePos ());
276 msg.pt.y = HIWORD(GetMessagePos ());
278 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
282 __inline__ static LRESULT
283 STATUSBAR_GetBorders (LPARAM lParam)
285 LPINT out = (LPINT) lParam;
287 out[0] = HORZ_BORDER; /* horizontal border width */
288 out[1] = VERT_BORDER; /* vertical border width */
289 out[2] = HORZ_GAP; /* width of border between rectangles */
291 return TRUE;
295 static LRESULT
296 STATUSBAR_GetIcon (HWND hwnd, WPARAM wParam)
298 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
299 INT nPart;
301 nPart = (INT)wParam & 0x00ff;
302 if ((nPart < -1) || (nPart >= self->numParts))
303 return 0;
305 if (nPart == -1)
306 return (self->part0.hIcon);
307 else
308 return (self->parts[nPart].hIcon);
312 static LRESULT
313 STATUSBAR_GetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
315 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
316 LPINT parts;
317 INT num_parts;
318 INT i;
320 num_parts = (INT) wParam;
321 parts = (LPINT) lParam;
322 if (parts) {
323 return (infoPtr->numParts);
324 for (i = 0; i < num_parts; i++) {
325 parts[i] = infoPtr->parts[i].x;
328 return (infoPtr->numParts);
332 static LRESULT
333 STATUSBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
335 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
336 int part_num;
337 LPRECT rect;
339 part_num = ((INT) wParam) & 0x00ff;
340 rect = (LPRECT) lParam;
341 if (infoPtr->simple)
342 *rect = infoPtr->part0.bound;
343 else
344 *rect = infoPtr->parts[part_num].bound;
345 return TRUE;
349 static LRESULT
350 STATUSBAR_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
352 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
353 STATUSWINDOWPART *part;
354 INT nPart;
355 LRESULT result;
357 nPart = ((INT) wParam) & 0x00ff;
358 if (self->simple)
359 part = &self->part0;
360 else
361 part = &self->parts[nPart];
363 if (part->style == SBT_OWNERDRAW)
364 result = (LRESULT)part->text;
365 else {
366 result = part->text ? lstrlenW (part->text) : 0;
367 result |= (part->style << 16);
368 if (lParam && LOWORD(result))
369 lstrcpyWtoA ((LPSTR)lParam, part->text);
371 return result;
375 static LRESULT
376 STATUSBAR_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
378 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
379 STATUSWINDOWPART *part;
380 INT nPart;
381 LRESULT result;
383 nPart = ((INT)wParam) & 0x00ff;
384 if (infoPtr->simple)
385 part = &infoPtr->part0;
386 else
387 part = &infoPtr->parts[nPart];
389 if (part->style == SBT_OWNERDRAW)
390 result = (LRESULT)part->text;
391 else {
392 result = part->text ? lstrlenW (part->text) : 0;
393 result |= (part->style << 16);
394 if (lParam)
395 lstrcpyW ((LPWSTR)lParam, part->text);
397 return result;
401 static LRESULT
402 STATUSBAR_GetTextLength (HWND hwnd, WPARAM wParam)
404 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
405 STATUSWINDOWPART *part;
406 INT part_num;
407 DWORD result;
409 part_num = ((INT) wParam) & 0x00ff;
411 if (infoPtr->simple)
412 part = &infoPtr->part0;
413 else
414 part = &infoPtr->parts[part_num];
416 if (part->text)
417 result = lstrlenW(part->text);
418 else
419 result = 0;
421 result |= (part->style << 16);
422 return result;
426 static LRESULT
427 STATUSBAR_GetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
429 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
431 if (infoPtr->hwndToolTip) {
432 TTTOOLINFOA ti;
433 ti.cbSize = sizeof(TTTOOLINFOA);
434 ti.hwnd = hwnd;
435 ti.uId = LOWORD(wParam);
436 SendMessageA (infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
438 if (ti.lpszText)
439 lstrcpynA ((LPSTR)lParam, ti.lpszText, HIWORD(wParam));
442 return 0;
446 static LRESULT
447 STATUSBAR_GetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
449 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
451 if (infoPtr->hwndToolTip) {
452 TTTOOLINFOW ti;
453 ti.cbSize = sizeof(TTTOOLINFOW);
454 ti.hwnd = hwnd;
455 ti.uId = LOWORD(wParam);
456 SendMessageW (infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
458 if (ti.lpszText)
459 lstrcpynW ((LPWSTR)lParam, ti.lpszText, HIWORD(wParam));
462 return 0;
466 __inline__ static LRESULT
467 STATUSBAR_GetUnicodeFormat (HWND hwnd)
469 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
470 return infoPtr->bUnicode;
474 __inline__ static LRESULT
475 STATUSBAR_IsSimple (HWND hwnd)
477 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
478 return infoPtr->simple;
482 static LRESULT
483 STATUSBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
485 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
486 COLORREF oldBkColor;
487 HDC hdc;
489 oldBkColor = self->clrBk;
490 self->clrBk = (COLORREF)lParam;
491 hdc = GetDC (hwnd);
492 STATUSBAR_Refresh (hwnd, hdc);
493 ReleaseDC (hwnd, hdc);
495 return oldBkColor;
499 static LRESULT
500 STATUSBAR_SetIcon (HWND hwnd, WPARAM wParam, LPARAM lParam)
502 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
503 INT nPart = (INT)wParam & 0x00ff;
504 HDC hdc;
506 if ((nPart < -1) || (nPart >= self->numParts))
507 return FALSE;
509 hdc = GetDC (hwnd);
510 if (nPart == -1) {
511 self->part0.hIcon = (HICON)lParam;
512 if (self->simple)
513 STATUSBAR_RefreshPart (hwnd, &self->part0, hdc);
515 else {
516 self->parts[nPart].hIcon = (HICON)lParam;
517 if (!(self->simple))
518 STATUSBAR_RefreshPart (hwnd, &self->parts[nPart], hdc);
520 ReleaseDC (hwnd, hdc);
522 return TRUE;
526 static LRESULT
527 STATUSBAR_SetMinHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
529 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
531 if (IsWindowVisible (hwnd)) {
532 HWND parent = GetParent (hwnd);
533 INT width, x, y;
534 RECT parent_rect;
536 GetClientRect (parent, &parent_rect);
537 self->height = (INT)wParam + VERT_BORDER;
538 width = parent_rect.right - parent_rect.left;
539 x = parent_rect.left;
540 y = parent_rect.bottom - self->height;
541 MoveWindow (hwnd, parent_rect.left,
542 parent_rect.bottom - self->height,
543 width, self->height, TRUE);
544 STATUSBAR_SetPartBounds (hwnd);
547 return TRUE;
551 static LRESULT
552 STATUSBAR_SetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
554 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
555 STATUSWINDOWPART *tmp;
556 HDC hdc;
557 LPINT parts;
558 int i;
559 int oldNumParts;
561 if (self->simple)
562 self->simple = FALSE;
564 oldNumParts = self->numParts;
565 self->numParts = (INT) wParam;
566 parts = (LPINT) lParam;
567 if (oldNumParts > self->numParts) {
568 for (i = self->numParts ; i < oldNumParts; i++) {
569 if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
570 COMCTL32_Free (self->parts[i].text);
573 else if (oldNumParts < self->numParts) {
574 tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
575 for (i = 0; i < oldNumParts; i++) {
576 tmp[i] = self->parts[i];
578 if (self->parts)
579 COMCTL32_Free (self->parts);
580 self->parts = tmp;
583 for (i = 0; i < self->numParts; i++) {
584 self->parts[i].x = parts[i];
587 if (self->hwndToolTip) {
588 INT nTipCount =
589 SendMessageA (self->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
591 if (nTipCount < self->numParts) {
592 /* add tools */
593 TTTOOLINFOA ti;
594 INT i;
596 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
597 ti.cbSize = sizeof(TTTOOLINFOA);
598 ti.hwnd = hwnd;
599 for (i = nTipCount; i < self->numParts; i++) {
600 TRACE (statusbar, "add tool %d\n", i);
601 ti.uId = i;
602 SendMessageA (self->hwndToolTip, TTM_ADDTOOLA,
603 0, (LPARAM)&ti);
606 else if (nTipCount > self->numParts) {
607 /* delete tools */
608 INT i;
610 for (i = nTipCount - 1; i >= self->numParts; i--) {
612 FIXME (statusbar, "delete tool %d\n", i);
618 STATUSBAR_SetPartBounds (hwnd);
620 hdc = GetDC (hwnd);
621 STATUSBAR_Refresh (hwnd, hdc);
622 ReleaseDC (hwnd, hdc);
624 return TRUE;
628 static LRESULT
629 STATUSBAR_SetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
631 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
632 STATUSWINDOWPART *part;
633 int part_num;
634 int style;
635 LPSTR text;
636 int len;
637 HDC hdc;
639 text = (LPSTR) lParam;
640 part_num = ((INT) wParam) & 0x00ff;
641 style = ((INT) wParam) & 0xff00;
643 if ((self->simple) || (self->parts==NULL) || (part_num==255))
644 part = &self->part0;
645 else
646 part = &self->parts[part_num];
647 if (!part) return FALSE;
648 part->style = style;
649 if (style == SBT_OWNERDRAW) {
650 part->text = (LPWSTR)text;
652 else {
653 /* duplicate string */
654 if (part->text)
655 COMCTL32_Free (part->text);
656 part->text = 0;
657 if (text && (len = lstrlenA(text))) {
658 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
659 lstrcpyAtoW (part->text, text);
663 hdc = GetDC (hwnd);
664 STATUSBAR_RefreshPart (hwnd, part, hdc);
665 ReleaseDC (hwnd, hdc);
667 return TRUE;
671 static LRESULT
672 STATUSBAR_SetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
674 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
675 STATUSWINDOWPART *part;
676 INT part_num, style, len;
677 LPWSTR text;
678 HDC hdc;
680 text = (LPWSTR) lParam;
681 part_num = ((INT) wParam) & 0x00ff;
682 style = ((INT) wParam) & 0xff00;
684 if ((self->simple) || (self->parts==NULL) || (part_num==255))
685 part = &self->part0;
686 else
687 part = &self->parts[part_num];
688 if (!part) return FALSE;
689 part->style = style;
690 if (style == SBT_OWNERDRAW) {
691 part->text = text;
693 else {
694 /* duplicate string */
695 if (part->text)
696 COMCTL32_Free (part->text);
697 part->text = 0;
698 if (text && (len = lstrlenW(text))) {
699 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
700 lstrcpyW(part->text, text);
704 hdc = GetDC (hwnd);
705 STATUSBAR_RefreshPart (hwnd, part, hdc);
706 ReleaseDC (hwnd, hdc);
708 return TRUE;
712 static LRESULT
713 STATUSBAR_SetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
715 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
717 TRACE (statusbar, "part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
718 if (infoPtr->hwndToolTip) {
719 TTTOOLINFOA ti;
720 ti.cbSize = sizeof(TTTOOLINFOA);
721 ti.hwnd = hwnd;
722 ti.uId = (INT)wParam;
723 ti.hinst = 0;
724 ti.lpszText = (LPSTR)lParam;
725 SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
726 0, (LPARAM)&ti);
729 return 0;
733 static LRESULT
734 STATUSBAR_SetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
736 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
738 TRACE (statusbar, "part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
739 if (infoPtr->hwndToolTip) {
740 TTTOOLINFOW ti;
741 ti.cbSize = sizeof(TTTOOLINFOW);
742 ti.hwnd = hwnd;
743 ti.uId = (INT)wParam;
744 ti.hinst = 0;
745 ti.lpszText = (LPWSTR)lParam;
746 SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW,
747 0, (LPARAM)&ti);
750 return 0;
754 __inline__ static LRESULT
755 STATUSBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
757 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
758 BOOL bTemp = infoPtr->bUnicode;
760 TRACE (statusbar, "(0x%x)\n", (BOOL)wParam);
761 infoPtr->bUnicode = (BOOL)wParam;
763 return bTemp;
767 static LRESULT
768 STATUSBAR_Simple (HWND hwnd, WPARAM wParam, LPARAM lParam)
770 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
771 HDC hdc;
772 NMHDR nmhdr;
774 infoPtr->simple = (BOOL)wParam;
776 /* send notification */
777 nmhdr.hwndFrom = hwnd;
778 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
779 nmhdr.code = SBN_SIMPLEMODECHANGE;
780 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
782 hdc = GetDC (hwnd);
783 STATUSBAR_Refresh (hwnd, hdc);
784 ReleaseDC (hwnd, hdc);
786 return TRUE;
790 static LRESULT
791 STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
793 LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
794 NONCLIENTMETRICSA nclm;
795 RECT rect;
796 int width, len;
797 HDC hdc;
798 STATUSWINDOWINFO *self;
800 self = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
801 SetWindowLongA (hwnd, 0, (DWORD)self);
803 self->numParts = 1;
804 self->parts = 0;
805 self->simple = FALSE;
806 self->clrBk = CLR_DEFAULT;
807 self->hFont = 0;
808 GetClientRect (hwnd, &rect);
810 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
811 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
812 self->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
814 /* initialize simple case */
815 self->part0.bound = rect;
816 self->part0.text = 0;
817 self->part0.x = 0;
818 self->part0.style = 0;
819 self->part0.hIcon = 0;
821 /* initialize first part */
822 self->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
823 self->parts[0].bound = rect;
824 self->parts[0].text = 0;
825 self->parts[0].x = -1;
826 self->parts[0].style = 0;
827 self->parts[0].hIcon = 0;
829 if (IsWindowUnicode (hwnd)) {
830 self->bUnicode = TRUE;
831 if ((len = lstrlenW ((LPCWSTR)lpCreate->lpszName))) {
832 self->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
833 lstrcpyW (self->parts[0].text, (LPCWSTR)lpCreate->lpszName);
836 else {
837 if ((len = lstrlenA ((LPCSTR)lpCreate->lpszName))) {
838 self->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
839 lstrcpyAtoW (self->parts[0].text, (LPCSTR)lpCreate->lpszName);
843 if ((hdc = GetDC (0))) {
844 TEXTMETRICA tm;
845 HFONT hOldFont;
847 hOldFont = SelectObject (hdc,self->hDefaultFont);
848 GetTextMetricsA(hdc, &tm);
849 self->textHeight = tm.tmHeight;
850 SelectObject (hdc, hOldFont);
851 ReleaseDC(0, hdc);
854 if (GetWindowLongA (hwnd, GWL_STYLE) & SBT_TOOLTIPS) {
855 self->hwndToolTip =
856 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
857 CW_USEDEFAULT, CW_USEDEFAULT,
858 CW_USEDEFAULT, CW_USEDEFAULT,
859 hwnd, 0,
860 GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
862 if (self->hwndToolTip) {
863 NMTOOLTIPSCREATED nmttc;
865 nmttc.hdr.hwndFrom = hwnd;
866 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
867 nmttc.hdr.code = NM_TOOLTIPSCREATED;
868 nmttc.hwndToolTips = self->hwndToolTip;
870 SendMessageA (GetParent (hwnd), WM_NOTIFY,
871 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
875 GetClientRect (GetParent (hwnd), &rect);
876 width = rect.right - rect.left;
877 self->height = self->textHeight + 4 + VERT_BORDER;
878 MoveWindow (hwnd, lpCreate->x, lpCreate->y-1,
879 width, self->height, FALSE);
880 STATUSBAR_SetPartBounds (hwnd);
882 return 0;
886 static LRESULT
887 STATUSBAR_WMDestroy (HWND hwnd)
889 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
890 int i;
892 for (i = 0; i < self->numParts; i++) {
893 if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
894 COMCTL32_Free (self->parts[i].text);
896 if (self->part0.text && (self->part0.style != SBT_OWNERDRAW))
897 COMCTL32_Free (self->part0.text);
898 COMCTL32_Free (self->parts);
900 /* delete default font */
901 if (self->hDefaultFont)
902 DeleteObject (self->hDefaultFont);
904 /* delete tool tip control */
905 if (self->hwndToolTip)
906 DestroyWindow (self->hwndToolTip);
908 COMCTL32_Free (self);
910 return 0;
914 static __inline__ LRESULT
915 STATUSBAR_WMGetFont (HWND hwnd)
917 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
918 return infoPtr->hFont;
922 static LRESULT
923 STATUSBAR_WMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
925 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
926 INT len;
928 if (!(infoPtr->parts[0].text))
929 return 0;
930 len = lstrlenW (infoPtr->parts[0].text);
931 if (wParam > len) {
932 if (infoPtr->bUnicode)
933 lstrcpyW ((LPWSTR)lParam, infoPtr->parts[0].text);
934 else
935 lstrcpyWtoA ((LPSTR)lParam, infoPtr->parts[0].text);
936 return len;
939 return -1;
943 __inline__ static LRESULT
944 STATUSBAR_WMMouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
946 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
948 if (infoPtr->hwndToolTip)
949 STATUSBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
950 WM_MOUSEMOVE, wParam, lParam);
951 return 0;
955 static LRESULT
956 STATUSBAR_WMNCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
958 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
959 RECT rect;
960 POINT pt;
962 GetClientRect (hwnd, &rect);
964 pt.x = (INT)LOWORD(lParam);
965 pt.y = (INT)HIWORD(lParam);
966 ScreenToClient (hwnd, &pt);
968 rect.left = rect.right - 13;
969 rect.top += 2;
971 if (PtInRect (&rect, pt))
972 return HTBOTTOMRIGHT;
975 return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
979 static __inline__ LRESULT
980 STATUSBAR_WMNCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
982 PostMessageA (GetParent (hwnd), WM_NCLBUTTONDOWN, wParam, lParam);
983 return 0;
987 static __inline__ LRESULT
988 STATUSBAR_WMNCLButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
990 PostMessageA (GetParent (hwnd), WM_NCLBUTTONUP, wParam, lParam);
991 return 0;
995 static LRESULT
996 STATUSBAR_WMPaint (HWND hwnd, WPARAM wParam)
998 HDC hdc;
999 PAINTSTRUCT ps;
1001 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1002 STATUSBAR_Refresh (hwnd, hdc);
1003 if (!wParam)
1004 EndPaint (hwnd, &ps);
1006 return 0;
1010 static LRESULT
1011 STATUSBAR_WMSetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1013 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1015 infoPtr->hFont = (HFONT)wParam;
1016 if (LOWORD(lParam) == TRUE) {
1017 HDC hdc = GetDC (hwnd);
1018 STATUSBAR_Refresh (hwnd, hdc);
1019 ReleaseDC (hwnd, hdc);
1022 return 0;
1026 static LRESULT
1027 STATUSBAR_WMSetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
1029 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1030 STATUSWINDOWPART *part;
1031 int len;
1032 HDC hdc;
1034 if (infoPtr->numParts == 0)
1035 return FALSE;
1037 part = &infoPtr->parts[0];
1038 /* duplicate string */
1039 if (part->text)
1040 COMCTL32_Free (part->text);
1041 part->text = 0;
1042 if (infoPtr->bUnicode) {
1043 if (lParam && (len = lstrlenW((LPCWSTR)lParam))) {
1044 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1045 lstrcpyW (part->text, (LPCWSTR)lParam);
1048 else {
1049 if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
1050 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1051 lstrcpyAtoW (part->text, (LPCSTR)lParam);
1055 hdc = GetDC (hwnd);
1056 STATUSBAR_RefreshPart (hwnd, part, hdc);
1057 ReleaseDC (hwnd, hdc);
1059 return TRUE;
1063 static LRESULT
1064 STATUSBAR_WMSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1066 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1067 INT width, x, y, flags;
1068 RECT parent_rect;
1069 HWND parent;
1071 /* Need to resize width to match parent */
1072 flags = (INT) wParam;
1074 /* FIXME for flags =
1075 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
1078 if (flags == SIZE_RESTORED) {
1079 /* width and height don't apply */
1080 parent = GetParent (hwnd);
1081 GetClientRect (parent, &parent_rect);
1082 width = parent_rect.right - parent_rect.left;
1083 x = parent_rect.left;
1084 y = parent_rect.bottom - infoPtr->height;
1085 MoveWindow (hwnd, parent_rect.left,
1086 parent_rect.bottom - infoPtr->height,
1087 width, infoPtr->height, TRUE);
1088 STATUSBAR_SetPartBounds (hwnd);
1090 return 0;
1094 static LRESULT
1095 STATUSBAR_SendNotify (HWND hwnd, UINT code)
1097 NMHDR nmhdr;
1099 nmhdr.hwndFrom = hwnd;
1100 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1101 nmhdr.code = code;
1102 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
1103 return 0;
1108 LRESULT WINAPI
1109 StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1111 switch (msg) {
1112 case SB_GETBORDERS:
1113 return STATUSBAR_GetBorders (lParam);
1115 case SB_GETICON:
1116 return STATUSBAR_GetIcon (hwnd, wParam);
1118 case SB_GETPARTS:
1119 return STATUSBAR_GetParts (hwnd, wParam, lParam);
1121 case SB_GETRECT:
1122 return STATUSBAR_GetRect (hwnd, wParam, lParam);
1124 case SB_GETTEXTA:
1125 return STATUSBAR_GetTextA (hwnd, wParam, lParam);
1127 case SB_GETTEXTW:
1128 return STATUSBAR_GetTextW (hwnd, wParam, lParam);
1130 case SB_GETTEXTLENGTHA:
1131 case SB_GETTEXTLENGTHW:
1132 return STATUSBAR_GetTextLength (hwnd, wParam);
1134 case SB_GETTIPTEXTA:
1135 return STATUSBAR_GetTipTextA (hwnd, wParam, lParam);
1137 case SB_GETTIPTEXTW:
1138 return STATUSBAR_GetTipTextW (hwnd, wParam, lParam);
1140 case SB_GETUNICODEFORMAT:
1141 return STATUSBAR_GetUnicodeFormat (hwnd);
1143 case SB_ISSIMPLE:
1144 return STATUSBAR_IsSimple (hwnd);
1146 case SB_SETBKCOLOR:
1147 return STATUSBAR_SetBkColor (hwnd, wParam, lParam);
1149 case SB_SETICON:
1150 return STATUSBAR_SetIcon (hwnd, wParam, lParam);
1152 case SB_SETMINHEIGHT:
1153 return STATUSBAR_SetMinHeight (hwnd, wParam, lParam);
1155 case SB_SETPARTS:
1156 return STATUSBAR_SetParts (hwnd, wParam, lParam);
1158 case SB_SETTEXTA:
1159 return STATUSBAR_SetTextA (hwnd, wParam, lParam);
1161 case SB_SETTEXTW:
1162 return STATUSBAR_SetTextW (hwnd, wParam, lParam);
1164 case SB_SETTIPTEXTA:
1165 return STATUSBAR_SetTipTextA (hwnd, wParam, lParam);
1167 case SB_SETTIPTEXTW:
1168 return STATUSBAR_SetTipTextW (hwnd, wParam, lParam);
1170 case SB_SETUNICODEFORMAT:
1171 return STATUSBAR_SetUnicodeFormat (hwnd, wParam);
1173 case SB_SIMPLE:
1174 return STATUSBAR_Simple (hwnd, wParam, lParam);
1177 case WM_CREATE:
1178 return STATUSBAR_WMCreate (hwnd, wParam, lParam);
1180 case WM_DESTROY:
1181 return STATUSBAR_WMDestroy (hwnd);
1183 case WM_GETFONT:
1184 return STATUSBAR_WMGetFont (hwnd);
1186 case WM_GETTEXT:
1187 return STATUSBAR_WMGetText (hwnd, wParam, lParam);
1189 case WM_GETTEXTLENGTH:
1190 return STATUSBAR_GetTextLength (hwnd, 0);
1192 case WM_LBUTTONDBLCLK:
1193 return STATUSBAR_SendNotify (hwnd, NM_DBLCLK);
1195 case WM_LBUTTONUP:
1196 return STATUSBAR_SendNotify (hwnd, NM_CLICK);
1198 case WM_MOUSEMOVE:
1199 return STATUSBAR_WMMouseMove (hwnd, wParam, lParam);
1201 case WM_NCHITTEST:
1202 return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
1204 case WM_NCLBUTTONDOWN:
1205 return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
1207 case WM_NCLBUTTONUP:
1208 return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
1210 case WM_PAINT:
1211 return STATUSBAR_WMPaint (hwnd, wParam);
1213 case WM_RBUTTONDBLCLK:
1214 return STATUSBAR_SendNotify (hwnd, NM_RDBLCLK);
1216 case WM_RBUTTONUP:
1217 return STATUSBAR_SendNotify (hwnd, NM_RCLICK);
1219 case WM_SETFONT:
1220 return STATUSBAR_WMSetFont (hwnd, wParam, lParam);
1222 case WM_SETTEXT:
1223 return STATUSBAR_WMSetText (hwnd, wParam, lParam);
1225 case WM_SIZE:
1226 return STATUSBAR_WMSize (hwnd, wParam, lParam);
1228 default:
1229 if (msg >= WM_USER)
1230 ERR (statusbar, "unknown msg %04x wp=%04x lp=%08lx\n",
1231 msg, wParam, lParam);
1232 return DefWindowProcA (hwnd, msg, wParam, lParam);
1234 return 0;
1238 /***********************************************************************
1239 * STATUS_Register [Internal]
1241 * Registers the status window class.
1244 VOID
1245 STATUS_Register (VOID)
1247 WNDCLASSA wndClass;
1249 if (GlobalFindAtomA (STATUSCLASSNAMEA)) return;
1251 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1252 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1253 wndClass.lpfnWndProc = (WNDPROC)StatusWindowProc;
1254 wndClass.cbClsExtra = 0;
1255 wndClass.cbWndExtra = sizeof(STATUSWINDOWINFO *);
1256 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1257 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1258 wndClass.lpszClassName = STATUSCLASSNAMEA;
1260 RegisterClassA (&wndClass);
1264 /***********************************************************************
1265 * STATUS_Unregister [Internal]
1267 * Unregisters the status window class.
1270 VOID
1271 STATUS_Unregister (VOID)
1273 if (GlobalFindAtomA (STATUSCLASSNAMEA))
1274 UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);