source: trunk/src/comctl32/status.c@ 1330

Last change on this file since 1330 was 1058, checked in by achimha, 26 years ago

merged latest WINE 990923 changes

File size: 32.1 KB
Line 
1/* $Id: status.c,v 1.11 1999-09-26 11:01:10 achimha Exp $ */
2/*
3 * Interface code to StatusWindow widget/control
4 *
5 * Copyright 1996 Bruce Milner
6 * Copyright 1998, 1999 Eric Kohl
7 * Copyright 1999 Achim Hasenmueller
8 * Copyright 1999 Christoph Bratschi
9 */
10
11/* WINE 990923 level */
12
13#include "winbase.h"
14#include "commctrl.h"
15#include "comctl32.h"
16#include "status.h"
17#include <string.h>
18
19/*
20 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
21 * The second cdrom contains executables drawstat.exe,gettext.exe,
22 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
23 */
24
25/*
26 * Fixme/Todo
27 * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
28 * 2) Tooltip support (almost done).
29 */
30
31/* CB: Odin problems
32 - DrawText: DT_VCENTER doesn't work
33*/
34
35#define _MAX(a,b) (((a)>(b))?(a):(b))
36#define _MIN(a,b) (((a)>(b))?(b):(a))
37
38#define HORZ_BORDER 0
39#define VERT_BORDER 2
40#define VERT_SPACE 2 //space between boder and text
41#define HORZ_GAP 2
42#define TOP_MARGIN 2
43#define ICON_SPACE 2
44#define TEXT_SPACE 3
45
46#define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
47
48
49static void
50STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
51{
52 HPEN hOldPen;
53 POINT pt;
54 INT i;
55
56 pt.x = lpRect->right - 1;
57 pt.y = lpRect->bottom - 1;
58
59 hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
60 MoveToEx (hdc, pt.x - 12, pt.y, NULL);
61 LineTo (hdc, pt.x, pt.y);
62 LineTo (hdc, pt.x, pt.y - 12);
63
64 pt.x--;
65 pt.y--;
66
67 SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
68 for (i = 1; i < 11; i += 4) {
69 MoveToEx (hdc, pt.x - i, pt.y, NULL);
70 LineTo (hdc, pt.x, pt.y - i);
71
72 MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
73 LineTo (hdc, pt.x, pt.y - i-1);
74 }
75
76 SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
77 for (i = 3; i < 13; i += 4) {
78 MoveToEx (hdc, pt.x - i, pt.y, NULL);
79 LineTo (hdc, pt.x, pt.y - i);
80 }
81
82 SelectObject (hdc, hOldPen);
83}
84
85
86static void
87STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
88{
89 RECT r = part->bound;
90 UINT border = BDR_SUNKENOUTER;
91
92 if (part->style & SBT_POPOUT)
93 border = BDR_RAISEDOUTER;
94 else if (part->style & SBT_NOBORDERS)
95 border = 0;
96
97 DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
98
99 r.bottom -= VERT_SPACE;
100 r.top += VERT_SPACE;
101
102 /* draw the icon */
103 if (part->hIcon) {
104 INT cy = r.bottom - r.top;
105
106 r.left += ICON_SPACE;
107 DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
108 r.left += cy;
109 }
110
111 /* now draw text */
112 if (part->text) {
113 int oldbkmode = SetBkMode(hdc, TRANSPARENT);
114 LPWSTR p = (LPWSTR)part->text;
115 UINT align = DT_LEFT;
116 if (*p == L'\t') {
117 p++;
118 align = DT_CENTER;
119
120 if (*p == L'\t') {
121 p++;
122 align = DT_RIGHT;
123 }
124 }
125 r.left += TEXT_SPACE;
126 DrawTextW (hdc, p, lstrlenW (p), &r, align|DT_VCENTER|DT_SINGLELINE);
127 if (oldbkmode != TRANSPARENT)
128 SetBkMode(hdc, oldbkmode);
129 }
130}
131
132
133static VOID
134STATUSBAR_RefreshPart (HWND hwnd, STATUSWINDOWPART *part, HDC hdc)
135{
136 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
137 HBRUSH hbrBk;
138 HFONT hOldFont;
139
140 if (!IsWindowVisible (hwnd))
141 return;
142
143 if (self->clrBk != CLR_DEFAULT)
144 hbrBk = CreateSolidBrush (self->clrBk);
145 else
146 hbrBk = GetSysColorBrush (COLOR_3DFACE);
147 FillRect(hdc, &part->bound, hbrBk);
148
149 hOldFont = SelectObject (hdc, self->hFont ? self->hFont : self->hDefaultFont);
150
151 if (part->style & SBT_OWNERDRAW) {
152 DRAWITEMSTRUCT dis;
153
154 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
155 dis.itemID = -1;
156 dis.hwndItem = hwnd;
157 dis.hDC = hdc;
158 dis.rcItem = part->bound;
159 dis.itemData = (INT)part->text;
160 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
161 (WPARAM)dis.CtlID, (LPARAM)&dis);
162 }
163 else
164 STATUSBAR_DrawPart (hdc, part);
165
166 SelectObject (hdc, hOldFont);
167
168 if (self->clrBk != CLR_DEFAULT)
169 DeleteObject (hbrBk);
170
171 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
172 RECT rect;
173
174 GetClientRect (hwnd, &rect);
175 STATUSBAR_DrawSizeGrip (hdc, &rect);
176 }
177}
178
179
180static BOOL
181STATUSBAR_Refresh (HWND hwnd, HDC hdc)
182{
183 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
184 int i;
185 RECT rect;
186 HBRUSH hbrBk;
187 HFONT hOldFont;
188
189 if (!IsWindowVisible(hwnd))
190 return (TRUE);
191
192 GetClientRect (hwnd, &rect);
193
194 if (infoPtr->clrBk != CLR_DEFAULT)
195 hbrBk = CreateSolidBrush (infoPtr->clrBk);
196 else
197 hbrBk = GetSysColorBrush (COLOR_3DFACE);
198 FillRect(hdc, &rect, hbrBk);
199
200 hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
201
202 if (infoPtr->simple) {
203 STATUSBAR_DrawPart (hdc, &infoPtr->part0);
204 }
205 else {
206 for (i = 0; i < infoPtr->numParts; i++) {
207 if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
208 DRAWITEMSTRUCT dis;
209
210 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
211 dis.itemID = -1;
212 dis.hwndItem = hwnd;
213 dis.hDC = hdc;
214 dis.rcItem = infoPtr->parts[i].bound;
215 dis.itemData = (INT)infoPtr->parts[i].text;
216 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
217 (WPARAM)dis.CtlID, (LPARAM)&dis);
218 }
219 else
220 STATUSBAR_DrawPart (hdc, &infoPtr->parts[i]);
221 }
222 }
223
224 SelectObject (hdc, hOldFont);
225
226 if (infoPtr->clrBk != CLR_DEFAULT)
227 DeleteObject (hbrBk);
228
229 if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
230 STATUSBAR_DrawSizeGrip (hdc, &rect);
231
232 return TRUE;
233}
234
235
236static void
237STATUSBAR_SetPartBounds (HWND hwnd)
238{
239 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
240 STATUSWINDOWPART *part;
241 RECT rect, *r;
242 int i;
243
244 /* get our window size */
245 GetClientRect (hwnd, &rect);
246
247 rect.top += TOP_MARGIN;
248
249 /* set bounds for simple rectangle */
250 self->part0.bound = rect;
251
252 /* set bounds for non-simple rectangles */
253 for (i = 0; i < self->numParts; i++) {
254 part = &self->parts[i];
255 r = &self->parts[i].bound;
256 r->top = rect.top;
257 r->bottom = rect.bottom;
258 if (i == 0)
259 r->left = 0;
260 else
261 r->left = self->parts[i-1].bound.right + HORZ_GAP;
262 if (part->x == -1)
263 r->right = rect.right;
264 else
265 r->right = part->x;
266
267 if (self->hwndToolTip) {
268 TTTOOLINFOA ti;
269
270 ti.cbSize = sizeof(TTTOOLINFOA);
271 ti.hwnd = hwnd;
272 ti.uId = i;
273 ti.rect = *r;
274 SendMessageA (self->hwndToolTip, TTM_NEWTOOLRECTA,
275 0, (LPARAM)&ti);
276 }
277 }
278}
279
280
281static VOID
282STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
283 WPARAM wParam, LPARAM lParam)
284{
285 MSG msg;
286
287 msg.hwnd = hwndMsg;
288 msg.message = uMsg;
289 msg.wParam = wParam;
290 msg.lParam = lParam;
291 msg.time = GetMessageTime ();
292 msg.pt.x = LOWORD(GetMessagePos ());
293 msg.pt.y = HIWORD(GetMessagePos ());
294
295 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
296}
297
298
299static LRESULT
300STATUSBAR_GetBorders (LPARAM lParam)
301{
302 LPINT out = (LPINT) lParam;
303
304 out[0] = HORZ_BORDER; /* horizontal border width */
305 out[1] = VERT_BORDER; /* vertical border width */
306 out[2] = HORZ_GAP; /* width of border between rectangles */
307
308 return TRUE;
309}
310
311
312static LRESULT
313STATUSBAR_GetIcon (HWND hwnd, WPARAM wParam)
314{
315 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
316 INT nPart;
317
318 nPart = (INT)wParam & 0x00ff;
319 if ((nPart < -1) || (nPart >= self->numParts))
320 return 0;
321
322 if (nPart == -1)
323 return (self->part0.hIcon);
324 else
325 return (self->parts[nPart].hIcon);
326}
327
328
329static LRESULT
330STATUSBAR_GetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
331{
332 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
333 LPINT parts;
334 INT num_parts;
335 INT i;
336
337 num_parts = (INT) wParam;
338 parts = (LPINT) lParam;
339 if (parts) {
340 return (infoPtr->numParts);
341 for (i = 0; i < num_parts; i++) {
342 parts[i] = infoPtr->parts[i].x;
343 }
344 }
345 return (infoPtr->numParts);
346}
347
348
349static LRESULT
350STATUSBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
351{
352 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
353 int part_num;
354 LPRECT rect;
355
356 part_num = ((INT) wParam) & 0x00ff;
357 rect = (LPRECT) lParam;
358 if (infoPtr->simple)
359 *rect = infoPtr->part0.bound;
360 else
361 *rect = infoPtr->parts[part_num].bound;
362 return TRUE;
363}
364
365
366static LRESULT
367STATUSBAR_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
368{
369 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
370 STATUSWINDOWPART *part;
371 INT nPart;
372 LRESULT result;
373
374 nPart = ((INT) wParam) & 0x00ff;
375 if (self->simple)
376 part = &self->part0;
377 else
378 part = &self->parts[nPart];
379
380 if (part->style & SBT_OWNERDRAW)
381 result = (LRESULT)part->text;
382 else {
383 result = part->text ? lstrlenW (part->text) : 0;
384 result |= (part->style << 16);
385 if (lParam && LOWORD(result))
386 lstrcpyWtoA((LPSTR)lParam, part->text);
387 }
388 return result;
389}
390
391
392static LRESULT
393STATUSBAR_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
394{
395 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
396 STATUSWINDOWPART *part;
397 INT nPart;
398 LRESULT result;
399
400 nPart = ((INT)wParam) & 0x00ff;
401 if (infoPtr->simple)
402 part = &infoPtr->part0;
403 else
404 part = &infoPtr->parts[nPart];
405
406 if (part->style & SBT_OWNERDRAW)
407 result = (LRESULT)part->text;
408 else {
409 result = part->text ? lstrlenW (part->text) : 0;
410 result |= (part->style << 16);
411 if (lParam)
412 lstrcpyW ((LPWSTR)lParam, part->text);
413 }
414 return result;
415}
416
417
418static LRESULT
419STATUSBAR_GetTextLength (HWND hwnd, WPARAM wParam)
420{
421 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
422 STATUSWINDOWPART *part;
423 INT part_num;
424 DWORD result;
425
426 part_num = ((INT) wParam) & 0x00ff;
427
428 if (infoPtr->simple)
429 part = &infoPtr->part0;
430 else
431 part = &infoPtr->parts[part_num];
432
433 if (part->text)
434 result = lstrlenW(part->text);
435 else
436 result = 0;
437
438 result |= (part->style << 16);
439 return result;
440}
441
442
443static LRESULT
444STATUSBAR_GetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
445{
446 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
447
448 if (infoPtr->hwndToolTip) {
449 TTTOOLINFOA ti;
450 ti.cbSize = sizeof(TTTOOLINFOA);
451 ti.hwnd = hwnd;
452 ti.uId = LOWORD(wParam);
453 SendMessageA (infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
454
455 if (ti.lpszText)
456 lstrcpynA ((LPSTR)lParam, ti.lpszText, HIWORD(wParam));
457 }
458
459 return 0;
460}
461
462
463static LRESULT
464STATUSBAR_GetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
465{
466 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
467
468 if (infoPtr->hwndToolTip) {
469 TTTOOLINFOW ti;
470 ti.cbSize = sizeof(TTTOOLINFOW);
471 ti.hwnd = hwnd;
472 ti.uId = LOWORD(wParam);
473 SendMessageW (infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
474
475 if (ti.lpszText)
476 lstrcpynW ((LPWSTR)lParam, ti.lpszText, HIWORD(wParam));
477 }
478
479 return 0;
480}
481
482
483static LRESULT
484STATUSBAR_GetUnicodeFormat (HWND hwnd)
485{
486 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
487 return infoPtr->bUnicode;
488}
489
490
491static LRESULT
492STATUSBAR_IsSimple (HWND hwnd)
493{
494 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
495 return infoPtr->simple;
496}
497
498
499static LRESULT
500STATUSBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
501{
502 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
503 COLORREF oldBkColor;
504 HDC hdc;
505
506 oldBkColor = self->clrBk;
507 self->clrBk = (COLORREF)lParam;
508 hdc = GetDC (hwnd);
509 STATUSBAR_Refresh (hwnd, hdc);
510 ReleaseDC (hwnd, hdc);
511
512 return oldBkColor;
513}
514
515
516static LRESULT
517STATUSBAR_SetIcon (HWND hwnd, WPARAM wParam, LPARAM lParam)
518{
519 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
520 INT nPart = (INT)wParam & 0x00ff;
521 HDC hdc;
522
523 if ((nPart < -1) || (nPart >= self->numParts))
524 return FALSE;
525
526 hdc = GetDC (hwnd);
527 if (nPart == -1) {
528 self->part0.hIcon = (HICON)lParam;
529 if (self->simple)
530 STATUSBAR_RefreshPart (hwnd, &self->part0, hdc);
531 }
532 else {
533 self->parts[nPart].hIcon = (HICON)lParam;
534 if (!(self->simple))
535 STATUSBAR_RefreshPart (hwnd, &self->parts[nPart], hdc);
536 }
537 ReleaseDC (hwnd, hdc);
538
539 return TRUE;
540}
541
542
543static LRESULT
544STATUSBAR_SetMinHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
545{
546 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
547
548 if (IsWindowVisible (hwnd)) {
549 HWND parent = GetParent (hwnd);
550 INT width, x, y;
551 RECT parent_rect;
552
553 GetClientRect (parent, &parent_rect);
554 self->height = (INT)wParam + VERT_BORDER;
555 width = parent_rect.right - parent_rect.left;
556 x = parent_rect.left;
557 y = parent_rect.bottom - self->height;
558 MoveWindow (hwnd, parent_rect.left,
559 parent_rect.bottom - self->height,
560 width, self->height, TRUE);
561 STATUSBAR_SetPartBounds (hwnd);
562 }
563
564 return TRUE;
565}
566
567
568static LRESULT
569STATUSBAR_SetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
570{
571 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
572 STATUSWINDOWPART *tmp;
573 HDC hdc;
574 LPINT parts;
575 int i;
576 int oldNumParts;
577
578 if (self->simple)
579 self->simple = FALSE;
580
581 oldNumParts = self->numParts;
582 self->numParts = (INT) wParam;
583 parts = (LPINT) lParam;
584 if (oldNumParts > self->numParts) {
585 for (i = self->numParts ; i < oldNumParts; i++) {
586 if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
587 COMCTL32_Free (self->parts[i].text);
588 }
589 }
590 else if (oldNumParts < self->numParts) {
591 tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
592 for (i = 0; i < oldNumParts; i++) {
593 tmp[i] = self->parts[i];
594 }
595 if (self->parts)
596 COMCTL32_Free (self->parts);
597 self->parts = tmp;
598 }
599
600 for (i = 0; i < self->numParts; i++) {
601 self->parts[i].x = parts[i];
602 }
603
604 if (self->hwndToolTip) {
605 INT nTipCount =
606 SendMessageA (self->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
607
608 if (nTipCount < self->numParts) {
609 /* add tools */
610 TTTOOLINFOA ti;
611 INT i;
612
613 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
614 ti.cbSize = sizeof(TTTOOLINFOA);
615 ti.hwnd = hwnd;
616 for (i = nTipCount; i < self->numParts; i++) {
617// TRACE (statusbar, "add tool %d\n", i);
618 ti.uId = i;
619 SendMessageA (self->hwndToolTip, TTM_ADDTOOLA,
620 0, (LPARAM)&ti);
621 }
622 }
623 else if (nTipCount > self->numParts) {
624 /* delete tools */
625 INT i;
626
627 for (i = nTipCount - 1; i >= self->numParts; i--) {
628
629// FIXME (statusbar, "delete tool %d\n", i);
630
631 }
632 }
633 }
634
635 STATUSBAR_SetPartBounds (hwnd);
636
637 hdc = GetDC (hwnd);
638 STATUSBAR_Refresh (hwnd, hdc);
639 ReleaseDC (hwnd, hdc);
640
641 return TRUE;
642}
643
644
645static LRESULT
646STATUSBAR_SetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
647{
648 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
649 STATUSWINDOWPART *part;
650 int part_num;
651 int style;
652 LPSTR text;
653 LPWSTR newText;
654 int len;
655 HDC hdc;
656
657 text = (LPSTR) lParam;
658 part_num = ((INT) wParam) & 0x00ff;
659 style = ((INT) wParam) & 0xff00;
660
661 if ((self->simple) || (self->parts==NULL) || (part_num==255))
662 part = &self->part0;
663 else
664 part = &self->parts[part_num];
665 if (!part) return FALSE;
666
667 if (style & SBT_OWNERDRAW)
668 {
669 if (!(part->style & SBT_OWNERDRAW) && part->text) COMCTL32_Free(part->text);
670 part->text = (LPWSTR)text;
671 } else
672 {
673 //compare
674 if (text && (len = lstrlenA(text)))
675 {
676 newText = COMCTL32_Alloc((len+1)*sizeof(WCHAR));
677 lstrcpyAtoW (newText,text);
678 } else newText = NULL;
679 if (lstrcmpW(part->text,newText) == 0)
680 {
681 COMCTL32_Free(newText);
682 if (part->style != style)
683 {
684 hdc = GetDC(hwnd);
685 STATUSBAR_RefreshPart(hwnd,part,hdc);
686 ReleaseDC(hwnd, hdc);
687 }
688 return TRUE;
689 }
690
691 COMCTL32_Free(part->text);
692 part->text = newText;
693 }
694 part->style = style;
695
696 hdc = GetDC (hwnd);
697 STATUSBAR_RefreshPart (hwnd, part, hdc);
698 ReleaseDC (hwnd, hdc);
699
700 return TRUE;
701}
702
703
704static LRESULT
705STATUSBAR_SetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
706{
707 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
708 STATUSWINDOWPART *part;
709 INT part_num, style, len;
710 LPWSTR text;
711 HDC hdc;
712
713 text = (LPWSTR) lParam;
714 part_num = ((INT) wParam) & 0x00ff;
715 style = ((INT) wParam) & 0xff00;
716
717 if ((self->simple) || (self->parts==NULL) || (part_num==255))
718 part = &self->part0;
719 else
720 part = &self->parts[part_num];
721 if (!part) return FALSE;
722
723 if (style & SBT_OWNERDRAW)
724 {
725 if (!(part->style & SBT_OWNERDRAW) && part->text) COMCTL32_Free(part->text);
726 part->text = text;
727 } else
728 {
729 //compare
730 if (lstrcmpW(part->text,text) == 0)
731 {
732 if (part->style != style)
733 {
734 hdc = GetDC(hwnd);
735 STATUSBAR_RefreshPart(hwnd,part,hdc);
736 ReleaseDC(hwnd, hdc);
737 }
738 return TRUE;
739 }
740
741 /* duplicate string */
742 COMCTL32_Free(part->text);
743 if (text && (len = lstrlenW(text)))
744 {
745 part->text = COMCTL32_Alloc((len+1)*sizeof(WCHAR));
746 lstrcpyW(part->text,text);
747 }
748 }
749 part->style = style;
750
751 hdc = GetDC (hwnd);
752 STATUSBAR_RefreshPart (hwnd, part, hdc);
753 ReleaseDC (hwnd, hdc);
754
755 return TRUE;
756}
757
758
759static LRESULT
760STATUSBAR_SetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
761{
762 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
763
764// TRACE (statusbar, "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);
774 }
775
776 return 0;
777}
778
779
780static LRESULT
781STATUSBAR_SetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
782{
783 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
784
785// TRACE (statusbar, "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);
795 }
796
797 return 0;
798}
799
800
801static LRESULT
802STATUSBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
803{
804 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
805 BOOL bTemp = infoPtr->bUnicode;
806
807// TRACE (statusbar, "(0x%x)\n", (BOOL)wParam);
808 infoPtr->bUnicode = (BOOL)wParam;
809
810 return bTemp;
811}
812
813
814static LRESULT
815STATUSBAR_Simple (HWND hwnd, WPARAM wParam, LPARAM lParam)
816{
817 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
818 HDC hdc;
819 NMHDR nmhdr;
820
821 infoPtr->simple = (BOOL)wParam;
822
823 /* send notification */
824 nmhdr.hwndFrom = hwnd;
825 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
826 nmhdr.code = SBN_SIMPLEMODECHANGE;
827 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
828
829 hdc = GetDC (hwnd);
830 STATUSBAR_Refresh (hwnd, hdc);
831 ReleaseDC (hwnd, hdc);
832
833 return TRUE;
834}
835
836
837static LRESULT
838STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
839{
840 LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
841 NONCLIENTMETRICSA nclm;
842 RECT rect;
843 int width, len;
844 HDC hdc;
845 STATUSWINDOWINFO *self;
846
847 self = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
848 SetWindowLongA (hwnd, 0, (DWORD)self);
849
850 self->numParts = 1;
851 self->parts = 0;
852 self->simple = FALSE;
853 self->clrBk = CLR_DEFAULT;
854 self->hFont = 0;
855 GetClientRect (hwnd, &rect);
856
857 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
858 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
859 self->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
860
861 /* initialize simple case */
862 self->part0.bound = rect;
863 self->part0.text = 0;
864 self->part0.x = 0;
865 self->part0.style = 0;
866 self->part0.hIcon = 0;
867
868 /* initialize first part */
869 self->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
870 self->parts[0].bound = rect;
871 self->parts[0].text = 0;
872 self->parts[0].x = -1;
873 self->parts[0].style = 0;
874 self->parts[0].hIcon = 0;
875
876 if (IsWindowUnicode (hwnd)) {
877 self->bUnicode = TRUE;
878 if (lpCreate->lpszName &&
879 (len = lstrlenW ((LPCWSTR)lpCreate->lpszName))) {
880 self->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
881 lstrcpyW (self->parts[0].text, (LPCWSTR)lpCreate->lpszName);
882 }
883 }
884 else {
885 if (lpCreate->lpszName &&
886 (len = lstrlenA ((LPCSTR)lpCreate->lpszName))) {
887 self->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
888 lstrcpyAtoW (self->parts[0].text, (LPCSTR)lpCreate->lpszName);
889 }
890 }
891
892 if ((hdc = GetDC (0))) {
893 TEXTMETRICA tm;
894 HFONT hOldFont;
895
896 hOldFont = SelectObject (hdc,self->hDefaultFont);
897 GetTextMetricsA(hdc, &tm);
898 self->textHeight = tm.tmHeight;
899 SelectObject (hdc, hOldFont);
900 ReleaseDC(0, hdc);
901 }
902
903 if (GetWindowLongA (hwnd, GWL_STYLE) & SBT_TOOLTIPS) {
904 self->hwndToolTip =
905 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
906 CW_USEDEFAULT, CW_USEDEFAULT,
907 CW_USEDEFAULT, CW_USEDEFAULT,
908 hwnd, 0,
909 GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
910
911 if (self->hwndToolTip) {
912 NMTOOLTIPSCREATED nmttc;
913
914 nmttc.hdr.hwndFrom = hwnd;
915 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
916 nmttc.hdr.code = NM_TOOLTIPSCREATED;
917 nmttc.hwndToolTips = self->hwndToolTip;
918
919 SendMessageA (GetParent (hwnd), WM_NOTIFY,
920 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
921 }
922 }
923
924 GetClientRect (GetParent (hwnd), &rect);
925 width = rect.right - rect.left;
926 self->height = self->textHeight + 4 + VERT_BORDER;
927 MoveWindow (hwnd, lpCreate->x, lpCreate->y-1,
928 width, self->height, FALSE);
929 STATUSBAR_SetPartBounds (hwnd);
930
931 return 0;
932}
933
934
935static LRESULT
936STATUSBAR_WMDestroy (HWND hwnd)
937{
938 STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
939 int i;
940
941 for (i = 0; i < self->numParts; i++) {
942 if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
943 COMCTL32_Free (self->parts[i].text);
944 }
945 if (self->part0.text && !(self->part0.style & SBT_OWNERDRAW))
946 COMCTL32_Free (self->part0.text);
947 COMCTL32_Free (self->parts);
948
949 /* delete default font */
950 if (self->hDefaultFont)
951 DeleteObject (self->hDefaultFont);
952
953 /* delete tool tip control */
954 if (self->hwndToolTip)
955 DestroyWindow (self->hwndToolTip);
956
957 COMCTL32_Free (self);
958
959 return 0;
960}
961
962
963static LRESULT
964STATUSBAR_WMGetFont (HWND hwnd)
965{
966 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
967 return infoPtr->hFont;
968}
969
970
971static LRESULT
972STATUSBAR_WMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
973{
974 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
975 INT len;
976
977 if (!(infoPtr->parts[0].text))
978 return 0;
979 len = lstrlenW (infoPtr->parts[0].text);
980 if (wParam > len) {
981 if (infoPtr->bUnicode)
982 lstrcpyW ((LPWSTR)lParam, infoPtr->parts[0].text);
983 else
984 lstrcpyWtoA ((LPSTR)lParam, infoPtr->parts[0].text);
985 return len;
986 }
987
988 return -1;
989}
990
991
992static LRESULT
993STATUSBAR_WMMouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
994{
995 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
996
997 if (infoPtr->hwndToolTip)
998 STATUSBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
999 WM_MOUSEMOVE, wParam, lParam);
1000 return 0;
1001}
1002
1003
1004static LRESULT
1005STATUSBAR_WMNCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1006{
1007 if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
1008 RECT rect;
1009 POINT pt;
1010
1011 GetClientRect (hwnd, &rect);
1012
1013 pt.x = (INT)LOWORD(lParam);
1014 pt.y = (INT)HIWORD(lParam);
1015 ScreenToClient (hwnd, &pt);
1016
1017 rect.left = rect.right - 13;
1018 rect.top += 2;
1019
1020 if (PtInRect (&rect, pt))
1021 return HTBOTTOMRIGHT;
1022 }
1023
1024 return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
1025}
1026
1027
1028static LRESULT
1029STATUSBAR_WMNCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1030{
1031 PostMessageA (GetParent (hwnd), WM_NCLBUTTONDOWN, wParam, lParam);
1032 return 0;
1033}
1034
1035
1036static LRESULT
1037STATUSBAR_WMNCLButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1038{
1039 PostMessageA (GetParent (hwnd), WM_NCLBUTTONUP, wParam, lParam);
1040 return 0;
1041}
1042
1043
1044static LRESULT
1045STATUSBAR_WMPaint (HWND hwnd, WPARAM wParam)
1046{
1047 HDC hdc;
1048 PAINTSTRUCT ps;
1049
1050 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1051 STATUSBAR_Refresh (hwnd, hdc);
1052 if (!wParam)
1053 EndPaint (hwnd, &ps);
1054
1055 return 0;
1056}
1057
1058
1059static LRESULT
1060STATUSBAR_WMSetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1061{
1062 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1063
1064 infoPtr->hFont = (HFONT)wParam;
1065 if (LOWORD(lParam) == TRUE) {
1066 HDC hdc = GetDC (hwnd);
1067 STATUSBAR_Refresh (hwnd, hdc);
1068 ReleaseDC (hwnd, hdc);
1069 }
1070
1071 return 0;
1072}
1073
1074
1075static LRESULT
1076STATUSBAR_WMSetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
1077{
1078 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1079 STATUSWINDOWPART *part;
1080 int len;
1081 HDC hdc;
1082
1083 if (infoPtr->numParts == 0)
1084 return FALSE;
1085
1086 part = &infoPtr->parts[0];
1087 /* duplicate string */
1088 if (part->text)
1089 COMCTL32_Free (part->text);
1090 part->text = 0;
1091 if (infoPtr->bUnicode) {
1092 if (lParam && (len = lstrlenW((LPCWSTR)lParam))) {
1093 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1094 lstrcpyW (part->text, (LPCWSTR)lParam);
1095 }
1096 }
1097 else {
1098 if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
1099 part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1100 lstrcpyAtoW (part->text, (char*)lParam);
1101 }
1102 }
1103
1104 hdc = GetDC (hwnd);
1105 STATUSBAR_RefreshPart (hwnd, part, hdc);
1106 ReleaseDC (hwnd, hdc);
1107
1108 return TRUE;
1109}
1110
1111
1112static LRESULT
1113STATUSBAR_WMSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1114{
1115 STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
1116 INT width, x, y, flags;
1117 RECT parent_rect;
1118 HWND parent;
1119
1120 /* Need to resize width to match parent */
1121 flags = (INT) wParam;
1122
1123 /* FIXME for flags =
1124 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
1125 */
1126
1127 if (flags == SIZE_RESTORED) {
1128 /* width and height don't apply */
1129 parent = GetParent (hwnd);
1130 GetClientRect (parent, &parent_rect);
1131 width = parent_rect.right - parent_rect.left;
1132 x = parent_rect.left;
1133 y = parent_rect.bottom - infoPtr->height;
1134 MoveWindow (hwnd, parent_rect.left,
1135 parent_rect.bottom - infoPtr->height,
1136 width, infoPtr->height, TRUE);
1137 STATUSBAR_SetPartBounds (hwnd);
1138 }
1139 return 0;
1140}
1141
1142
1143static LRESULT
1144STATUSBAR_SendNotify (HWND hwnd, UINT code)
1145{
1146 NMHDR nmhdr;
1147
1148 nmhdr.hwndFrom = hwnd;
1149 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1150 nmhdr.code = code;
1151 SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
1152 return 0;
1153}
1154
1155
1156
1157static LRESULT WINAPI
1158StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1159{
1160 switch (msg) {
1161 case SB_GETBORDERS:
1162 return STATUSBAR_GetBorders (lParam);
1163
1164 case SB_GETICON:
1165 return STATUSBAR_GetIcon (hwnd, wParam);
1166
1167 case SB_GETPARTS:
1168 return STATUSBAR_GetParts (hwnd, wParam, lParam);
1169
1170 case SB_GETRECT:
1171 return STATUSBAR_GetRect (hwnd, wParam, lParam);
1172
1173 case SB_GETTEXTA:
1174 return STATUSBAR_GetTextA (hwnd, wParam, lParam);
1175
1176 case SB_GETTEXTW:
1177 return STATUSBAR_GetTextW (hwnd, wParam, lParam);
1178
1179 case SB_GETTEXTLENGTHA:
1180 case SB_GETTEXTLENGTHW:
1181 return STATUSBAR_GetTextLength (hwnd, wParam);
1182
1183 case SB_GETTIPTEXTA:
1184 return STATUSBAR_GetTipTextA (hwnd, wParam, lParam);
1185
1186 case SB_GETTIPTEXTW:
1187 return STATUSBAR_GetTipTextW (hwnd, wParam, lParam);
1188
1189 case SB_GETUNICODEFORMAT:
1190 return STATUSBAR_GetUnicodeFormat (hwnd);
1191
1192 case SB_ISSIMPLE:
1193 return STATUSBAR_IsSimple (hwnd);
1194
1195 case SB_SETBKCOLOR:
1196 return STATUSBAR_SetBkColor (hwnd, wParam, lParam);
1197
1198 case SB_SETICON:
1199 return STATUSBAR_SetIcon (hwnd, wParam, lParam);
1200
1201 case SB_SETMINHEIGHT:
1202 return STATUSBAR_SetMinHeight (hwnd, wParam, lParam);
1203
1204 case SB_SETPARTS:
1205 return STATUSBAR_SetParts (hwnd, wParam, lParam);
1206
1207 case SB_SETTEXTA:
1208 return STATUSBAR_SetTextA (hwnd, wParam, lParam);
1209
1210 case SB_SETTEXTW:
1211 return STATUSBAR_SetTextW (hwnd, wParam, lParam);
1212
1213 case SB_SETTIPTEXTA:
1214 return STATUSBAR_SetTipTextA (hwnd, wParam, lParam);
1215
1216 case SB_SETTIPTEXTW:
1217 return STATUSBAR_SetTipTextW (hwnd, wParam, lParam);
1218
1219 case SB_SETUNICODEFORMAT:
1220 return STATUSBAR_SetUnicodeFormat (hwnd, wParam);
1221
1222 case SB_SIMPLE:
1223 return STATUSBAR_Simple (hwnd, wParam, lParam);
1224
1225
1226 case WM_CREATE:
1227 return STATUSBAR_WMCreate (hwnd, wParam, lParam);
1228
1229 case WM_DESTROY:
1230 return STATUSBAR_WMDestroy (hwnd);
1231
1232 case WM_GETFONT:
1233 return STATUSBAR_WMGetFont (hwnd);
1234
1235 case WM_GETTEXT:
1236 return STATUSBAR_WMGetText (hwnd, wParam, lParam);
1237
1238 case WM_GETTEXTLENGTH:
1239 return STATUSBAR_GetTextLength (hwnd, 0);
1240
1241 case WM_LBUTTONDBLCLK:
1242 return STATUSBAR_SendNotify (hwnd, NM_DBLCLK);
1243
1244 case WM_LBUTTONUP:
1245 return STATUSBAR_SendNotify (hwnd, NM_CLICK);
1246
1247 case WM_MOUSEMOVE:
1248 return STATUSBAR_WMMouseMove (hwnd, wParam, lParam);
1249
1250 case WM_NCHITTEST:
1251 return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
1252
1253 case WM_NCLBUTTONDOWN:
1254 return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
1255
1256 case WM_NCLBUTTONUP:
1257 return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
1258
1259 case WM_PAINT:
1260 return STATUSBAR_WMPaint (hwnd, wParam);
1261
1262 case WM_RBUTTONDBLCLK:
1263 return STATUSBAR_SendNotify (hwnd, NM_RDBLCLK);
1264
1265 case WM_RBUTTONUP:
1266 return STATUSBAR_SendNotify (hwnd, NM_RCLICK);
1267
1268 case WM_SETFONT:
1269 return STATUSBAR_WMSetFont (hwnd, wParam, lParam);
1270
1271 case WM_SETTEXT:
1272 return STATUSBAR_WMSetText (hwnd, wParam, lParam);
1273
1274 case WM_SIZE:
1275 return STATUSBAR_WMSize (hwnd, wParam, lParam);
1276
1277 default:
1278// if (msg >= WM_USER)
1279// ERR (statusbar, "unknown msg %04x wp=%04x lp=%08lx\n",
1280// msg, wParam, lParam);
1281 return DefWindowProcA (hwnd, msg, wParam, lParam);
1282 }
1283 return 0;
1284}
1285
1286
1287/***********************************************************************
1288 * STATUS_Register [Internal]
1289 *
1290 * Registers the status window class.
1291 */
1292
1293VOID
1294STATUS_Register (VOID)
1295{
1296 WNDCLASSA wndClass;
1297
1298 if (GlobalFindAtomA (STATUSCLASSNAMEA)) return;
1299
1300 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1301 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1302 wndClass.lpfnWndProc = (WNDPROC)StatusWindowProc;
1303 wndClass.cbClsExtra = 0;
1304 wndClass.cbWndExtra = sizeof(STATUSWINDOWINFO *);
1305 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1306 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1307 wndClass.lpszClassName = STATUSCLASSNAMEA;
1308
1309 RegisterClassA (&wndClass);
1310}
1311
1312
1313/***********************************************************************
1314 * STATUS_Unregister [Internal]
1315 *
1316 * Unregisters the status window class.
1317 */
1318
1319VOID
1320STATUS_Unregister (VOID)
1321{
1322 if (GlobalFindAtomA (STATUSCLASSNAMEA))
1323 UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);
1324}
1325
Note: See TracBrowser for help on using the repository browser.