Replaced all lstr* calls from inside Wine code by their str* equivalent.
[wine.git] / dlls / comctl32 / status.c
blob5d8524e110c5cdb801b37f7140315722dda7f3be
1 /*
2 * Interface code to StatusWindow widget/control
4 * Copyright 1996 Bruce Milner
5 * Copyright 1998, 1999 Eric Kohl
6 */
7 /*
8 * FIXME/TODO
9 * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
10 * 2) Tooltip support (almost done).
11 * 3) I think RedrawWindow() is rather wrong, we should use InvalidateRect
12 * probably.
15 #include "winbase.h"
16 #include "wine/unicode.h"
17 #include "commctrl.h"
18 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(statusbar);
22 typedef struct
24 INT x;
25 INT style;
26 RECT bound;
27 LPWSTR text;
28 HICON hIcon;
29 } STATUSWINDOWPART;
31 typedef struct
33 UINT16 numParts;
34 UINT16 textHeight;
35 UINT height;
36 BOOL simple;
37 HWND hwndToolTip;
38 HFONT hFont;
39 HFONT hDefaultFont;
40 COLORREF clrBk; /* background color */
41 BOOL bUnicode; /* unicode flag */
42 STATUSWINDOWPART part0; /* simple window */
43 STATUSWINDOWPART *parts;
44 } STATUSWINDOWINFO;
47 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
48 * The second cdrom contains executables drawstat.exe,gettext.exe,
49 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
53 #define _MAX(a,b) (((a)>(b))?(a):(b))
54 #define _MIN(a,b) (((a)>(b))?(b):(a))
56 #define HORZ_BORDER 0
57 #define VERT_BORDER 2
58 #define HORZ_GAP 2
60 #define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
62 /* prototype */
63 static void
64 STATUSBAR_SetPartBounds (HWND hwnd);
66 static void
67 STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
69 HPEN hOldPen;
70 POINT pt;
71 INT i;
73 pt.x = lpRect->right - 1;
74 pt.y = lpRect->bottom - 1;
76 hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
77 MoveToEx (hdc, pt.x - 12, pt.y, NULL);
78 LineTo (hdc, pt.x, pt.y);
79 LineTo (hdc, pt.x, pt.y - 12);
81 pt.x--;
82 pt.y--;
84 SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
85 for (i = 1; i < 11; i += 4) {
86 MoveToEx (hdc, pt.x - i, pt.y, NULL);
87 LineTo (hdc, pt.x, pt.y - i);
89 MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
90 LineTo (hdc, pt.x, pt.y - i-1);
93 SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
94 for (i = 3; i < 13; i += 4) {
95 MoveToEx (hdc, pt.x - i, pt.y, NULL);
96 LineTo (hdc, pt.x, pt.y - i);
99 SelectObject (hdc, hOldPen);
103 static void
104 STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
106 RECT r = part->bound;
107 UINT border = BDR_SUNKENOUTER;
109 if (part->style & SBT_POPOUT)
110 border = BDR_RAISEDOUTER;
111 else if (part->style & SBT_NOBORDERS)
112 border = 0;
114 DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
116 /* draw the icon */
117 if (part->hIcon) {
118 INT cy = r.bottom - r.top;
120 r.left += 2;
121 DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
122 r.left += cy;
125 /* now draw text */
126 if (part->text) {
127 int oldbkmode = SetBkMode(hdc, TRANSPARENT);
128 LPWSTR p = (LPWSTR)part->text;
129 UINT align = DT_LEFT;
130 if (*p == L'\t') {
131 p++;
132 align = DT_CENTER;
134 if (*p == L'\t') {
135 p++;
136 align = DT_RIGHT;
139 r.left += 3;
140 DrawTextW (hdc, p, lstrlenW (p), &r, align|DT_VCENTER|DT_SINGLELINE);
141 if (oldbkmode != TRANSPARENT)
142 SetBkMode(hdc, oldbkmode);
147 static VOID
148 STATUSBAR_RefreshPart (HWND hwnd, STATUSWINDOWPART *part, HDC hdc, int itemID)
150 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
151 HBRUSH hbrBk;
152 HFONT hOldFont;
154 if (!IsWindowVisible (hwnd))
155 return;
157 if (part->bound.right < part->bound.left) return;
159 if (self->clrBk != CLR_DEFAULT)
160 hbrBk = CreateSolidBrush (self->clrBk);
161 else
162 hbrBk = GetSysColorBrush (COLOR_3DFACE);
163 FillRect(hdc, &part->bound, hbrBk);
165 hOldFont = SelectObject (hdc, self->hFont ? self->hFont : self->hDefaultFont);
167 if (part->style & SBT_OWNERDRAW) {
168 DRAWITEMSTRUCT dis;
170 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
171 dis.itemID = itemID;
172 dis.hwndItem = hwnd;
173 dis.hDC = hdc;
174 dis.rcItem = part->bound;
175 dis.itemData = (INT)part->text;
176 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
177 (WPARAM)dis.CtlID, (LPARAM)&dis);
178 } else
179 STATUSBAR_DrawPart (hdc, part);
181 SelectObject (hdc, hOldFont);
183 if (self->clrBk != CLR_DEFAULT)
184 DeleteObject (hbrBk);
186 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
187 RECT rect;
189 GetClientRect (hwnd, &rect);
190 STATUSBAR_DrawSizeGrip (hdc, &rect);
195 static BOOL
196 STATUSBAR_Refresh (HWND hwnd, HDC hdc)
198 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
199 int i;
200 RECT rect;
201 HBRUSH hbrBk;
202 HFONT hOldFont;
204 if (!IsWindowVisible(hwnd))
205 return (TRUE);
207 STATUSBAR_SetPartBounds(hwnd);
209 GetClientRect (hwnd, &rect);
211 if (infoPtr->clrBk != CLR_DEFAULT)
212 hbrBk = CreateSolidBrush (infoPtr->clrBk);
213 else
214 hbrBk = GetSysColorBrush (COLOR_3DFACE);
215 FillRect(hdc, &rect, hbrBk);
217 hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
219 if (infoPtr->simple) {
220 STATUSBAR_RefreshPart (hwnd, &infoPtr->part0,hdc,0);
221 } else {
222 for (i = 0; i < infoPtr->numParts; i++) {
223 if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
224 DRAWITEMSTRUCT dis;
226 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
227 dis.itemID = i;
228 dis.hwndItem = hwnd;
229 dis.hDC = hdc;
230 dis.rcItem = infoPtr->parts[i].bound;
231 dis.itemData = (INT)infoPtr->parts[i].text;
232 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
233 (WPARAM)dis.CtlID, (LPARAM)&dis);
234 } else
235 STATUSBAR_RefreshPart (hwnd, &infoPtr->parts[i], hdc,i);
239 SelectObject (hdc, hOldFont);
241 if (infoPtr->clrBk != CLR_DEFAULT)
242 DeleteObject (hbrBk);
244 if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
245 STATUSBAR_DrawSizeGrip (hdc, &rect);
247 return TRUE;
251 static void
252 STATUSBAR_SetPartBounds (HWND hwnd)
254 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
255 STATUSWINDOWPART *part;
256 RECT rect, *r;
257 int i;
259 /* get our window size */
260 GetClientRect (hwnd, &rect);
262 rect.top += VERT_BORDER;
264 /* set bounds for simple rectangle */
265 self->part0.bound = rect;
267 /* set bounds for non-simple rectangles */
268 for (i = 0; i < self->numParts; i++) {
269 part = &self->parts[i];
270 r = &self->parts[i].bound;
271 r->top = rect.top;
272 r->bottom = rect.bottom;
273 if (i == 0)
274 r->left = 0;
275 else
276 r->left = self->parts[i-1].bound.right + HORZ_GAP;
277 if (part->x == -1)
278 r->right = rect.right;
279 else
280 r->right = part->x;
282 if (self->hwndToolTip) {
283 TTTOOLINFOA ti;
285 ti.cbSize = sizeof(TTTOOLINFOA);
286 ti.hwnd = hwnd;
287 ti.uId = i;
288 ti.rect = *r;
289 SendMessageA (self->hwndToolTip, TTM_NEWTOOLRECTA,
290 0, (LPARAM)&ti);
296 static VOID
297 STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
298 WPARAM wParam, LPARAM lParam)
300 MSG msg;
302 msg.hwnd = hwndMsg;
303 msg.message = uMsg;
304 msg.wParam = wParam;
305 msg.lParam = lParam;
306 msg.time = GetMessageTime ();
307 msg.pt.x = LOWORD(GetMessagePos ());
308 msg.pt.y = HIWORD(GetMessagePos ());
310 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
314 inline static LRESULT
315 STATUSBAR_GetBorders (LPARAM lParam)
317 LPINT out = (LPINT) lParam;
319 out[0] = HORZ_BORDER; /* horizontal border width */
320 out[1] = VERT_BORDER; /* vertical border width */
321 out[2] = HORZ_GAP; /* width of border between rectangles */
323 return TRUE;
327 static LRESULT
328 STATUSBAR_GetIcon (HWND hwnd, WPARAM wParam)
330 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
331 INT nPart;
333 nPart = (INT)wParam & 0x00ff;
334 if ((nPart < -1) || (nPart >= self->numParts))
335 return 0;
337 if (nPart == -1)
338 return (self->part0.hIcon);
339 else
340 return (self->parts[nPart].hIcon);
344 static LRESULT
345 STATUSBAR_GetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
347 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
348 LPINT parts;
349 INT num_parts;
350 INT i;
352 num_parts = (INT) wParam;
353 parts = (LPINT) lParam;
354 if (parts) {
355 for (i = 0; i < num_parts; i++) {
356 parts[i] = infoPtr->parts[i].x;
359 return (infoPtr->numParts);
363 static LRESULT
364 STATUSBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
366 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
367 int part_num;
368 LPRECT rect;
370 part_num = ((INT) wParam) & 0x00ff;
371 rect = (LPRECT) lParam;
372 if (infoPtr->simple)
373 *rect = infoPtr->part0.bound;
374 else
375 *rect = infoPtr->parts[part_num].bound;
376 return TRUE;
380 static LRESULT
381 STATUSBAR_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
383 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
384 STATUSWINDOWPART *part;
385 INT nPart;
386 LRESULT result;
388 nPart = ((INT) wParam) & 0x00ff;
389 if (self->simple)
390 part = &self->part0;
391 else
392 part = &self->parts[nPart];
394 if (part->style & SBT_OWNERDRAW)
395 result = (LRESULT)part->text;
396 else {
397 result = part->text ? lstrlenW (part->text) : 0;
398 result |= (part->style << 16);
399 if (lParam && LOWORD(result))
400 lstrcpyWtoA ((LPSTR)lParam, part->text);
402 return result;
406 static LRESULT
407 STATUSBAR_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
409 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
410 STATUSWINDOWPART *part;
411 INT nPart;
412 LRESULT result;
414 nPart = ((INT)wParam) & 0x00ff;
415 if (infoPtr->simple)
416 part = &infoPtr->part0;
417 else
418 part = &infoPtr->parts[nPart];
420 if (part->style & SBT_OWNERDRAW)
421 result = (LRESULT)part->text;
422 else {
423 result = part->text ? lstrlenW (part->text) : 0;
424 result |= (part->style << 16);
425 if (lParam)
426 strcpyW ((LPWSTR)lParam, part->text);
428 return result;
432 static LRESULT
433 STATUSBAR_GetTextLength (HWND hwnd, WPARAM wParam)
435 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
436 STATUSWINDOWPART *part;
437 INT part_num;
438 DWORD result;
440 part_num = ((INT) wParam) & 0x00ff;
442 if (infoPtr->simple)
443 part = &infoPtr->part0;
444 else
445 part = &infoPtr->parts[part_num];
447 if (part->text)
448 result = lstrlenW(part->text);
449 else
450 result = 0;
452 result |= (part->style << 16);
453 return result;
457 static LRESULT
458 STATUSBAR_GetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
460 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
462 if (infoPtr->hwndToolTip) {
463 TTTOOLINFOA ti;
464 ti.cbSize = sizeof(TTTOOLINFOA);
465 ti.hwnd = hwnd;
466 ti.uId = LOWORD(wParam);
467 SendMessageA (infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
469 if (ti.lpszText)
470 lstrcpynA ((LPSTR)lParam, ti.lpszText, HIWORD(wParam));
473 return 0;
477 static LRESULT
478 STATUSBAR_GetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
480 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
482 if (infoPtr->hwndToolTip) {
483 TTTOOLINFOW ti;
484 ti.cbSize = sizeof(TTTOOLINFOW);
485 ti.hwnd = hwnd;
486 ti.uId = LOWORD(wParam);
487 SendMessageW (infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
489 if (ti.lpszText)
490 lstrcpynW ((LPWSTR)lParam, ti.lpszText, HIWORD(wParam));
493 return 0;
497 inline static LRESULT
498 STATUSBAR_GetUnicodeFormat (HWND hwnd)
500 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
501 return infoPtr->bUnicode;
505 inline static LRESULT
506 STATUSBAR_IsSimple (HWND hwnd)
508 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
509 return infoPtr->simple;
513 static LRESULT
514 STATUSBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
516 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
517 COLORREF oldBkColor;
519 oldBkColor = self->clrBk;
520 self->clrBk = (COLORREF)lParam;
521 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
523 return oldBkColor;
527 static LRESULT
528 STATUSBAR_SetIcon (HWND hwnd, WPARAM wParam, LPARAM lParam)
530 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
531 INT nPart = (INT)wParam & 0x00ff;
533 if ((nPart < -1) || (nPart >= self->numParts))
534 return FALSE;
536 TRACE("setting part %d, icon %lx\n",nPart,lParam);
538 if (nPart == -1) {
539 if (self->part0.hIcon == (HICON)lParam) /* same as - no redraw */
540 return TRUE;
541 self->part0.hIcon = (HICON)lParam;
542 if (self->simple)
543 RedrawWindow(hwnd, &self->part0.bound,(HRGN)NULL,
544 RDW_INVALIDATE|RDW_UPDATENOW);
545 } else {
546 if (self->parts[nPart].hIcon == (HICON)lParam) /* same as - no redraw */
547 return TRUE;
549 self->parts[nPart].hIcon = (HICON)lParam;
550 if (!(self->simple))
551 RedrawWindow(hwnd,&self->parts[nPart].bound,(HRGN)NULL,
552 RDW_INVALIDATE|RDW_UPDATENOW);
554 return TRUE;
558 static LRESULT
559 STATUSBAR_SetMinHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
561 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
563 if (IsWindowVisible (hwnd)) {
564 HWND parent = GetParent (hwnd);
565 INT width, x, y;
566 RECT parent_rect;
568 GetClientRect (parent, &parent_rect);
569 self->height = (INT)wParam + VERT_BORDER;
570 width = parent_rect.right - parent_rect.left;
571 x = parent_rect.left;
572 y = parent_rect.bottom - self->height;
573 MoveWindow (hwnd, parent_rect.left,
574 parent_rect.bottom - self->height,
575 width, self->height, TRUE);
576 STATUSBAR_SetPartBounds (hwnd);
579 return TRUE;
583 static LRESULT
584 STATUSBAR_SetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
586 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
587 STATUSWINDOWPART *tmp;
588 LPINT parts;
589 int i;
590 int oldNumParts;
592 TRACE("(%d,%p)\n",wParam,(LPVOID)lParam);
594 if (self->simple)
595 self->simple = FALSE;
597 oldNumParts = self->numParts;
598 self->numParts = (INT) wParam;
599 parts = (LPINT) lParam;
600 if (oldNumParts > self->numParts) {
601 for (i = self->numParts ; i < oldNumParts; i++) {
602 if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
603 COMCTL32_Free (self->parts[i].text);
606 if (oldNumParts < self->numParts) {
607 tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
608 for (i = 0; i < oldNumParts; i++) {
609 tmp[i] = self->parts[i];
611 if (self->parts)
612 COMCTL32_Free (self->parts);
613 self->parts = tmp;
615 if (oldNumParts == self->numParts) {
616 for (i=0;i<oldNumParts;i++)
617 if (self->parts[i].x != parts[i])
618 break;
619 if (i==oldNumParts) /* Unchanged? no need to redraw! */
620 return TRUE;
623 for (i = 0; i < self->numParts; i++)
624 self->parts[i].x = parts[i];
626 if (self->hwndToolTip) {
627 INT nTipCount =
628 SendMessageA (self->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
630 if (nTipCount < self->numParts) {
631 /* add tools */
632 TTTOOLINFOA ti;
633 INT i;
635 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
636 ti.cbSize = sizeof(TTTOOLINFOA);
637 ti.hwnd = hwnd;
638 for (i = nTipCount; i < self->numParts; i++) {
639 TRACE("add tool %d\n", i);
640 ti.uId = i;
641 SendMessageA (self->hwndToolTip, TTM_ADDTOOLA,
642 0, (LPARAM)&ti);
645 else if (nTipCount > self->numParts) {
646 /* delete tools */
647 INT i;
649 for (i = nTipCount - 1; i >= self->numParts; i--) {
650 FIXME("delete tool %d\n", i);
654 STATUSBAR_SetPartBounds (hwnd);
655 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
656 return TRUE;
660 static LRESULT
661 STATUSBAR_SetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
663 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
664 STATUSWINDOWPART *part=NULL;
665 int part_num;
666 int style;
667 LPSTR text;
668 BOOL changed = FALSE;
670 text = (LPSTR) lParam;
671 part_num = ((INT) wParam) & 0x00ff;
672 style = ((INT) wParam) & 0xff00;
674 TRACE("setting part %d, text %s\n",part_num,debugstr_a(text));
676 if (part_num==255)
677 part = &self->part0;
678 else if (!self->simple && self->parts!=NULL)
679 part = &self->parts[part_num];
680 if (!part) return FALSE;
682 if (part->style != style)
683 changed = TRUE;
685 part->style = style;
686 if (style & SBT_OWNERDRAW) {
687 if (part->text == (LPWSTR)text)
688 return TRUE;
689 part->text = (LPWSTR)text;
690 } else {
691 LPWSTR ntext;
693 /* check if text is unchanged -> no need to redraw */
694 if (text) {
695 LPWSTR tmptext = COMCTL32_Alloc((lstrlenA(text)+1)*sizeof(WCHAR));
696 lstrcpyAtoW (tmptext, text);
698 if (!changed && part->text && !lstrcmpW(tmptext,part->text)) {
699 COMCTL32_Free(tmptext);
700 return TRUE;
702 ntext = tmptext;
703 } else {
704 if (!changed && !part->text)
705 return TRUE;
706 ntext = 0;
709 if (part->text)
710 COMCTL32_Free (part->text);
711 part->text = ntext;
713 RedrawWindow(hwnd,&part->bound,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
715 return TRUE;
719 static LRESULT
720 STATUSBAR_SetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
722 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
723 STATUSWINDOWPART *part;
724 INT part_num, style, len;
725 LPWSTR text;
727 text = (LPWSTR) lParam;
728 part_num = ((INT) wParam) & 0x00ff;
729 style = ((INT) wParam) & 0xff00;
731 if ((self->simple) || (self->parts==NULL) || (part_num==255))
732 part = &self->part0;
733 else
734 part = &self->parts[part_num];
735 if (!part) return FALSE;
737 if (!(part->style & SBT_OWNERDRAW) && part->text)
738 COMCTL32_Free (part->text);
739 part->text = 0;
741 /* FIXME: add "no need to redraw logic" */
742 if (style & SBT_OWNERDRAW) {
743 part->text = text;
744 } else {
745 /* duplicate string */
746 if (text && (len = lstrlenW(text))) {
747 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
748 strcpyW(part->text, text);
751 part->style = style;
753 RedrawWindow(hwnd,&part->bound,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
755 return TRUE;
759 static LRESULT
760 STATUSBAR_SetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
762 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
764 TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
765 if (infoPtr->hwndToolTip) {
766 TTTOOLINFOA ti;
767 ti.cbSize = sizeof(TTTOOLINFOA);
768 ti.hwnd = hwnd;
769 ti.uId = (INT)wParam;
770 ti.hinst = 0;
771 ti.lpszText = (LPSTR)lParam;
772 SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
773 0, (LPARAM)&ti);
776 return 0;
780 static LRESULT
781 STATUSBAR_SetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
783 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
785 TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
786 if (infoPtr->hwndToolTip) {
787 TTTOOLINFOW ti;
788 ti.cbSize = sizeof(TTTOOLINFOW);
789 ti.hwnd = hwnd;
790 ti.uId = (INT)wParam;
791 ti.hinst = 0;
792 ti.lpszText = (LPWSTR)lParam;
793 SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW,
794 0, (LPARAM)&ti);
797 return 0;
801 inline static LRESULT
802 STATUSBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
804 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
805 BOOL bTemp = infoPtr->bUnicode;
807 TRACE("(0x%x)\n", (BOOL)wParam);
808 infoPtr->bUnicode = (BOOL)wParam;
810 return bTemp;
814 static LRESULT
815 STATUSBAR_Simple (HWND hwnd, WPARAM wParam, LPARAM lParam)
817 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
818 NMHDR nmhdr;
820 if (infoPtr->simple == wParam) /* no need to change */
821 return TRUE;
823 infoPtr->simple = (BOOL)wParam;
825 /* send notification */
826 nmhdr.hwndFrom = hwnd;
827 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
828 nmhdr.code = SBN_SIMPLEMODECHANGE;
829 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
830 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
831 return TRUE;
835 static LRESULT
836 STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
838 LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
839 NONCLIENTMETRICSA nclm;
840 RECT rect;
841 int width, len;
842 HDC hdc;
843 STATUSWINDOWINFO *self;
845 self = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
846 SetWindowLongA (hwnd, 0, (DWORD)self);
848 self->numParts = 1;
849 self->parts = 0;
850 self->simple = FALSE;
851 self->clrBk = CLR_DEFAULT;
852 self->hFont = 0;
853 GetClientRect (hwnd, &rect);
855 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
856 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
857 self->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
859 /* initialize simple case */
860 self->part0.bound = rect;
861 self->part0.text = 0;
862 self->part0.x = 0;
863 self->part0.style = 0;
864 self->part0.hIcon = 0;
866 /* initialize first part */
867 self->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
868 self->parts[0].bound = rect;
869 self->parts[0].text = 0;
870 self->parts[0].x = -1;
871 self->parts[0].style = 0;
872 self->parts[0].hIcon = 0;
874 if (IsWindowUnicode (hwnd)) {
875 self->bUnicode = TRUE;
876 if (lpCreate->lpszName &&
877 (len = lstrlenW ((LPCWSTR)lpCreate->lpszName))) {
878 self->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
879 strcpyW (self->parts[0].text, (LPCWSTR)lpCreate->lpszName);
882 else {
883 if (lpCreate->lpszName &&
884 (len = lstrlenA ((LPCSTR)lpCreate->lpszName))) {
885 self->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
886 lstrcpyAtoW (self->parts[0].text, (LPCSTR)lpCreate->lpszName);
890 if ((hdc = GetDC (0))) {
891 TEXTMETRICA tm;
892 HFONT hOldFont;
894 hOldFont = SelectObject (hdc,self->hDefaultFont);
895 GetTextMetricsA(hdc, &tm);
896 self->textHeight = tm.tmHeight;
897 SelectObject (hdc, hOldFont);
898 ReleaseDC(0, hdc);
901 if (GetWindowLongA (hwnd, GWL_STYLE) & SBT_TOOLTIPS) {
902 self->hwndToolTip =
903 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
904 CW_USEDEFAULT, CW_USEDEFAULT,
905 CW_USEDEFAULT, CW_USEDEFAULT,
906 hwnd, 0,
907 GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
909 if (self->hwndToolTip) {
910 NMTOOLTIPSCREATED nmttc;
912 nmttc.hdr.hwndFrom = hwnd;
913 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
914 nmttc.hdr.code = NM_TOOLTIPSCREATED;
915 nmttc.hwndToolTips = self->hwndToolTip;
917 SendMessageA (GetParent (hwnd), WM_NOTIFY,
918 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
922 GetClientRect (GetParent (hwnd), &rect);
923 width = rect.right - rect.left;
924 self->height = self->textHeight + 4 + VERT_BORDER;
925 MoveWindow (hwnd, lpCreate->x, lpCreate->y-1,
926 width, self->height, FALSE);
927 STATUSBAR_SetPartBounds (hwnd);
929 return 0;
933 static LRESULT
934 STATUSBAR_WMDestroy (HWND hwnd)
936 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
937 int i;
939 for (i = 0; i < self->numParts; i++) {
940 if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
941 COMCTL32_Free (self->parts[i].text);
943 if (self->part0.text && !(self->part0.style & SBT_OWNERDRAW))
944 COMCTL32_Free (self->part0.text);
945 COMCTL32_Free (self->parts);
947 /* delete default font */
948 if (self->hDefaultFont)
949 DeleteObject (self->hDefaultFont);
951 /* delete tool tip control */
952 if (self->hwndToolTip)
953 DestroyWindow (self->hwndToolTip);
955 COMCTL32_Free (self);
956 SetWindowLongA(hwnd, 0, 0);
957 return 0;
961 static inline LRESULT
962 STATUSBAR_WMGetFont (HWND hwnd)
964 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
965 return infoPtr->hFont;
969 static LRESULT
970 STATUSBAR_WMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
972 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
973 INT len;
975 if (!(infoPtr->parts[0].text))
976 return 0;
977 len = lstrlenW (infoPtr->parts[0].text);
978 if (wParam > len) {
979 if (infoPtr->bUnicode)
980 strcpyW ((LPWSTR)lParam, infoPtr->parts[0].text);
981 else
982 lstrcpyWtoA ((LPSTR)lParam, infoPtr->parts[0].text);
983 return len;
986 return -1;
990 inline static LRESULT
991 STATUSBAR_WMMouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
993 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
995 if (infoPtr->hwndToolTip)
996 STATUSBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
997 WM_MOUSEMOVE, wParam, lParam);
998 return 0;
1002 static LRESULT
1003 STATUSBAR_WMNCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1005 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
1006 RECT rect;
1007 POINT pt;
1009 GetClientRect (hwnd, &rect);
1011 pt.x = (INT)LOWORD(lParam);
1012 pt.y = (INT)HIWORD(lParam);
1013 ScreenToClient (hwnd, &pt);
1015 rect.left = rect.right - 13;
1016 rect.top += 2;
1018 if (PtInRect (&rect, pt))
1019 return HTBOTTOMRIGHT;
1022 return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
1026 static inline LRESULT
1027 STATUSBAR_WMNCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1029 PostMessageA (GetParent (hwnd), WM_NCLBUTTONDOWN, wParam, lParam);
1030 return 0;
1034 static inline LRESULT
1035 STATUSBAR_WMNCLButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1037 PostMessageA (GetParent (hwnd), WM_NCLBUTTONUP, wParam, lParam);
1038 return 0;
1042 static LRESULT
1043 STATUSBAR_WMPaint (HWND hwnd, WPARAM wParam)
1045 HDC hdc;
1046 PAINTSTRUCT ps;
1048 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1049 STATUSBAR_Refresh (hwnd, hdc);
1050 if (!wParam)
1051 EndPaint (hwnd, &ps);
1053 return 0;
1057 static LRESULT
1058 STATUSBAR_WMSetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1060 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1062 infoPtr->hFont = (HFONT)wParam;
1063 if (LOWORD(lParam) == TRUE)
1064 RedrawWindow(hwnd,(RECT*)NULL,(HRGN)NULL,
1065 RDW_INVALIDATE|RDW_UPDATENOW);
1067 return 0;
1071 static LRESULT
1072 STATUSBAR_WMSetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
1074 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1075 STATUSWINDOWPART *part;
1076 int len;
1078 if (infoPtr->numParts == 0)
1079 return FALSE;
1081 part = &infoPtr->parts[0];
1082 /* duplicate string */
1083 if (part->text)
1084 COMCTL32_Free (part->text);
1085 part->text = 0;
1086 if (infoPtr->bUnicode) {
1087 if (lParam && (len = lstrlenW((LPCWSTR)lParam))) {
1088 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1089 strcpyW (part->text, (LPCWSTR)lParam);
1092 else {
1093 if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
1094 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1095 lstrcpyAtoW (part->text, (LPCSTR)lParam);
1099 RedrawWindow(hwnd,&part->bound,(HRGN)NULL,RDW_INVALIDATE|RDW_UPDATENOW);
1101 return TRUE;
1105 static LRESULT
1106 STATUSBAR_WMSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1108 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1109 INT width, x, y, flags;
1110 RECT parent_rect;
1111 HWND parent;
1113 /* Need to resize width to match parent */
1114 flags = (INT) wParam;
1116 /* FIXME for flags =
1117 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
1120 if (flags == SIZE_RESTORED) {
1121 /* width and height don't apply */
1122 parent = GetParent (hwnd);
1123 GetClientRect (parent, &parent_rect);
1124 width = parent_rect.right - parent_rect.left;
1125 x = parent_rect.left;
1126 y = parent_rect.bottom - infoPtr->height;
1127 MoveWindow (hwnd, parent_rect.left,
1128 parent_rect.bottom - infoPtr->height,
1129 width, infoPtr->height, TRUE);
1130 STATUSBAR_SetPartBounds (hwnd);
1132 return 0;
1136 static LRESULT
1137 STATUSBAR_SendNotify (HWND hwnd, UINT code)
1139 NMHDR nmhdr;
1141 nmhdr.hwndFrom = hwnd;
1142 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1143 nmhdr.code = code;
1144 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
1145 return 0;
1150 static LRESULT WINAPI
1151 StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1153 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, msg, wParam, lParam);
1154 if (!(STATUSBAR_GetInfoPtr(hwnd)) && (msg != WM_CREATE))
1155 return DefWindowProcA (hwnd, msg, wParam, lParam);
1157 switch (msg) {
1158 case SB_GETBORDERS:
1159 return STATUSBAR_GetBorders (lParam);
1161 case SB_GETICON:
1162 return STATUSBAR_GetIcon (hwnd, wParam);
1164 case SB_GETPARTS:
1165 return STATUSBAR_GetParts (hwnd, wParam, lParam);
1167 case SB_GETRECT:
1168 return STATUSBAR_GetRect (hwnd, wParam, lParam);
1170 case SB_GETTEXTA:
1171 return STATUSBAR_GetTextA (hwnd, wParam, lParam);
1173 case SB_GETTEXTW:
1174 return STATUSBAR_GetTextW (hwnd, wParam, lParam);
1176 case SB_GETTEXTLENGTHA:
1177 case SB_GETTEXTLENGTHW:
1178 return STATUSBAR_GetTextLength (hwnd, wParam);
1180 case SB_GETTIPTEXTA:
1181 return STATUSBAR_GetTipTextA (hwnd, wParam, lParam);
1183 case SB_GETTIPTEXTW:
1184 return STATUSBAR_GetTipTextW (hwnd, wParam, lParam);
1186 case SB_GETUNICODEFORMAT:
1187 return STATUSBAR_GetUnicodeFormat (hwnd);
1189 case SB_ISSIMPLE:
1190 return STATUSBAR_IsSimple (hwnd);
1192 case SB_SETBKCOLOR:
1193 return STATUSBAR_SetBkColor (hwnd, wParam, lParam);
1195 case SB_SETICON:
1196 return STATUSBAR_SetIcon (hwnd, wParam, lParam);
1198 case SB_SETMINHEIGHT:
1199 return STATUSBAR_SetMinHeight (hwnd, wParam, lParam);
1201 case SB_SETPARTS:
1202 return STATUSBAR_SetParts (hwnd, wParam, lParam);
1204 case SB_SETTEXTA:
1205 return STATUSBAR_SetTextA (hwnd, wParam, lParam);
1207 case SB_SETTEXTW:
1208 return STATUSBAR_SetTextW (hwnd, wParam, lParam);
1210 case SB_SETTIPTEXTA:
1211 return STATUSBAR_SetTipTextA (hwnd, wParam, lParam);
1213 case SB_SETTIPTEXTW:
1214 return STATUSBAR_SetTipTextW (hwnd, wParam, lParam);
1216 case SB_SETUNICODEFORMAT:
1217 return STATUSBAR_SetUnicodeFormat (hwnd, wParam);
1219 case SB_SIMPLE:
1220 return STATUSBAR_Simple (hwnd, wParam, lParam);
1223 case WM_CREATE:
1224 return STATUSBAR_WMCreate (hwnd, wParam, lParam);
1226 case WM_DESTROY:
1227 return STATUSBAR_WMDestroy (hwnd);
1229 case WM_GETFONT:
1230 return STATUSBAR_WMGetFont (hwnd);
1232 case WM_GETTEXT:
1233 return STATUSBAR_WMGetText (hwnd, wParam, lParam);
1235 case WM_GETTEXTLENGTH:
1236 return STATUSBAR_GetTextLength (hwnd, 0);
1238 case WM_LBUTTONDBLCLK:
1239 return STATUSBAR_SendNotify (hwnd, NM_DBLCLK);
1241 case WM_LBUTTONUP:
1242 return STATUSBAR_SendNotify (hwnd, NM_CLICK);
1244 case WM_MOUSEMOVE:
1245 return STATUSBAR_WMMouseMove (hwnd, wParam, lParam);
1247 case WM_NCHITTEST:
1248 return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
1250 case WM_NCLBUTTONDOWN:
1251 return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
1253 case WM_NCLBUTTONUP:
1254 return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
1256 case WM_PAINT:
1257 return STATUSBAR_WMPaint (hwnd, wParam);
1259 case WM_RBUTTONDBLCLK:
1260 return STATUSBAR_SendNotify (hwnd, NM_RDBLCLK);
1262 case WM_RBUTTONUP:
1263 return STATUSBAR_SendNotify (hwnd, NM_RCLICK);
1265 case WM_SETFONT:
1266 return STATUSBAR_WMSetFont (hwnd, wParam, lParam);
1268 case WM_SETTEXT:
1269 return STATUSBAR_WMSetText (hwnd, wParam, lParam);
1271 case WM_SIZE:
1272 return STATUSBAR_WMSize (hwnd, wParam, lParam);
1274 default:
1275 if (msg >= WM_USER)
1276 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1277 msg, wParam, lParam);
1278 return DefWindowProcA (hwnd, msg, wParam, lParam);
1280 return 0;
1284 /***********************************************************************
1285 * STATUS_Register [Internal]
1287 * Registers the status window class.
1290 VOID
1291 STATUS_Register (void)
1293 WNDCLASSA wndClass;
1295 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1296 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1297 wndClass.lpfnWndProc = (WNDPROC)StatusWindowProc;
1298 wndClass.cbClsExtra = 0;
1299 wndClass.cbWndExtra = sizeof(STATUSWINDOWINFO *);
1300 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1301 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1302 wndClass.lpszClassName = STATUSCLASSNAMEA;
1304 RegisterClassA (&wndClass);
1308 /***********************************************************************
1309 * STATUS_Unregister [Internal]
1311 * Unregisters the status window class.
1314 VOID
1315 STATUS_Unregister (void)
1317 UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);