- add prototypes for serial API functions
[wine/wine-kai.git] / dlls / comctl32 / status.c
blobfed0bd717ef2689eb11b2192773c5444f8b1ccde
1 /*
2 * Interface code to StatusWindow widget/control
4 * Copyright 1996 Bruce Milner
5 * Copyright 1998, 1999 Eric Kohl
6 */
8 #include "winbase.h"
9 #include "commctrl.h"
10 #include "status.h"
11 #include "debugtools.h"
13 DEFAULT_DEBUG_CHANNEL(statusbar)
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(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
36 /* prototype */
37 static void
38 STATUSBAR_SetPartBounds (HWND hwnd);
40 static void
41 STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
43 HPEN hOldPen;
44 POINT pt;
45 INT i;
47 pt.x = lpRect->right - 1;
48 pt.y = lpRect->bottom - 1;
50 hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
51 MoveToEx (hdc, pt.x - 12, pt.y, NULL);
52 LineTo (hdc, pt.x, pt.y);
53 LineTo (hdc, pt.x, pt.y - 12);
55 pt.x--;
56 pt.y--;
58 SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
59 for (i = 1; i < 11; i += 4) {
60 MoveToEx (hdc, pt.x - i, pt.y, NULL);
61 LineTo (hdc, pt.x, pt.y - i);
63 MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
64 LineTo (hdc, pt.x, pt.y - i-1);
67 SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
68 for (i = 3; i < 13; i += 4) {
69 MoveToEx (hdc, pt.x - i, pt.y, NULL);
70 LineTo (hdc, pt.x, pt.y - i);
73 SelectObject (hdc, hOldPen);
77 static void
78 STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
80 RECT r = part->bound;
81 UINT border = BDR_SUNKENOUTER;
83 if (part->style & SBT_POPOUT)
84 border = BDR_RAISEDOUTER;
85 else if (part->style & SBT_NOBORDERS)
86 border = 0;
88 DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
90 /* draw the icon */
91 if (part->hIcon) {
92 INT cy = r.bottom - r.top;
94 r.left += 2;
95 DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
96 r.left += cy;
99 /* now draw text */
100 if (part->text) {
101 int oldbkmode = SetBkMode(hdc, TRANSPARENT);
102 LPWSTR p = (LPWSTR)part->text;
103 UINT align = DT_LEFT;
104 if (*p == L'\t') {
105 p++;
106 align = DT_CENTER;
108 if (*p == L'\t') {
109 p++;
110 align = DT_RIGHT;
113 r.left += 3;
114 DrawTextW (hdc, p, lstrlenW (p), &r, align|DT_VCENTER|DT_SINGLELINE);
115 if (oldbkmode != TRANSPARENT)
116 SetBkMode(hdc, oldbkmode);
121 static VOID
122 STATUSBAR_RefreshPart (HWND hwnd, STATUSWINDOWPART *part, HDC hdc, int itemID)
124 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
125 HBRUSH hbrBk;
126 HFONT hOldFont;
128 if (!IsWindowVisible (hwnd))
129 return;
131 if (self->clrBk != CLR_DEFAULT)
132 hbrBk = CreateSolidBrush (self->clrBk);
133 else
134 hbrBk = GetSysColorBrush (COLOR_3DFACE);
135 FillRect(hdc, &part->bound, hbrBk);
137 hOldFont = SelectObject (hdc, self->hFont ? self->hFont : self->hDefaultFont);
139 if (part->style & SBT_OWNERDRAW) {
140 DRAWITEMSTRUCT dis;
142 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
143 dis.itemID = itemID;
144 dis.hwndItem = hwnd;
145 dis.hDC = hdc;
146 dis.rcItem = part->bound;
147 dis.itemData = (INT)part->text;
148 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
149 (WPARAM)dis.CtlID, (LPARAM)&dis);
151 else
152 STATUSBAR_DrawPart (hdc, part);
154 SelectObject (hdc, hOldFont);
156 if (self->clrBk != CLR_DEFAULT)
157 DeleteObject (hbrBk);
159 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
160 RECT rect;
162 GetClientRect (hwnd, &rect);
163 STATUSBAR_DrawSizeGrip (hdc, &rect);
168 static BOOL
169 STATUSBAR_Refresh (HWND hwnd, HDC hdc)
171 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
172 int i;
173 RECT rect;
174 HBRUSH hbrBk;
175 HFONT hOldFont;
177 if (!IsWindowVisible(hwnd))
178 return (TRUE);
180 STATUSBAR_SetPartBounds(hwnd);
182 GetClientRect (hwnd, &rect);
184 if (infoPtr->clrBk != CLR_DEFAULT)
185 hbrBk = CreateSolidBrush (infoPtr->clrBk);
186 else
187 hbrBk = GetSysColorBrush (COLOR_3DFACE);
188 FillRect(hdc, &rect, hbrBk);
190 hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
192 if (infoPtr->simple) {
193 STATUSBAR_RefreshPart (hwnd, &infoPtr->part0,hdc,0);
195 else {
196 for (i = 0; i < infoPtr->numParts; i++) {
197 if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
198 DRAWITEMSTRUCT dis;
200 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
201 dis.itemID = i;
202 dis.hwndItem = hwnd;
203 dis.hDC = hdc;
204 dis.rcItem = infoPtr->parts[i].bound;
205 dis.itemData = (INT)infoPtr->parts[i].text;
206 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
207 (WPARAM)dis.CtlID, (LPARAM)&dis);
209 else
210 STATUSBAR_RefreshPart (hwnd, &infoPtr->parts[i], hdc,i);
214 SelectObject (hdc, hOldFont);
216 if (infoPtr->clrBk != CLR_DEFAULT)
217 DeleteObject (hbrBk);
219 if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
220 STATUSBAR_DrawSizeGrip (hdc, &rect);
222 return TRUE;
226 static void
227 STATUSBAR_SetPartBounds (HWND hwnd)
229 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
230 STATUSWINDOWPART *part;
231 RECT rect, *r;
232 int i;
234 /* get our window size */
235 GetClientRect (hwnd, &rect);
237 rect.top += VERT_BORDER;
239 /* set bounds for simple rectangle */
240 self->part0.bound = rect;
242 /* set bounds for non-simple rectangles */
243 for (i = 0; i < self->numParts; i++) {
244 part = &self->parts[i];
245 r = &self->parts[i].bound;
246 r->top = rect.top;
247 r->bottom = rect.bottom;
248 if (i == 0)
249 r->left = 0;
250 else
251 r->left = self->parts[i-1].bound.right + HORZ_GAP;
252 if (part->x == -1)
253 r->right = rect.right;
254 else
255 r->right = part->x;
257 if (self->hwndToolTip) {
258 TTTOOLINFOA ti;
260 ti.cbSize = sizeof(TTTOOLINFOA);
261 ti.hwnd = hwnd;
262 ti.uId = i;
263 ti.rect = *r;
264 SendMessageA (self->hwndToolTip, TTM_NEWTOOLRECTA,
265 0, (LPARAM)&ti);
271 static VOID
272 STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
273 WPARAM wParam, LPARAM lParam)
275 MSG msg;
277 msg.hwnd = hwndMsg;
278 msg.message = uMsg;
279 msg.wParam = wParam;
280 msg.lParam = lParam;
281 msg.time = GetMessageTime ();
282 msg.pt.x = LOWORD(GetMessagePos ());
283 msg.pt.y = HIWORD(GetMessagePos ());
285 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
289 inline static LRESULT
290 STATUSBAR_GetBorders (LPARAM lParam)
292 LPINT out = (LPINT) lParam;
294 out[0] = HORZ_BORDER; /* horizontal border width */
295 out[1] = VERT_BORDER; /* vertical border width */
296 out[2] = HORZ_GAP; /* width of border between rectangles */
298 return TRUE;
302 static LRESULT
303 STATUSBAR_GetIcon (HWND hwnd, WPARAM wParam)
305 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
306 INT nPart;
308 nPart = (INT)wParam & 0x00ff;
309 if ((nPart < -1) || (nPart >= self->numParts))
310 return 0;
312 if (nPart == -1)
313 return (self->part0.hIcon);
314 else
315 return (self->parts[nPart].hIcon);
319 static LRESULT
320 STATUSBAR_GetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
322 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
323 LPINT parts;
324 INT num_parts;
325 INT i;
327 num_parts = (INT) wParam;
328 parts = (LPINT) lParam;
329 if (parts) {
330 return (infoPtr->numParts);
331 for (i = 0; i < num_parts; i++) {
332 parts[i] = infoPtr->parts[i].x;
335 return (infoPtr->numParts);
339 static LRESULT
340 STATUSBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
342 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
343 int part_num;
344 LPRECT rect;
346 part_num = ((INT) wParam) & 0x00ff;
347 rect = (LPRECT) lParam;
348 if (infoPtr->simple)
349 *rect = infoPtr->part0.bound;
350 else
351 *rect = infoPtr->parts[part_num].bound;
352 return TRUE;
356 static LRESULT
357 STATUSBAR_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
359 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
360 STATUSWINDOWPART *part;
361 INT nPart;
362 LRESULT result;
364 nPart = ((INT) wParam) & 0x00ff;
365 if (self->simple)
366 part = &self->part0;
367 else
368 part = &self->parts[nPart];
370 if (part->style & SBT_OWNERDRAW)
371 result = (LRESULT)part->text;
372 else {
373 result = part->text ? lstrlenW (part->text) : 0;
374 result |= (part->style << 16);
375 if (lParam && LOWORD(result))
376 lstrcpyWtoA ((LPSTR)lParam, part->text);
378 return result;
382 static LRESULT
383 STATUSBAR_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
385 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
386 STATUSWINDOWPART *part;
387 INT nPart;
388 LRESULT result;
390 nPart = ((INT)wParam) & 0x00ff;
391 if (infoPtr->simple)
392 part = &infoPtr->part0;
393 else
394 part = &infoPtr->parts[nPart];
396 if (part->style & SBT_OWNERDRAW)
397 result = (LRESULT)part->text;
398 else {
399 result = part->text ? lstrlenW (part->text) : 0;
400 result |= (part->style << 16);
401 if (lParam)
402 lstrcpyW ((LPWSTR)lParam, part->text);
404 return result;
408 static LRESULT
409 STATUSBAR_GetTextLength (HWND hwnd, WPARAM wParam)
411 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
412 STATUSWINDOWPART *part;
413 INT part_num;
414 DWORD result;
416 part_num = ((INT) wParam) & 0x00ff;
418 if (infoPtr->simple)
419 part = &infoPtr->part0;
420 else
421 part = &infoPtr->parts[part_num];
423 if (part->text)
424 result = lstrlenW(part->text);
425 else
426 result = 0;
428 result |= (part->style << 16);
429 return result;
433 static LRESULT
434 STATUSBAR_GetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
436 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
438 if (infoPtr->hwndToolTip) {
439 TTTOOLINFOA ti;
440 ti.cbSize = sizeof(TTTOOLINFOA);
441 ti.hwnd = hwnd;
442 ti.uId = LOWORD(wParam);
443 SendMessageA (infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
445 if (ti.lpszText)
446 lstrcpynA ((LPSTR)lParam, ti.lpszText, HIWORD(wParam));
449 return 0;
453 static LRESULT
454 STATUSBAR_GetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
456 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
458 if (infoPtr->hwndToolTip) {
459 TTTOOLINFOW ti;
460 ti.cbSize = sizeof(TTTOOLINFOW);
461 ti.hwnd = hwnd;
462 ti.uId = LOWORD(wParam);
463 SendMessageW (infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
465 if (ti.lpszText)
466 lstrcpynW ((LPWSTR)lParam, ti.lpszText, HIWORD(wParam));
469 return 0;
473 inline static LRESULT
474 STATUSBAR_GetUnicodeFormat (HWND hwnd)
476 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
477 return infoPtr->bUnicode;
481 inline static LRESULT
482 STATUSBAR_IsSimple (HWND hwnd)
484 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
485 return infoPtr->simple;
489 static LRESULT
490 STATUSBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
492 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
493 COLORREF oldBkColor;
495 oldBkColor = self->clrBk;
496 self->clrBk = (COLORREF)lParam;
497 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
499 return oldBkColor;
503 static LRESULT
504 STATUSBAR_SetIcon (HWND hwnd, WPARAM wParam, LPARAM lParam)
506 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
507 INT nPart = (INT)wParam & 0x00ff;
508 HDC hdc;
510 if ((nPart < -1) || (nPart >= self->numParts))
511 return FALSE;
513 hdc = GetDC (hwnd);
514 if (nPart == -1) {
515 self->part0.hIcon = (HICON)lParam;
516 if (self->simple)
517 RedrawWindow(hwnd, &self->part0.bound,(HRGN)NULL,
518 RDW_INVALIDATE|RDW_UPDATENOW);
520 else {
521 self->parts[nPart].hIcon = (HICON)lParam;
522 if (!(self->simple))
523 RedrawWindow(hwnd,&self->parts[nPart].bound,(HRGN)NULL,
524 RDW_INVALIDATE|RDW_UPDATENOW);
526 ReleaseDC (hwnd, hdc);
528 return TRUE;
532 static LRESULT
533 STATUSBAR_SetMinHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
535 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
537 if (IsWindowVisible (hwnd)) {
538 HWND parent = GetParent (hwnd);
539 INT width, x, y;
540 RECT parent_rect;
542 GetClientRect (parent, &parent_rect);
543 self->height = (INT)wParam + VERT_BORDER;
544 width = parent_rect.right - parent_rect.left;
545 x = parent_rect.left;
546 y = parent_rect.bottom - self->height;
547 MoveWindow (hwnd, parent_rect.left,
548 parent_rect.bottom - self->height,
549 width, self->height, TRUE);
550 STATUSBAR_SetPartBounds (hwnd);
553 return TRUE;
557 static LRESULT
558 STATUSBAR_SetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
560 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
561 STATUSWINDOWPART *tmp;
562 LPINT parts;
563 int i;
564 int oldNumParts;
566 if (self->simple)
567 self->simple = FALSE;
569 oldNumParts = self->numParts;
570 self->numParts = (INT) wParam;
571 parts = (LPINT) lParam;
572 if (oldNumParts > self->numParts) {
573 for (i = self->numParts ; i < oldNumParts; i++) {
574 if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
575 COMCTL32_Free (self->parts[i].text);
578 else if (oldNumParts < self->numParts) {
579 tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
580 for (i = 0; i < oldNumParts; i++) {
581 tmp[i] = self->parts[i];
583 if (self->parts)
584 COMCTL32_Free (self->parts);
585 self->parts = tmp;
588 for (i = 0; i < self->numParts; i++) {
589 self->parts[i].x = parts[i];
592 if (self->hwndToolTip) {
593 INT nTipCount =
594 SendMessageA (self->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
596 if (nTipCount < self->numParts) {
597 /* add tools */
598 TTTOOLINFOA ti;
599 INT i;
601 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
602 ti.cbSize = sizeof(TTTOOLINFOA);
603 ti.hwnd = hwnd;
604 for (i = nTipCount; i < self->numParts; i++) {
605 TRACE("add tool %d\n", i);
606 ti.uId = i;
607 SendMessageA (self->hwndToolTip, TTM_ADDTOOLA,
608 0, (LPARAM)&ti);
611 else if (nTipCount > self->numParts) {
612 /* delete tools */
613 INT i;
615 for (i = nTipCount - 1; i >= self->numParts; i--) {
617 FIXME("delete tool %d\n", i);
623 STATUSBAR_SetPartBounds (hwnd);
625 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
627 return TRUE;
631 static LRESULT
632 STATUSBAR_SetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
634 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
635 STATUSWINDOWPART *part=NULL;
636 int part_num;
637 int style;
638 LPSTR text;
639 int len;
641 text = (LPSTR) lParam;
642 part_num = ((INT) wParam) & 0x00ff;
643 style = ((INT) wParam) & 0xff00;
645 if (part_num==255)
646 part = &self->part0;
647 else if (!self->simple && self->parts!=NULL)
648 part = &self->parts[part_num];
649 if (!part) return FALSE;
651 if (!(part->style & SBT_OWNERDRAW) && part->text)
652 COMCTL32_Free (part->text);
653 part->text = 0;
655 if (style & SBT_OWNERDRAW) {
656 part->text = (LPWSTR)text;
658 else {
659 /* duplicate string */
660 if (text && (len = lstrlenA(text))) {
661 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
662 lstrcpyAtoW (part->text, text);
665 part->style = style;
667 RedrawWindow(hwnd,&part->bound,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
669 return TRUE;
673 static LRESULT
674 STATUSBAR_SetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
676 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
677 STATUSWINDOWPART *part;
678 INT part_num, style, len;
679 LPWSTR text;
681 text = (LPWSTR) lParam;
682 part_num = ((INT) wParam) & 0x00ff;
683 style = ((INT) wParam) & 0xff00;
685 if ((self->simple) || (self->parts==NULL) || (part_num==255))
686 part = &self->part0;
687 else
688 part = &self->parts[part_num];
689 if (!part) return FALSE;
691 if (!(part->style & SBT_OWNERDRAW) && part->text)
692 COMCTL32_Free (part->text);
693 part->text = 0;
695 if (style & SBT_OWNERDRAW) {
696 part->text = text;
698 else {
699 /* duplicate string */
700 if (text && (len = lstrlenW(text))) {
701 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
702 lstrcpyW(part->text, text);
705 part->style = style;
707 RedrawWindow(hwnd,&part->bound,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
709 return TRUE;
713 static LRESULT
714 STATUSBAR_SetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
716 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
718 TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
719 if (infoPtr->hwndToolTip) {
720 TTTOOLINFOA ti;
721 ti.cbSize = sizeof(TTTOOLINFOA);
722 ti.hwnd = hwnd;
723 ti.uId = (INT)wParam;
724 ti.hinst = 0;
725 ti.lpszText = (LPSTR)lParam;
726 SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
727 0, (LPARAM)&ti);
730 return 0;
734 static LRESULT
735 STATUSBAR_SetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
737 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
739 TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
740 if (infoPtr->hwndToolTip) {
741 TTTOOLINFOW ti;
742 ti.cbSize = sizeof(TTTOOLINFOW);
743 ti.hwnd = hwnd;
744 ti.uId = (INT)wParam;
745 ti.hinst = 0;
746 ti.lpszText = (LPWSTR)lParam;
747 SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW,
748 0, (LPARAM)&ti);
751 return 0;
755 inline static LRESULT
756 STATUSBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
758 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
759 BOOL bTemp = infoPtr->bUnicode;
761 TRACE("(0x%x)\n", (BOOL)wParam);
762 infoPtr->bUnicode = (BOOL)wParam;
764 return bTemp;
768 static LRESULT
769 STATUSBAR_Simple (HWND hwnd, WPARAM wParam, LPARAM lParam)
771 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
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 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
784 return TRUE;
788 static LRESULT
789 STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
791 LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
792 NONCLIENTMETRICSA nclm;
793 RECT rect;
794 int width, len;
795 HDC hdc;
796 STATUSWINDOWINFO *self;
798 self = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
799 SetWindowLongA (hwnd, 0, (DWORD)self);
801 self->numParts = 1;
802 self->parts = 0;
803 self->simple = FALSE;
804 self->clrBk = CLR_DEFAULT;
805 self->hFont = 0;
806 GetClientRect (hwnd, &rect);
808 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
809 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
810 self->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
812 /* initialize simple case */
813 self->part0.bound = rect;
814 self->part0.text = 0;
815 self->part0.x = 0;
816 self->part0.style = 0;
817 self->part0.hIcon = 0;
819 /* initialize first part */
820 self->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
821 self->parts[0].bound = rect;
822 self->parts[0].text = 0;
823 self->parts[0].x = -1;
824 self->parts[0].style = 0;
825 self->parts[0].hIcon = 0;
827 if (IsWindowUnicode (hwnd)) {
828 self->bUnicode = TRUE;
829 if (lpCreate->lpszName &&
830 (len = lstrlenW ((LPCWSTR)lpCreate->lpszName))) {
831 self->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
832 lstrcpyW (self->parts[0].text, (LPCWSTR)lpCreate->lpszName);
835 else {
836 if (lpCreate->lpszName &&
837 (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);
909 SetWindowLongA(hwnd, 0, 0);
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 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,
1018 RDW_INVALIDATE|RDW_UPDATENOW);
1020 return 0;
1024 static LRESULT
1025 STATUSBAR_WMSetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
1027 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1028 STATUSWINDOWPART *part;
1029 int len;
1031 if (infoPtr->numParts == 0)
1032 return FALSE;
1034 part = &infoPtr->parts[0];
1035 /* duplicate string */
1036 if (part->text)
1037 COMCTL32_Free (part->text);
1038 part->text = 0;
1039 if (infoPtr->bUnicode) {
1040 if (lParam && (len = lstrlenW((LPCWSTR)lParam))) {
1041 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1042 lstrcpyW (part->text, (LPCWSTR)lParam);
1045 else {
1046 if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
1047 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1048 lstrcpyAtoW (part->text, (LPCSTR)lParam);
1052 RedrawWindow(hwnd,&part->bound,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
1054 return TRUE;
1058 static LRESULT
1059 STATUSBAR_WMSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1061 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1062 INT width, x, y, flags;
1063 RECT parent_rect;
1064 HWND parent;
1066 /* Need to resize width to match parent */
1067 flags = (INT) wParam;
1069 /* FIXME for flags =
1070 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
1073 if (flags == SIZE_RESTORED) {
1074 /* width and height don't apply */
1075 parent = GetParent (hwnd);
1076 GetClientRect (parent, &parent_rect);
1077 width = parent_rect.right - parent_rect.left;
1078 x = parent_rect.left;
1079 y = parent_rect.bottom - infoPtr->height;
1080 MoveWindow (hwnd, parent_rect.left,
1081 parent_rect.bottom - infoPtr->height,
1082 width, infoPtr->height, TRUE);
1083 STATUSBAR_SetPartBounds (hwnd);
1085 return 0;
1089 static LRESULT
1090 STATUSBAR_SendNotify (HWND hwnd, UINT code)
1092 NMHDR nmhdr;
1094 nmhdr.hwndFrom = hwnd;
1095 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1096 nmhdr.code = code;
1097 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
1098 return 0;
1103 static LRESULT WINAPI
1104 StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1106 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, msg, wParam, lParam);
1107 if (!(STATUSBAR_GetInfoPtr(hwnd)) && (msg != WM_CREATE))
1108 return DefWindowProcA (hwnd, msg, wParam, lParam);
1110 switch (msg) {
1111 case SB_GETBORDERS:
1112 return STATUSBAR_GetBorders (lParam);
1114 case SB_GETICON:
1115 return STATUSBAR_GetIcon (hwnd, wParam);
1117 case SB_GETPARTS:
1118 return STATUSBAR_GetParts (hwnd, wParam, lParam);
1120 case SB_GETRECT:
1121 return STATUSBAR_GetRect (hwnd, wParam, lParam);
1123 case SB_GETTEXTA:
1124 return STATUSBAR_GetTextA (hwnd, wParam, lParam);
1126 case SB_GETTEXTW:
1127 return STATUSBAR_GetTextW (hwnd, wParam, lParam);
1129 case SB_GETTEXTLENGTHA:
1130 case SB_GETTEXTLENGTHW:
1131 return STATUSBAR_GetTextLength (hwnd, wParam);
1133 case SB_GETTIPTEXTA:
1134 return STATUSBAR_GetTipTextA (hwnd, wParam, lParam);
1136 case SB_GETTIPTEXTW:
1137 return STATUSBAR_GetTipTextW (hwnd, wParam, lParam);
1139 case SB_GETUNICODEFORMAT:
1140 return STATUSBAR_GetUnicodeFormat (hwnd);
1142 case SB_ISSIMPLE:
1143 return STATUSBAR_IsSimple (hwnd);
1145 case SB_SETBKCOLOR:
1146 return STATUSBAR_SetBkColor (hwnd, wParam, lParam);
1148 case SB_SETICON:
1149 return STATUSBAR_SetIcon (hwnd, wParam, lParam);
1151 case SB_SETMINHEIGHT:
1152 return STATUSBAR_SetMinHeight (hwnd, wParam, lParam);
1154 case SB_SETPARTS:
1155 return STATUSBAR_SetParts (hwnd, wParam, lParam);
1157 case SB_SETTEXTA:
1158 return STATUSBAR_SetTextA (hwnd, wParam, lParam);
1160 case SB_SETTEXTW:
1161 return STATUSBAR_SetTextW (hwnd, wParam, lParam);
1163 case SB_SETTIPTEXTA:
1164 return STATUSBAR_SetTipTextA (hwnd, wParam, lParam);
1166 case SB_SETTIPTEXTW:
1167 return STATUSBAR_SetTipTextW (hwnd, wParam, lParam);
1169 case SB_SETUNICODEFORMAT:
1170 return STATUSBAR_SetUnicodeFormat (hwnd, wParam);
1172 case SB_SIMPLE:
1173 return STATUSBAR_Simple (hwnd, wParam, lParam);
1176 case WM_CREATE:
1177 return STATUSBAR_WMCreate (hwnd, wParam, lParam);
1179 case WM_DESTROY:
1180 return STATUSBAR_WMDestroy (hwnd);
1182 case WM_GETFONT:
1183 return STATUSBAR_WMGetFont (hwnd);
1185 case WM_GETTEXT:
1186 return STATUSBAR_WMGetText (hwnd, wParam, lParam);
1188 case WM_GETTEXTLENGTH:
1189 return STATUSBAR_GetTextLength (hwnd, 0);
1191 case WM_LBUTTONDBLCLK:
1192 return STATUSBAR_SendNotify (hwnd, NM_DBLCLK);
1194 case WM_LBUTTONUP:
1195 return STATUSBAR_SendNotify (hwnd, NM_CLICK);
1197 case WM_MOUSEMOVE:
1198 return STATUSBAR_WMMouseMove (hwnd, wParam, lParam);
1200 case WM_NCHITTEST:
1201 return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
1203 case WM_NCLBUTTONDOWN:
1204 return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
1206 case WM_NCLBUTTONUP:
1207 return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
1209 case WM_PAINT:
1210 return STATUSBAR_WMPaint (hwnd, wParam);
1212 case WM_RBUTTONDBLCLK:
1213 return STATUSBAR_SendNotify (hwnd, NM_RDBLCLK);
1215 case WM_RBUTTONUP:
1216 return STATUSBAR_SendNotify (hwnd, NM_RCLICK);
1218 case WM_SETFONT:
1219 return STATUSBAR_WMSetFont (hwnd, wParam, lParam);
1221 case WM_SETTEXT:
1222 return STATUSBAR_WMSetText (hwnd, wParam, lParam);
1224 case WM_SIZE:
1225 return STATUSBAR_WMSize (hwnd, wParam, lParam);
1227 default:
1228 if (msg >= WM_USER)
1229 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1230 msg, wParam, lParam);
1231 return DefWindowProcA (hwnd, msg, wParam, lParam);
1233 return 0;
1237 /***********************************************************************
1238 * STATUS_Register [Internal]
1240 * Registers the status window class.
1243 VOID
1244 STATUS_Register (void)
1246 WNDCLASSA wndClass;
1248 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1249 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1250 wndClass.lpfnWndProc = (WNDPROC)StatusWindowProc;
1251 wndClass.cbClsExtra = 0;
1252 wndClass.cbWndExtra = sizeof(STATUSWINDOWINFO *);
1253 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1254 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1255 wndClass.lpszClassName = STATUSCLASSNAMEA;
1257 RegisterClassA (&wndClass);
1261 /***********************************************************************
1262 * STATUS_Unregister [Internal]
1264 * Unregisters the status window class.
1267 VOID
1268 STATUS_Unregister (void)
1270 UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);