source: trunk/src/comctl32/toolbar.cpp@ 3962

Last change on this file since 3962 was 3962, checked in by sandervl, 25 years ago

PD: update to wine20000801 (toolbar+tooltips)

File size: 102.7 KB
Line 
1/* $Id: toolbar.cpp,v 1.8 2000-08-06 14:40:17 sandervl Exp $ */
2/*
3 * Toolbar control
4 *
5 * Copyright 1998,1999 Eric Kohl
6 * Copyright 1999 Achim Hasenmueller
7 * Copyright 1999 Christoph Bratschi
8 *
9 * TODO:
10 * - A little bug in TOOLBAR_DrawMasked()
11 * - Button wrapping (under construction).
12 * - Messages.
13 * - Notifications (under construction).
14 * - Fix TB_SETROWS.
15 * - Tooltip support (almost complete).
16 * - Unicode suppport (under construction).
17 * - Fix TOOLBAR_SetButtonInfo32A/W.
18 * - Customize dialog (under construction).
19 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
20 * - I_IMAGECALLBACK support.
21 *
22 * Testing:
23 * - Run tests using Waite Group Windows95 API Bible Volume 2.
24 * The second cdrom contains executables addstr.exe, btncount.exe,
25 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
26 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
27 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
28 * setparnt.exe, setrows.exe, toolwnd.exe.
29 * - Microsofts controlspy examples.
30 */
31
32/*
33 - (WINE 20000608 level)
34*/
35
36
37#include <string.h>
38
39#include "winbase.h"
40#include "commctrl.h"
41#include "cache.h"
42#include "comctl32.h"
43#include "ccbase.h"
44#include "toolbar.h"
45
46#define SEPARATOR_WIDTH 8
47#define TOP_BORDER 2
48#define BOTTOM_BORDER 2
49
50#define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
51
52static BOOL
53TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
54{
55 if ((index>=0) && (index < infoPtr->nNumBitmaps))
56 return TRUE;
57 else
58 return FALSE;
59}
60
61
62static void
63TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
64{
65 INT x = (lpRect->left + lpRect->right) / 2 - 1;
66 INT yBottom = lpRect->bottom - 3;
67 INT yTop = lpRect->top + 1;
68
69 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
70 MoveToEx (hdc, x, yBottom, NULL);
71 LineTo (hdc, x, yTop);
72 x++;
73 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
74 MoveToEx (hdc, x, yBottom, NULL);
75 LineTo (hdc, x, yTop);
76}
77
78/*
79 * Draw the text string for this button.
80 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
81 * is non-zero, so we can simply check himlDef to see if we have
82 * an image list
83 */
84static void
85TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
86 HDC hdc, INT nState, DWORD dwStyle)
87{
88 RECT rcText = btnPtr->rect;
89 HFONT hOldFont;
90 INT nOldBkMode;
91 COLORREF clrOld;
92 LPWSTR lpText = NULL;
93 HIMAGELIST himl = infoPtr->himlDef;
94
95 // TRACE ("iString: %x\n", btnPtr->iString);
96
97 /* get a pointer to the text */
98 if (btnPtr->iString == -1)
99 dprintf(("TOOLBAR_DrawString: Undocumented Index -1\n"));
100 else if (HIWORD(btnPtr->iString) != 0)
101 lpText = (LPWSTR)btnPtr->iString;
102 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
103 lpText = infoPtr->strings[btnPtr->iString];
104
105 // TRACE ("lpText: \"%s\"\n", debugstr_w(lpText));
106
107 /* draw text */
108 if (lpText) {
109
110 InflateRect (&rcText, -3, -3);
111
112 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
113 if ((dwStyle & TBSTYLE_LIST) &&
114 ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
115 (btnPtr->iBitmap != I_IMAGENONE)) {
116 rcText.left += infoPtr->nBitmapWidth;
117 }
118 else {
119 rcText.top += infoPtr->nBitmapHeight;
120 }
121 }
122
123 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
124 OffsetRect (&rcText, 1, 1);
125
126 hOldFont = SelectObject (hdc, infoPtr->hFont);
127 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
128 if (!(nState & TBSTATE_ENABLED)) {
129 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
130 OffsetRect (&rcText, 1, 1);
131 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
132 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
133 OffsetRect (&rcText, -1, -1);
134 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
135 }
136 else if (nState & TBSTATE_INDETERMINATE) {
137 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
138 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
139 }
140 else {
141 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
142 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
143 }
144
145 SetTextColor (hdc, clrOld);
146 SelectObject (hdc, hOldFont);
147 if (nOldBkMode != TRANSPARENT)
148 SetBkMode (hdc, nOldBkMode);
149 }
150}
151
152
153static void
154TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
155{
156 HBRUSH hbr = SelectObject (hdc, GetPattern55AABrush ());
157 INT cx = lpRect->right - lpRect->left;
158 INT cy = lpRect->bottom - lpRect->top;
159 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
160 SelectObject (hdc, hbr);
161}
162
163
164static void
165TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
166 HDC hdc, INT x, INT y)
167{
168 /* FIXME: this function is a hack since it uses image list
169 internals directly */
170
171 HIMAGELIST himl = infoPtr->himlDef;
172 HBITMAP hbmMask;
173 HDC hdcImageList;
174 HDC hdcMask;
175
176 if (!himl)
177 return;
178
179 /* create new dc's */
180 hdcImageList = CreateCompatibleDC (0);
181 hdcMask = CreateCompatibleDC (0);
182
183 /* create new bitmap */
184 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
185 SelectObject (hdcMask, hbmMask);
186
187 /* copy the mask bitmap */
188 SelectObject (hdcImageList, himl->hbmMask);
189 SetBkColor (hdcImageList, RGB(255, 255, 255));
190 SetTextColor (hdcImageList, RGB(0, 0, 0));
191 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
192 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
193
194#if 0
195 /* add white mask from image */
196 SelectObject (hdcImageList, himl->hbmImage);
197 SetBkColor (hdcImageList, RGB(0, 0, 0));
198 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
199 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
200#endif
201
202 /* draw the new mask */
203 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
204 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
205 hdcMask, 0, 0, 0xB8074A);
206
207 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
208 BitBlt (hdc, x, y, himl->cx, himl->cy,
209 hdcMask, 0, 0, 0xB8074A);
210
211 DeleteObject (hbmMask);
212 DeleteDC (hdcMask);
213 DeleteDC (hdcImageList);
214}
215
216
217static void
218TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
219{
220 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
221 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
222 RECT rc;
223
224 if (btnPtr->fsState & TBSTATE_HIDDEN)
225 return;
226
227 rc = btnPtr->rect;
228
229 // TRACE("iBitmap: %d\n", btnPtr->iBitmap);
230
231 /* separator */
232 if (btnPtr->fsStyle & TBSTYLE_SEP) {
233 /* with the FLAT style, iBitmap is the width and has already */
234 /* been taken into consideration in calculating the width */
235 /* so now we need to draw the vertical separator */
236 /* empirical tests show that iBitmap can/will be non-zero */
237 /* when drawing the vertical bar... */
238 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
239 TOOLBAR_DrawFlatSeparator (&rc, hdc);
240 return;
241 }
242
243 /* disabled */
244 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
245 if (!(dwStyle & TBSTYLE_FLAT))
246 DrawEdge (hdc, &rc, EDGE_RAISED,
247 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
248
249 if (infoPtr->himlDis &&
250 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
251 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
252 rc.left+1, rc.top+1, ILD_NORMAL);
253 else
254 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
255
256 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
257 return;
258 }
259
260 /* pressed TBSTYLE_BUTTON */
261 if (btnPtr->fsState & TBSTATE_PRESSED) {
262 if (dwStyle & TBSTYLE_FLAT)
263 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
264 else
265 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
266 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
267 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
268 rc.left+2, rc.top+2, ILD_NORMAL);
269 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
270 return;
271 }
272
273 /* checked TBSTYLE_CHECK */
274 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
275 (btnPtr->fsState & TBSTATE_CHECKED)) {
276 if (dwStyle & TBSTYLE_FLAT)
277 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
278 BF_RECT | BF_MIDDLE | BF_ADJUST);
279 else
280 DrawEdge (hdc, &rc, EDGE_SUNKEN,
281 BF_RECT | BF_MIDDLE | BF_ADJUST);
282
283 TOOLBAR_DrawPattern (hdc, &rc);
284
285 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
286 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
287 rc.left+2, rc.top+2, ILD_NORMAL);
288
289 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
290 return;
291 }
292
293 /* indeterminate */
294 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
295 DrawEdge (hdc, &rc, EDGE_RAISED,
296 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
297
298 TOOLBAR_DrawPattern (hdc, &rc);
299 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
300 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
301 return;
302 }
303
304 /* normal state */
305 if (dwStyle & TBSTYLE_FLAT)
306 {
307 if (btnPtr->bHot)
308 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
309 if (btnPtr->bHot && infoPtr->himlHot &&
310 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
311 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
312 rc.left +2, rc.top +2, ILD_NORMAL);
313 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
314 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
315 rc.left +2, rc.top +2, ILD_NORMAL);
316 }
317 else
318 {
319 DrawEdge (hdc, &rc, EDGE_RAISED,
320 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
321
322 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
323 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
324 rc.left+1, rc.top+1, ILD_NORMAL);
325 }
326
327 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
328}
329
330
331static void
332TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
333{
334 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
335 TBUTTON_INFO *btnPtr;
336 INT i;
337 RECT rcTemp;
338
339 /* redraw necessary buttons */
340 btnPtr = infoPtr->buttons;
341 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
342 {
343 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
344 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
345 }
346}
347
348static void
349TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
350{
351 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
352 TBUTTON_INFO *btnPtr;
353 HDC hdc;
354 HFONT hOldFont;
355
356 lpSize->cx = 0;
357 lpSize->cy = 0;
358 hdc = GetDC (0);
359 hOldFont = SelectObject (hdc, infoPtr->hFont);
360
361 btnPtr = &infoPtr->buttons[index];
362
363 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
364 (btnPtr->iString > -1) &&
365 (btnPtr->iString < infoPtr->nNumStrings))
366 {
367 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
368 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
369 }
370
371 SelectObject (hdc, hOldFont);
372 ReleaseDC (0, hdc);
373
374 // TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
375}
376
377static void
378TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
379{
380 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
381 TBUTTON_INFO *btnPtr;
382 INT i;
383 SIZE sz;
384
385
386 lpSize->cx = 0;
387 lpSize->cy = 0;
388
389 btnPtr = infoPtr->buttons;
390 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
391 TOOLBAR_MeasureString(hwnd,i,&sz);
392 if (sz.cx > lpSize->cx)
393 lpSize->cx = sz.cx;
394 if (sz.cy > lpSize->cy)
395 lpSize->cy = sz.cy;
396 }
397
398 // TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
399}
400
401/***********************************************************************
402* TOOLBAR_WrapToolbar
403*
404* This function walks through the buttons and seperators in the
405* toolbar, and sets the TBSTATE_WRAP flag only on those items where
406* wrapping should occur based on the width of the toolbar window.
407* It does *not* calculate button placement itself. That task
408* takes place in TOOLBAR_CalcToolbar. If the program wants to manage
409* the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
410* flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
411*/
412
413static void
414TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
415{
416 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
417 TBUTTON_INFO *btnPtr;
418 INT x, cx, i, j;
419 RECT rc;
420 BOOL bWrap, bButtonWrap;
421
422 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
423 /* no layout is necessary. Applications may use this style */
424 /* to perform their own layout on the toolbar. */
425 if( !(dwStyle & TBSTYLE_WRAPABLE) )
426 return;
427
428 btnPtr = infoPtr->buttons;
429 x = infoPtr->nIndent;
430
431 /* this can get the parents width, to know how far we can extend
432 * this toolbar. We cannot use its height, as there may be multiple
433 * toolbars in a rebar control
434 */
435 GetClientRect( GetParent(hwnd), &rc );
436 infoPtr->nWidth = rc.right - rc.left;
437 bButtonWrap = FALSE;
438
439 for (i = 0; i < infoPtr->nNumButtons; i++ )
440 {
441 bWrap = FALSE;
442 btnPtr[i].fsState &= ~TBSTATE_WRAP;
443
444 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
445 continue;
446
447 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
448 /* it is the actual width of the separator. This is used for */
449 /* custom controls in toolbars. */
450 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
451 cx = (btnPtr[i].iBitmap > 0) ?
452 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
453 else
454 cx = infoPtr->nButtonWidth;
455
456 /* Two or more adjacent separators form a separator group. */
457 /* The first separator in a group should be wrapped to the */
458 /* next row if the previous wrapping is on a button. */
459 if( bButtonWrap &&
460 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
461 (i + 1 < infoPtr->nNumButtons ) &&
462 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
463 {
464 btnPtr[i].fsState |= TBSTATE_WRAP;
465 x = infoPtr->nIndent;
466 i++;
467 bButtonWrap = FALSE;
468 continue;
469 }
470
471 /* The layout makes sure the bitmap is visible, but not the button. */
472 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
473 > infoPtr->nWidth )
474 {
475 BOOL bFound = FALSE;
476
477 /* If the current button is a separator and not hidden, */
478 /* go to the next until it reaches a non separator. */
479 /* Wrap the last separator if it is before a button. */
480 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
481 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
482 i < infoPtr->nNumButtons )
483 {
484 i++;
485 bFound = TRUE;
486 }
487
488 if( bFound && i < infoPtr->nNumButtons )
489 {
490 i--;
491 btnPtr[i].fsState |= TBSTATE_WRAP;
492 x = infoPtr->nIndent;
493 bButtonWrap = FALSE;
494 continue;
495 }
496 else if ( i >= infoPtr->nNumButtons)
497 break;
498
499 /* If the current button is not a separator, find the last */
500 /* separator and wrap it. */
501 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
502 {
503 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
504 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
505 {
506 bFound = TRUE;
507 i = j;
508 x = infoPtr->nIndent;
509 btnPtr[j].fsState |= TBSTATE_WRAP;
510 bButtonWrap = FALSE;
511 break;
512 }
513 }
514
515 /* If no separator available for wrapping, wrap one of */
516 /* non-hidden previous button. */
517 if (!bFound)
518 {
519 for ( j = i - 1;
520 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
521 {
522 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
523 continue;
524
525 bFound = TRUE;
526 i = j;
527 x = infoPtr->nIndent;
528 btnPtr[j].fsState |= TBSTATE_WRAP;
529 bButtonWrap = TRUE;
530 break;
531 }
532 }
533
534 /* If all above failed, wrap the current button. */
535 if (!bFound)
536 {
537 btnPtr[i].fsState |= TBSTATE_WRAP;
538 bFound = TRUE;
539 x = infoPtr->nIndent;
540 if (btnPtr[i].fsState & TBSTYLE_SEP )
541 bButtonWrap = FALSE;
542 else
543 bButtonWrap = TRUE;
544 }
545 }
546 else
547 x += cx;
548 }
549}
550
551/***********************************************************************
552* TOOLBAR_CalcToolbar
553*
554* This function calculates button and separator placement. It first
555* calculates the button sizes, gets the toolbar window width and then
556* calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
557* on. It assigns a new location to each item and sends this location to
558* the tooltip window if appropriate. Finally, it updates the rcBound
559* rect and calculates the new required toolbar window height.
560*/
561
562static void
563TOOLBAR_CalcToolbar (HWND hwnd)
564{
565 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
566 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
567 TBUTTON_INFO *btnPtr;
568 INT i, nRows, nSepRows;
569 INT x, y, cx, cy;
570 SIZE sizeString;
571 BOOL bWrap;
572
573 TOOLBAR_CalcStrings (hwnd, &sizeString);
574
575 if (dwStyle & TBSTYLE_LIST) {
576 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
577 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
578 }
579 else {
580 BOOL usesBitmaps = FALSE;
581 INT i;
582
583 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
584 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
585 usesBitmaps = TRUE;
586
587 if (sizeString.cy > 0) {
588 if (usesBitmaps)
589 infoPtr->nButtonHeight = sizeString.cy + infoPtr->nBitmapHeight + 6;
590 else
591 infoPtr->nButtonHeight = sizeString.cy + 6;
592 }
593 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
594 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
595
596 if (sizeString.cx > infoPtr->nBitmapWidth)
597 infoPtr->nButtonWidth = sizeString.cx + 6;
598 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
599 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
600 }
601
602 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
603 infoPtr->nButtonWidth = infoPtr->cxMin;
604 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
605 infoPtr->nButtonWidth = infoPtr->cxMax;
606
607 TOOLBAR_WrapToolbar( hwnd, dwStyle );
608
609 x = infoPtr->nIndent;
610 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
611
612 /*
613 * We wills et the height below, and we set the width on entry
614 * so we do not reset them here..
615 */
616#if 0
617 GetClientRect( hwnd, &rc );
618 /* get initial values for toolbar */
619 infoPtr->nWidth = rc.right - rc.left;
620 infoPtr->nHeight = rc.bottom - rc.top;
621#endif
622
623 /* from above, minimum is a button, and possible text */
624 cx = infoPtr->nButtonWidth;
625 /* cannot use just ButtonHeight, we may have no buttons! */
626 if (infoPtr->nNumButtons > 0)
627 infoPtr->nHeight = infoPtr->nButtonHeight;
628 cy = infoPtr->nHeight;
629
630 nRows = nSepRows = 0;
631
632 infoPtr->rcBound.top = y;
633 infoPtr->rcBound.left = x;
634 infoPtr->rcBound.bottom = y + cy;
635 infoPtr->rcBound.right = x;
636
637 btnPtr = infoPtr->buttons;
638
639 /* do not base height/width on parent, if the parent is a */
640 /* rebar control it could have multiple rows of toolbars */
641/* GetClientRect( GetParent(hwnd), &rc ); */
642/* cx = rc.right - rc.left; */
643/* cy = rc.bottom - rc.top; */
644
645 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
646 {
647 bWrap = FALSE;
648 if (btnPtr->fsState & TBSTATE_HIDDEN)
649 {
650 SetRectEmpty (&btnPtr->rect);
651 continue;
652 }
653
654 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
655 /* it is the actual width of the separator. This is used for */
656 /* custom controls in toolbars. */
657 if (btnPtr->fsStyle & TBSTYLE_SEP)
658 cx = (btnPtr->iBitmap > 0) ?
659 btnPtr->iBitmap : SEPARATOR_WIDTH;
660 else {
661 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
662 {
663 SIZE sz;
664 TOOLBAR_MeasureString(hwnd,i,&sz);
665 cx = sz.cx + 6;
666 }
667 else
668 cx = infoPtr->nButtonWidth;
669 }
670 cy = infoPtr->nHeight;
671
672 if (btnPtr->fsState & TBSTATE_WRAP )
673 bWrap = TRUE;
674
675 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
676
677 if (infoPtr->rcBound.left > x)
678 infoPtr->rcBound.left = x;
679 if (infoPtr->rcBound.right < x + cx)
680 infoPtr->rcBound.right = x + cx;
681 if (infoPtr->rcBound.bottom < y + cy)
682 infoPtr->rcBound.bottom = y + cy;
683
684 /* Set the toolTip only for non-hidden, non-separator button */
685 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
686 {
687 TTTOOLINFOA ti;
688
689 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
690 ti.cbSize = sizeof(TTTOOLINFOA);
691 ti.hwnd = hwnd;
692 ti.uId = btnPtr->idCommand;
693 ti.rect = btnPtr->rect;
694 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
695 0, (LPARAM)&ti);
696 }
697
698 /* btnPtr->nRow is zero based. The space between the rows is */
699 /* also considered as a row. */
700 btnPtr->nRow = nRows + nSepRows;
701 if( bWrap )
702 {
703 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
704 y += cy;
705 else
706 {
707 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
708 /* it is the actual width of the separator. This is used for */
709 /* custom controls in toolbars. */
710 y += cy + ( (btnPtr->iBitmap > 0 ) ?
711 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
712
713 /* nSepRows is used to calculate the extra height follwoing */
714 /* the last row. */
715 nSepRows++;
716 }
717 x = infoPtr->nIndent;
718 nRows++;
719 }
720 else
721 x += cx;
722 }
723
724 /* infoPtr->nRows is the number of rows on the toolbar */
725 infoPtr->nRows = nRows + nSepRows + 1;
726
727 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
728 /* the last row. */
729 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
730 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
731 nSepRows * (infoPtr->nBitmapHeight + 1) +
732 BOTTOM_BORDER;
733 // TRACE("toolbar height %d\n", infoPtr->nHeight);
734}
735
736
737static INT
738TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
739{
740 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
741 TBUTTON_INFO *btnPtr;
742 INT i;
743
744 btnPtr = infoPtr->buttons;
745 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
746 if (btnPtr->fsState & TBSTATE_HIDDEN)
747 continue;
748
749 if (btnPtr->fsStyle & TBSTYLE_SEP) {
750 if (PtInRect (&btnPtr->rect, *lpPt)) {
751 // TRACE(" ON SEPARATOR %d!\n", i);
752 return -i;
753 }
754 }
755 else {
756 if (PtInRect (&btnPtr->rect, *lpPt)) {
757 // TRACE(" ON BUTTON %d!\n", i);
758 return i;
759 }
760 }
761 }
762
763 // TRACE(" NOWHERE!\n");
764 return -1;
765}
766
767
768static INT
769TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
770{
771 TBUTTON_INFO *btnPtr;
772 INT i;
773
774 btnPtr = infoPtr->buttons;
775 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
776 if (btnPtr->idCommand == idCommand) {
777 // TRACE("command=%d index=%d\n", idCommand, i);
778 return i;
779 }
780 }
781 // TRACE("no index found for command=%d\n", idCommand);
782 return -1;
783}
784
785
786static INT
787TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
788{
789 TBUTTON_INFO *btnPtr;
790 INT nRunIndex;
791
792 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
793 return -1;
794
795 /* check index button */
796 btnPtr = &infoPtr->buttons[nIndex];
797 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
798 if (btnPtr->fsState & TBSTATE_CHECKED)
799 return nIndex;
800 }
801
802 /* check previous buttons */
803 nRunIndex = nIndex - 1;
804 while (nRunIndex >= 0) {
805 btnPtr = &infoPtr->buttons[nRunIndex];
806 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
807 if (btnPtr->fsState & TBSTATE_CHECKED)
808 return nRunIndex;
809 }
810 else
811 break;
812 nRunIndex--;
813 }
814
815 /* check next buttons */
816 nRunIndex = nIndex + 1;
817 while (nRunIndex < infoPtr->nNumButtons) {
818 btnPtr = &infoPtr->buttons[nRunIndex];
819 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
820 if (btnPtr->fsState & TBSTATE_CHECKED)
821 return nRunIndex;
822 }
823 else
824 break;
825 nRunIndex++;
826 }
827
828 return -1;
829}
830
831
832static VOID
833TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
834 WPARAM wParam, LPARAM lParam)
835{
836 MSG msg;
837
838 msg.hwnd = hwndMsg;
839 msg.message = uMsg;
840 msg.wParam = wParam;
841 msg.lParam = lParam;
842 msg.time = GetMessageTime ();
843 msg.pt.x = LOWORD(GetMessagePos ());
844 msg.pt.y = HIWORD(GetMessagePos ());
845
846 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
847}
848
849
850/***********************************************************************
851 * TOOLBAR_CustomizeDialogProc
852 * This function implements the toolbar customization dialog.
853 */
854static BOOL WINAPI
855TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
856{
857 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
858 static HDSA hDsa = NULL;
859
860 switch (uMsg)
861 {
862 case WM_INITDIALOG:
863 infoPtr = (TOOLBAR_INFO *)lParam;
864 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
865
866 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
867
868 if (infoPtr)
869 {
870 TBUTTON_INFO *btnPtr;
871 INT i;
872
873 /* insert 'virtual' separator button into 'available buttons' list */
874 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
875
876 /* copy all buttons and append them to the right listbox */
877 btnPtr = infoPtr->buttons;
878 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
879 {
880 DSA_InsertItem (hDsa, i, btnPtr);
881
882 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
883 if (btnPtr->fsState & TBSTATE_HIDDEN)
884 {
885 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
886 }
887 else
888 {
889 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
890 }
891 }
892
893 /* append 'virtual' separator button to the 'toolbar buttons' list */
894 /* TODO */
895 }
896 return TRUE;
897
898 case WM_CLOSE:
899 EndDialog(hwnd, FALSE);
900 return TRUE;
901
902 case WM_COMMAND:
903 switch (LOWORD(wParam))
904 {
905 case IDCANCEL:
906 EndDialog(hwnd, FALSE);
907 break;
908 }
909 return TRUE;
910
911 case WM_DESTROY:
912 if (hDsa)
913 DSA_Destroy (hDsa);
914 return TRUE;
915
916 case WM_DRAWITEM:
917 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
918 {
919 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
920 TBUTTON_INFO btnPtr;
921 RECT rcButton;
922 RECT rcText;
923 HPEN hOldPen;
924 HBRUSH hOldBrush;
925 COLORREF oldText = 0;
926 COLORREF oldBk = 0;
927
928 // FIXME("action: %x itemState: %x\n",
929 // lpdis->itemAction, lpdis->itemState);
930
931 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
932
933 if (lpdis->itemState & ODS_FOCUS)
934 {
935 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
936 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
937 }
938
939 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
940 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
941
942 /* fill background rectangle */
943 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
944 lpdis->rcItem.right, lpdis->rcItem.bottom);
945
946 /* calculate button and text rectangles */
947 CopyRect (&rcButton, &lpdis->rcItem);
948 InflateRect (&rcButton, -1, -1);
949 CopyRect (&rcText, &rcButton);
950 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
951 rcText.left = rcButton.right + 2;
952
953 /* draw focus rectangle */
954 if (lpdis->itemState & ODS_FOCUS)
955 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
956
957 /* draw button */
958 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
959
960 /* draw image and text */
961 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
962 {
963 /* virtual separator in the 'available' list */
964 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
965 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
966 }
967 else
968 {
969 /* real button */
970
971 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
972 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
973
974 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
975 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
976
977 }
978
979 if (lpdis->itemState & ODS_FOCUS)
980 {
981 SetBkColor (lpdis->hDC, oldBk);
982 SetTextColor (lpdis->hDC, oldText);
983 }
984
985 SelectObject (lpdis->hDC, hOldBrush);
986 SelectObject (lpdis->hDC, hOldPen);
987
988 return TRUE;
989 }
990 return FALSE;
991
992 case WM_MEASUREITEM:
993 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
994 {
995 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
996
997 if (infoPtr)
998 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
999 else
1000 lpmis->itemHeight = 15 + 8; /* default height */
1001
1002 return TRUE;
1003 }
1004 return FALSE;
1005
1006 default:
1007 return FALSE;
1008 }
1009}
1010
1011
1012/***********************************************************************
1013 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1014 *
1015 */
1016static LRESULT
1017TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1018{
1019 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1020 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1021 INT nIndex = 0, nButtons, nCount;
1022 HBITMAP hbmLoad;
1023
1024 // TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1025 if (!lpAddBmp)
1026 return -1;
1027
1028 if (lpAddBmp->hInst == HINST_COMMCTRL)
1029 {
1030 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1031 nButtons = 15;
1032 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1033 nButtons = 13;
1034 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1035 nButtons = 5;
1036 else
1037 return -1;
1038
1039 // TRACE ("adding %d internal bitmaps!\n", nButtons);
1040
1041 /* Windows resize all the buttons to the size of a newly added standard image */
1042 if (lpAddBmp->nID & 1)
1043 {
1044 /* large icons */
1045 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1046 MAKELPARAM((WORD)26, (WORD)26));
1047 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1048 MAKELPARAM((WORD)33, (WORD)33));
1049 }
1050 else
1051 {
1052 /* small icons */
1053 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1054 MAKELPARAM((WORD)16, (WORD)16));
1055 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1056 MAKELPARAM((WORD)22, (WORD)22));
1057 }
1058
1059 TOOLBAR_CalcToolbar (hwnd);
1060 }
1061 else
1062 {
1063 nButtons = (INT)wParam;
1064 if (nButtons <= 0)
1065 return -1;
1066
1067 // TRACE ("adding %d bitmaps!\n", nButtons);
1068 }
1069
1070 if (!(infoPtr->himlDef)) {
1071 /* create new default image list */
1072 // TRACE ("creating default image list!\n");
1073
1074 infoPtr->himlDef =
1075 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1076 ILC_COLOR | ILC_MASK, nButtons, 2);
1077 infoPtr->himlInt = infoPtr->himlDef;
1078 }
1079
1080 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1081
1082 /* Add bitmaps to the default image list */
1083 if (lpAddBmp->hInst == (HINSTANCE)0)
1084 {
1085 nIndex =
1086 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1087 CLR_DEFAULT);
1088 }
1089 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1090 {
1091 /* Add system bitmaps */
1092 switch (lpAddBmp->nID)
1093 {
1094 case IDB_STD_SMALL_COLOR:
1095 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1096 MAKEINTRESOURCEA(IDB_STD_SMALL));
1097 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1098 hbmLoad, CLR_DEFAULT);
1099 DeleteObject (hbmLoad);
1100 break;
1101
1102 case IDB_STD_LARGE_COLOR:
1103 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1104 MAKEINTRESOURCEA(IDB_STD_LARGE));
1105 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1106 hbmLoad, CLR_DEFAULT);
1107 DeleteObject (hbmLoad);
1108 break;
1109
1110 case IDB_VIEW_SMALL_COLOR:
1111 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1112 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1113 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1114 hbmLoad, CLR_DEFAULT);
1115 DeleteObject (hbmLoad);
1116 break;
1117
1118 case IDB_VIEW_LARGE_COLOR:
1119 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1120 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1121 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1122 hbmLoad, CLR_DEFAULT);
1123 DeleteObject (hbmLoad);
1124 break;
1125
1126 case IDB_HIST_SMALL_COLOR:
1127 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1128 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1129 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1130 hbmLoad, CLR_DEFAULT);
1131 DeleteObject (hbmLoad);
1132 break;
1133
1134 case IDB_HIST_LARGE_COLOR:
1135 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1136 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1137 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1138 hbmLoad, CLR_DEFAULT);
1139 DeleteObject (hbmLoad);
1140 break;
1141
1142 default:
1143 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1144 // ERR ("invalid imagelist!\n");
1145 break;
1146 }
1147 }
1148 else
1149 {
1150 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1151 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1152 DeleteObject (hbmLoad);
1153 }
1154
1155 if (nIndex != -1)
1156 {
1157 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1158
1159 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1160 {
1161 dprintf(("TOOLBAR_AddBitmap: Desired images do not match recieved images : Previous image number %i Previous images in list %i added %i expecting total %i, Images in list %i\n",
1162 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1163 infoPtr->nNumBitmaps+nButtons,imagecount));
1164
1165 infoPtr->nNumBitmaps = imagecount;
1166 }
1167 else
1168 infoPtr->nNumBitmaps += nButtons;
1169 }
1170
1171 return nIndex;
1172}
1173
1174
1175static LRESULT
1176TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1177{
1178 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1179 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1180 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1181
1182 // TRACE("adding %d buttons!\n", wParam);
1183
1184 nAddButtons = (UINT)wParam;
1185 nOldButtons = infoPtr->nNumButtons;
1186 nNewButtons = nOldButtons + nAddButtons;
1187
1188 if (infoPtr->nNumButtons == 0) {
1189 infoPtr->buttons =
1190 (TBUTTON_INFO*) COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1191 }
1192 else {
1193 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1194 infoPtr->buttons =
1195 (TBUTTON_INFO*) COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1196 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1197 nOldButtons * sizeof(TBUTTON_INFO));
1198 COMCTL32_Free (oldButtons);
1199 }
1200
1201 infoPtr->nNumButtons = nNewButtons;
1202
1203 /* insert new button data */
1204 for (nCount = 0; nCount < nAddButtons; nCount++) {
1205 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1206 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1207 btnPtr->idCommand = lpTbb[nCount].idCommand;
1208 btnPtr->fsState = lpTbb[nCount].fsState;
1209 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1210 btnPtr->dwData = lpTbb[nCount].dwData;
1211 btnPtr->iString = lpTbb[nCount].iString;
1212 btnPtr->bHot = FALSE;
1213
1214 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1215 TTTOOLINFOA ti;
1216
1217 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1218 ti.cbSize = sizeof (TTTOOLINFOA);
1219 ti.hwnd = hwnd;
1220 ti.uId = btnPtr->idCommand;
1221 ti.hinst = 0;
1222 ti.lpszText = LPSTR_TEXTCALLBACKA;
1223
1224 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1225 0, (LPARAM)&ti);
1226 }
1227 }
1228
1229 TOOLBAR_CalcToolbar (hwnd);
1230
1231 InvalidateRect(hwnd, NULL, FALSE);
1232
1233 return TRUE;
1234}
1235
1236
1237static LRESULT
1238TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1239{
1240 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1241 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1242 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1243
1244 // TRACE("adding %d buttons!\n", wParam);
1245
1246 nAddButtons = (UINT)wParam;
1247 nOldButtons = infoPtr->nNumButtons;
1248 nNewButtons = nOldButtons + nAddButtons;
1249
1250 if (infoPtr->nNumButtons == 0) {
1251 infoPtr->buttons =
1252 (TBUTTON_INFO*)COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1253 }
1254 else {
1255 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1256 infoPtr->buttons =
1257 (TBUTTON_INFO*)COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1258 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1259 nOldButtons * sizeof(TBUTTON_INFO));
1260 COMCTL32_Free (oldButtons);
1261 }
1262
1263 infoPtr->nNumButtons = nNewButtons;
1264
1265 /* insert new button data */
1266 for (nCount = 0; nCount < nAddButtons; nCount++) {
1267 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1268 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1269 btnPtr->idCommand = lpTbb[nCount].idCommand;
1270 btnPtr->fsState = lpTbb[nCount].fsState;
1271 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1272 btnPtr->dwData = lpTbb[nCount].dwData;
1273 btnPtr->iString = lpTbb[nCount].iString;
1274 btnPtr->bHot = FALSE;
1275
1276 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1277 TTTOOLINFOW ti;
1278
1279 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1280 ti.cbSize = sizeof (TTTOOLINFOW);
1281 ti.hwnd = hwnd;
1282 ti.uId = btnPtr->idCommand;
1283 ti.hinst = 0;
1284 ti.lpszText = LPSTR_TEXTCALLBACKW;
1285
1286 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1287 0, (LPARAM)&ti);
1288 }
1289 }
1290
1291 TOOLBAR_CalcToolbar (hwnd);
1292
1293 InvalidateRect(hwnd, NULL, FALSE);
1294
1295 return TRUE;
1296}
1297
1298
1299static LRESULT
1300TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1301{
1302 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1303 INT nIndex;
1304
1305 if ((wParam) && (HIWORD(lParam) == 0)) {
1306 char szString[256];
1307 INT len;
1308 // TRACE("adding string from resource!\n");
1309
1310 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1311 szString, 256);
1312
1313 // TRACE("len=%d \"%s\"\n", len, szString);
1314 nIndex = infoPtr->nNumStrings;
1315 if (infoPtr->nNumStrings == 0) {
1316 infoPtr->strings =
1317 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR));
1318 }
1319 else {
1320 LPWSTR *oldStrings = infoPtr->strings;
1321 infoPtr->strings =
1322 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1323 memcpy (&infoPtr->strings[0], &oldStrings[0],
1324 sizeof(LPWSTR) * infoPtr->nNumStrings);
1325 COMCTL32_Free (oldStrings);
1326 }
1327
1328 infoPtr->strings[infoPtr->nNumStrings] =
1329 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1330 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1331 infoPtr->nNumStrings++;
1332 }
1333 else {
1334 LPSTR p = (LPSTR)lParam;
1335 INT len;
1336
1337 if (p == NULL)
1338 return -1;
1339 // TRACE("adding string(s) from array!\n");
1340
1341 nIndex = infoPtr->nNumStrings;
1342 while (*p) {
1343 len = lstrlenA (p);
1344 // TRACE("len=%d \"%s\"\n", len, p);
1345
1346 if (infoPtr->nNumStrings == 0) {
1347 infoPtr->strings =
1348 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR));
1349 }
1350 else {
1351 LPWSTR *oldStrings = infoPtr->strings;
1352 infoPtr->strings =
1353 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1354 memcpy (&infoPtr->strings[0], &oldStrings[0],
1355 sizeof(LPWSTR) * infoPtr->nNumStrings);
1356 COMCTL32_Free (oldStrings);
1357 }
1358
1359 infoPtr->strings[infoPtr->nNumStrings] =
1360 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1361 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1362 infoPtr->nNumStrings++;
1363
1364 p += (len+1);
1365 }
1366 }
1367
1368 return nIndex;
1369}
1370
1371
1372static LRESULT
1373TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1374{
1375#define MAX_RESOURCE_STRING_LENGTH 512
1376 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1377 INT nIndex;
1378
1379 if ((wParam) && (HIWORD(lParam) == 0)) {
1380 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1381 INT len;
1382 // TRACE("adding string from resource!\n");
1383
1384 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1385 szString, MAX_RESOURCE_STRING_LENGTH);
1386
1387 // TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1388 // TRACE("First char: 0x%x\n", *szString);
1389 if (szString[0] == L'|')
1390 {
1391 PWSTR p = szString + 1;
1392
1393 nIndex = infoPtr->nNumStrings;
1394 while (*p != L'|') {
1395
1396 if (infoPtr->nNumStrings == 0) {
1397 infoPtr->strings =
1398 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR));
1399 }
1400 else {
1401 LPWSTR *oldStrings = infoPtr->strings;
1402 infoPtr->strings =
1403 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1404 memcpy (&infoPtr->strings[0], &oldStrings[0],
1405 sizeof(LPWSTR) * infoPtr->nNumStrings);
1406 COMCTL32_Free (oldStrings);
1407 }
1408
1409 len = COMCTL32_StrChrW (p, L'|') - p;
1410 // TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1411 infoPtr->strings[infoPtr->nNumStrings] =
1412 (WCHAR *)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1413 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1414 infoPtr->nNumStrings++;
1415
1416 p += (len+1);
1417 }
1418 }
1419 else
1420 {
1421 nIndex = infoPtr->nNumStrings;
1422 if (infoPtr->nNumStrings == 0) {
1423 infoPtr->strings =
1424 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR));
1425 }
1426 else {
1427 LPWSTR *oldStrings = infoPtr->strings;
1428 infoPtr->strings =
1429 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1430 memcpy (&infoPtr->strings[0], &oldStrings[0],
1431 sizeof(LPWSTR) * infoPtr->nNumStrings);
1432 COMCTL32_Free (oldStrings);
1433 }
1434
1435 infoPtr->strings[infoPtr->nNumStrings] =
1436 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1437 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1438 infoPtr->nNumStrings++;
1439 }
1440 }
1441 else {
1442 LPWSTR p = (LPWSTR)lParam;
1443 INT len;
1444
1445 if (p == NULL)
1446 return -1;
1447 // TRACE("adding string(s) from array!\n");
1448 nIndex = infoPtr->nNumStrings;
1449 while (*p) {
1450 len = lstrlenW (p);
1451
1452 // TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1453 if (infoPtr->nNumStrings == 0) {
1454 infoPtr->strings =
1455 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR));
1456 }
1457 else {
1458 LPWSTR *oldStrings = infoPtr->strings;
1459 infoPtr->strings =
1460 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1461 memcpy (&infoPtr->strings[0], &oldStrings[0],
1462 sizeof(LPWSTR) * infoPtr->nNumStrings);
1463 COMCTL32_Free (oldStrings);
1464 }
1465
1466 infoPtr->strings[infoPtr->nNumStrings] =
1467 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1468 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1469 infoPtr->nNumStrings++;
1470
1471 p += (len+1);
1472 }
1473 }
1474
1475 return nIndex;
1476}
1477
1478
1479static LRESULT
1480TOOLBAR_AutoSize (HWND hwnd)
1481{
1482 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1483 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1484 RECT parent_rect;
1485 RECT window_rect;
1486 HWND parent;
1487 INT x, y;
1488 INT cx, cy;
1489 UINT uPosFlags = SWP_NOZORDER;
1490
1491 // TRACE("resize forced, style=%lx!\n", dwStyle);
1492
1493 parent = GetParent (hwnd);
1494 GetClientRect(parent, &parent_rect);
1495
1496 x = parent_rect.left;
1497 y = parent_rect.top;
1498
1499 if (dwStyle & CCS_NORESIZE) {
1500 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1501 cx = 0;
1502 cy = 0;
1503 }
1504 else {
1505 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1506 TOOLBAR_CalcToolbar (hwnd);
1507 InvalidateRect( hwnd, NULL, TRUE );
1508 cy = infoPtr->nHeight;
1509 cx = infoPtr->nWidth;
1510
1511 if (dwStyle & CCS_NOMOVEY) {
1512 GetWindowRect(hwnd, &window_rect);
1513 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1514 y = window_rect.top;
1515 }
1516 }
1517
1518 if (dwStyle & CCS_NOPARENTALIGN)
1519 uPosFlags |= SWP_NOMOVE;
1520
1521 if (!(dwStyle & CCS_NODIVIDER))
1522 cy += GetSystemMetrics(SM_CYEDGE);
1523
1524 if (dwStyle & WS_BORDER)
1525 {
1526 x = y = 1;
1527 cy += GetSystemMetrics(SM_CYEDGE);
1528 cx += GetSystemMetrics(SM_CYEDGE);
1529 }
1530
1531 infoPtr->bAutoSize = TRUE;
1532 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1533 cx, cy, uPosFlags);
1534 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1535 * the setwindowpos calls */
1536 infoPtr->bAutoSize = FALSE;
1537
1538 return 0;
1539}
1540
1541
1542static LRESULT
1543TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1544{
1545 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1546
1547 return infoPtr->nNumButtons;
1548}
1549
1550
1551static LRESULT
1552TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1553{
1554 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1555
1556 if (infoPtr == NULL) {
1557// ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1558// ERR("infoPtr == NULL!\n");
1559 return 0;
1560 }
1561
1562 infoPtr->dwStructSize = (DWORD)wParam;
1563
1564 return 0;
1565}
1566
1567
1568static LRESULT
1569TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1570{
1571 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1572 TBUTTON_INFO *btnPtr;
1573 INT nIndex;
1574
1575 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1576 if (nIndex == -1)
1577 return FALSE;
1578
1579 btnPtr = &infoPtr->buttons[nIndex];
1580 btnPtr->iBitmap = LOWORD(lParam);
1581
1582 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1583
1584 return TRUE;
1585}
1586
1587
1588static LRESULT
1589TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1590{
1591 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1592 TBUTTON_INFO *btnPtr;
1593 INT nIndex;
1594 INT nOldIndex = -1;
1595 BOOL bChecked = FALSE;
1596
1597 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1598 if (nIndex == -1)
1599 return FALSE;
1600
1601 btnPtr = &infoPtr->buttons[nIndex];
1602
1603 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1604 return FALSE;
1605
1606 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1607
1608 if (LOWORD(lParam) == FALSE)
1609 btnPtr->fsState &= ~TBSTATE_CHECKED;
1610 else {
1611 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1612 nOldIndex =
1613 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1614 if (nOldIndex == nIndex)
1615 return 0;
1616 if (nOldIndex != -1)
1617 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1618 }
1619 btnPtr->fsState |= TBSTATE_CHECKED;
1620 }
1621
1622 if( bChecked != LOWORD(lParam) )
1623 {
1624 if (nOldIndex != -1)
1625 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect, TRUE);
1626 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1627 }
1628
1629 /* FIXME: Send a WM_NOTIFY?? */
1630
1631 return TRUE;
1632}
1633
1634
1635static LRESULT
1636TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1637{
1638 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1639
1640 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1641}
1642
1643
1644static LRESULT
1645TOOLBAR_Customize (HWND hwnd)
1646{
1647 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1648 LRESULT ret;
1649 LPCVOID temp;
1650 HRSRC hRes;
1651 NMHDR nmhdr;
1652
1653 /* send TBN_BEGINADJUST notification */
1654 nmhdr.hwndFrom = hwnd;
1655 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1656 nmhdr.code = TBN_BEGINADJUST;
1657
1658 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1659 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1660
1661 if (!(hRes = FindResourceA (COMCTL32_hModule,
1662 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1663 RT_DIALOGA)))
1664 return FALSE;
1665
1666 if(!(temp = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1667 return FALSE;
1668
1669 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1670 (LPDLGTEMPLATEA)temp,
1671 hwnd,
1672 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1673 (LPARAM)infoPtr);
1674
1675 /* send TBN_ENDADJUST notification */
1676 nmhdr.code = TBN_ENDADJUST;
1677
1678 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1679 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1680
1681 return ret;
1682}
1683
1684
1685static LRESULT
1686TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1687{
1688 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1689 INT nIndex = (INT)wParam;
1690
1691 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1692 return FALSE;
1693
1694 if ((infoPtr->hwndToolTip) &&
1695 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1696 TTTOOLINFOA ti;
1697
1698 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1699 ti.cbSize = sizeof (TTTOOLINFOA);
1700 ti.hwnd = hwnd;
1701 ti.uId = infoPtr->buttons[nIndex].idCommand;
1702
1703 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1704 }
1705
1706 if (infoPtr->nNumButtons == 1) {
1707 // TRACE(" simple delete!\n");
1708 COMCTL32_Free (infoPtr->buttons);
1709 infoPtr->buttons = NULL;
1710 infoPtr->nNumButtons = 0;
1711 }
1712 else {
1713 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1714 // TRACE("complex delete! [nIndex=%d]\n", nIndex);
1715
1716 infoPtr->nNumButtons--;
1717 infoPtr->buttons = (TBUTTON_INFO*)COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1718 if (nIndex > 0) {
1719 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1720 nIndex * sizeof(TBUTTON_INFO));
1721 }
1722
1723 if (nIndex < infoPtr->nNumButtons) {
1724 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1725 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1726 }
1727
1728 COMCTL32_Free (oldButtons);
1729 }
1730
1731 TOOLBAR_CalcToolbar (hwnd);
1732
1733 InvalidateRect (hwnd, NULL, TRUE);
1734
1735 return TRUE;
1736}
1737
1738
1739static LRESULT
1740TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1741{
1742 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1743 TBUTTON_INFO *btnPtr;
1744 INT nIndex;
1745 DWORD bState;
1746
1747 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1748 if (nIndex == -1)
1749 return FALSE;
1750
1751 btnPtr = &infoPtr->buttons[nIndex];
1752
1753 bState = btnPtr->fsState & TBSTATE_ENABLED;
1754
1755 /* update the toolbar button state */
1756 if(LOWORD(lParam) == FALSE) {
1757 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1758 } else {
1759 btnPtr->fsState |= TBSTATE_ENABLED;
1760 }
1761
1762 /* redraw the button only if the state of the button changed */
1763 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
1764 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1765
1766 return TRUE;
1767}
1768
1769
1770static inline LRESULT
1771TOOLBAR_GetAnchorHighlight (HWND hwnd)
1772{
1773 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1774
1775 return infoPtr->bAnchor;
1776}
1777
1778
1779static LRESULT
1780TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1781{
1782 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1783 INT nIndex;
1784
1785 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1786 if (nIndex == -1)
1787 return -1;
1788
1789 return infoPtr->buttons[nIndex].iBitmap;
1790}
1791
1792
1793static inline LRESULT
1794TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1795{
1796 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1797}
1798
1799
1800static LRESULT
1801TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1802{
1803 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1804 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1805 INT nIndex = (INT)wParam;
1806 TBUTTON_INFO *btnPtr;
1807
1808 if (infoPtr == NULL)
1809 return FALSE;
1810
1811 if (lpTbb == NULL)
1812 return FALSE;
1813
1814 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1815 return FALSE;
1816
1817 btnPtr = &infoPtr->buttons[nIndex];
1818 lpTbb->iBitmap = btnPtr->iBitmap;
1819 lpTbb->idCommand = btnPtr->idCommand;
1820 lpTbb->fsState = btnPtr->fsState;
1821 lpTbb->fsStyle = btnPtr->fsStyle;
1822 lpTbb->dwData = btnPtr->dwData;
1823 lpTbb->iString = btnPtr->iString;
1824
1825 return TRUE;
1826}
1827
1828
1829static LRESULT
1830TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1831{
1832 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1833 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1834 TBUTTON_INFO *btnPtr;
1835 INT nIndex;
1836
1837 if (infoPtr == NULL)
1838 return -1;
1839 if (lpTbInfo == NULL)
1840 return -1;
1841 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1842 return -1;
1843
1844 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1845 if (nIndex == -1)
1846 return -1;
1847
1848 btnPtr = &infoPtr->buttons[nIndex];
1849
1850 if (lpTbInfo->dwMask & TBIF_COMMAND)
1851 lpTbInfo->idCommand = btnPtr->idCommand;
1852 if (lpTbInfo->dwMask & TBIF_IMAGE)
1853 lpTbInfo->iImage = btnPtr->iBitmap;
1854 if (lpTbInfo->dwMask & TBIF_LPARAM)
1855 lpTbInfo->lParam = btnPtr->dwData;
1856 if (lpTbInfo->dwMask & TBIF_SIZE)
1857 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1858 if (lpTbInfo->dwMask & TBIF_STATE)
1859 lpTbInfo->fsState = btnPtr->fsState;
1860 if (lpTbInfo->dwMask & TBIF_STYLE)
1861 lpTbInfo->fsStyle = btnPtr->fsStyle;
1862 if (lpTbInfo->dwMask & TBIF_TEXT) {
1863 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
1864 {
1865 lstrcpynWtoA (lpTbInfo->pszText,
1866 (LPWSTR)infoPtr->strings[btnPtr->iString],
1867 lpTbInfo->cchText);
1868 }
1869 else lpTbInfo->pszText[0]=0;
1870 }
1871 return nIndex;
1872}
1873
1874
1875static LRESULT
1876TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1877{
1878 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1879 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
1880 TBUTTON_INFO *btnPtr;
1881 INT nIndex;
1882
1883 if (infoPtr == NULL)
1884 return -1;
1885 if (lpTbInfo == NULL)
1886 return -1;
1887 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
1888 return -1;
1889
1890 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1891 if (nIndex == -1)
1892 return -1;
1893
1894 btnPtr = &infoPtr->buttons[nIndex];
1895
1896 if (lpTbInfo->dwMask & TBIF_COMMAND)
1897 lpTbInfo->idCommand = btnPtr->idCommand;
1898 if (lpTbInfo->dwMask & TBIF_IMAGE)
1899 lpTbInfo->iImage = btnPtr->iBitmap;
1900 if (lpTbInfo->dwMask & TBIF_LPARAM)
1901 lpTbInfo->lParam = btnPtr->dwData;
1902 if (lpTbInfo->dwMask & TBIF_SIZE)
1903 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1904 if (lpTbInfo->dwMask & TBIF_STATE)
1905 lpTbInfo->fsState = btnPtr->fsState;
1906 if (lpTbInfo->dwMask & TBIF_STYLE)
1907 lpTbInfo->fsStyle = btnPtr->fsStyle;
1908 if (lpTbInfo->dwMask & TBIF_TEXT) {
1909 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1910 lstrcpynW (lpTbInfo->pszText,
1911 (LPWSTR)infoPtr->strings[btnPtr->iString],
1912 lpTbInfo->cchText);
1913 }
1914
1915 return nIndex;
1916}
1917
1918
1919static LRESULT
1920TOOLBAR_GetButtonSize (HWND hwnd)
1921{
1922 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1923
1924 return MAKELONG((WORD)infoPtr->nButtonWidth,
1925 (WORD)infoPtr->nButtonHeight);
1926}
1927
1928
1929static LRESULT
1930TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1931{
1932 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1933 INT nIndex, nStringIndex;
1934
1935 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1936 if (nIndex == -1)
1937 return -1;
1938
1939 nStringIndex = infoPtr->buttons[nIndex].iString;
1940
1941 // TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1942
1943 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1944 return -1;
1945
1946 if (lParam == 0)
1947 return -1;
1948
1949 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1950
1951 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1952}
1953
1954
1955static LRESULT
1956TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1957{
1958 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1959 INT nIndex, nStringIndex;
1960
1961 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1962 if (nIndex == -1)
1963 return -1;
1964
1965 nStringIndex = infoPtr->buttons[nIndex].iString;
1966
1967 // TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1968
1969 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1970 return -1;
1971
1972 if (lParam == 0)
1973 return -1;
1974
1975 lstrcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1976
1977 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1978}
1979
1980
1981/* << TOOLBAR_GetColorScheme >> */
1982
1983
1984static LRESULT
1985TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1986{
1987 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1988
1989 return (LRESULT)infoPtr->himlDis;
1990}
1991
1992
1993inline static LRESULT
1994TOOLBAR_GetExtendedStyle (HWND hwnd)
1995{
1996 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1997
1998 return infoPtr->dwExStyle;
1999}
2000
2001
2002static LRESULT
2003TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2004{
2005 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2006
2007 return (LRESULT)infoPtr->himlHot;
2008}
2009
2010
2011static LRESULT
2012TOOLBAR_GetHotItem (HWND hwnd)
2013{
2014 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2015
2016 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2017 return -1;
2018
2019 if (infoPtr->nHotItem < 0)
2020 return -1;
2021
2022 return (LRESULT)infoPtr->nHotItem;
2023}
2024
2025
2026static LRESULT
2027TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2028{
2029 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2030
2031 return (LRESULT)infoPtr->himlDef;
2032}
2033
2034
2035/* << TOOLBAR_GetInsertMark >> */
2036/* << TOOLBAR_GetInsertMarkColor >> */
2037
2038
2039static LRESULT
2040TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2041{
2042 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2043 TBUTTON_INFO *btnPtr;
2044 LPRECT lpRect;
2045 INT nIndex;
2046
2047 if (infoPtr == NULL)
2048 return FALSE;
2049 nIndex = (INT)wParam;
2050 btnPtr = &infoPtr->buttons[nIndex];
2051 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2052 return FALSE;
2053 lpRect = (LPRECT)lParam;
2054 if (lpRect == NULL)
2055 return FALSE;
2056 if (btnPtr->fsState & TBSTATE_HIDDEN)
2057 return FALSE;
2058
2059 TOOLBAR_CalcToolbar( hwnd );
2060
2061 lpRect->left = btnPtr->rect.left;
2062 lpRect->right = btnPtr->rect.right;
2063 lpRect->bottom = btnPtr->rect.bottom;
2064 lpRect->top = btnPtr->rect.top;
2065
2066 return TRUE;
2067}
2068
2069
2070static LRESULT
2071TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2072{
2073 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2074 LPSIZE lpSize = (LPSIZE)lParam;
2075
2076 if (lpSize == NULL)
2077 return FALSE;
2078
2079 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2080 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2081
2082 // TRACE("maximum size %d x %d\n",
2083 // infoPtr->rcBound.right - infoPtr->rcBound.left,
2084 // infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2085
2086 return TRUE;
2087}
2088
2089
2090/* << TOOLBAR_GetObject >> */
2091/* << TOOLBAR_GetPadding >> */
2092
2093
2094static LRESULT
2095TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2096{
2097 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2098 TBUTTON_INFO *btnPtr;
2099 LPRECT lpRect;
2100 INT nIndex;
2101
2102 if (infoPtr == NULL)
2103 return FALSE;
2104 nIndex = (INT)wParam;
2105 btnPtr = &infoPtr->buttons[nIndex];
2106 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2107 return FALSE;
2108 lpRect = (LPRECT)lParam;
2109 if (lpRect == NULL)
2110 return FALSE;
2111
2112 lpRect->left = btnPtr->rect.left;
2113 lpRect->right = btnPtr->rect.right;
2114 lpRect->bottom = btnPtr->rect.bottom;
2115 lpRect->top = btnPtr->rect.top;
2116
2117 return TRUE;
2118}
2119
2120
2121static LRESULT
2122TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2123{
2124 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2125
2126 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2127 return infoPtr->nRows;
2128 else
2129 return 1;
2130}
2131
2132
2133static LRESULT
2134TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2135{
2136 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2137 INT nIndex;
2138
2139 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2140 if (nIndex == -1)
2141 return -1;
2142
2143 return infoPtr->buttons[nIndex].fsState;
2144}
2145
2146
2147static LRESULT
2148TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2149{
2150 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2151 INT nIndex;
2152
2153 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2154 if (nIndex == -1)
2155 return -1;
2156
2157 return infoPtr->buttons[nIndex].fsStyle;
2158}
2159
2160
2161static LRESULT
2162TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2163{
2164 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2165
2166 if (infoPtr == NULL)
2167 return 0;
2168
2169 return infoPtr->nMaxTextRows;
2170}
2171
2172
2173static LRESULT
2174TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2175{
2176 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2177
2178 if (infoPtr == NULL)
2179 return 0;
2180 return infoPtr->hwndToolTip;
2181}
2182
2183
2184static LRESULT
2185TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2186{
2187 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2188
2189 // TRACE("%s hwnd=0x%x stub!\n",
2190// infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2191
2192 return infoPtr->bUnicode;
2193}
2194
2195
2196inline static LRESULT
2197TOOLBAR_GetVersion (HWND hwnd)
2198{
2199 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2200 return infoPtr->iVersion;
2201}
2202
2203
2204static LRESULT
2205TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2206{
2207 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2208 TBUTTON_INFO *btnPtr;
2209 INT nIndex;
2210
2211 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2212 if (nIndex == -1)
2213 return FALSE;
2214
2215 btnPtr = &infoPtr->buttons[nIndex];
2216 if (LOWORD(lParam) == FALSE)
2217 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2218 else
2219 btnPtr->fsState |= TBSTATE_HIDDEN;
2220
2221 TOOLBAR_CalcToolbar (hwnd);
2222
2223 InvalidateRect (hwnd, NULL, TRUE);
2224
2225 return TRUE;
2226}
2227
2228
2229inline static LRESULT
2230TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2231{
2232 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2233}
2234
2235
2236static LRESULT
2237TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2238{
2239 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2240 TBUTTON_INFO *btnPtr;
2241 INT nIndex;
2242
2243 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2244 if (nIndex == -1)
2245 return FALSE;
2246
2247 btnPtr = &infoPtr->buttons[nIndex];
2248 if (LOWORD(lParam) == FALSE)
2249 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2250 else
2251 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2252
2253 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2254
2255 return TRUE;
2256}
2257
2258
2259static LRESULT
2260TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2261{
2262 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2263 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2264 INT nIndex = (INT)wParam;
2265 TBUTTON_INFO *oldButtons;
2266
2267 if (lpTbb == NULL)
2268 return FALSE;
2269
2270 if (nIndex == -1) {
2271 /* EPP: this seems to be an undocumented call (from my IE4)
2272 * I assume in that case that:
2273 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2274 * - index of insertion is at the end of existing buttons
2275 * I only see this happen with nIndex == -1, but it could have a special
2276 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2277 */
2278 int len;
2279 LPSTR ptr;
2280
2281 if(lpTbb->iString) {
2282 len = lstrlenA((char*)lpTbb->iString) + 2;
2283 ptr = (CHAR*)COMCTL32_Alloc(len);
2284 nIndex = infoPtr->nNumButtons;
2285 strcpy(ptr, (char*)lpTbb->iString);
2286 ptr[len - 1] = 0; /* ended by two '\0' */
2287 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2288 COMCTL32_Free(ptr);
2289 }
2290 else {
2291 // ERR("lpTbb->iString is NULL\n");
2292 return FALSE;
2293 }
2294
2295 } else if (nIndex < 0)
2296 return FALSE;
2297
2298 // TRACE("inserting button index=%d\n", nIndex);
2299 if (nIndex > infoPtr->nNumButtons) {
2300 nIndex = infoPtr->nNumButtons;
2301 // TRACE("adjust index=%d\n", nIndex);
2302 }
2303
2304 oldButtons = infoPtr->buttons;
2305 infoPtr->nNumButtons++;
2306 infoPtr->buttons = (TBUTTON_INFO*)COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2307 /* pre insert copy */
2308 if (nIndex > 0) {
2309 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2310 nIndex * sizeof(TBUTTON_INFO));
2311 }
2312
2313 /* insert new button */
2314 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2315 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2316 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2317 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2318 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2319 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2320
2321 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2322 TTTOOLINFOA ti;
2323
2324 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2325 ti.cbSize = sizeof (TTTOOLINFOA);
2326 ti.hwnd = hwnd;
2327 ti.uId = lpTbb->idCommand;
2328 ti.hinst = 0;
2329 ti.lpszText = LPSTR_TEXTCALLBACKA;
2330
2331 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2332 0, (LPARAM)&ti);
2333 }
2334
2335 /* post insert copy */
2336 if (nIndex < infoPtr->nNumButtons - 1) {
2337 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2338 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2339 }
2340
2341 COMCTL32_Free (oldButtons);
2342
2343 TOOLBAR_CalcToolbar (hwnd);
2344
2345 InvalidateRect (hwnd, NULL, FALSE);
2346
2347 return TRUE;
2348}
2349
2350
2351static LRESULT
2352TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2353{
2354 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2355 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2356 INT nIndex = (INT)wParam;
2357 TBUTTON_INFO *oldButtons;
2358
2359 if (lpTbb == NULL)
2360 return FALSE;
2361 if (nIndex < 0)
2362 return FALSE;
2363
2364 // TRACE("inserting button index=%d\n", nIndex);
2365 if (nIndex > infoPtr->nNumButtons) {
2366 nIndex = infoPtr->nNumButtons;
2367 // TRACE("adjust index=%d\n", nIndex);
2368 }
2369
2370 oldButtons = infoPtr->buttons;
2371 infoPtr->nNumButtons++;
2372 infoPtr->buttons = (TBUTTON_INFO*)COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2373 /* pre insert copy */
2374 if (nIndex > 0) {
2375 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2376 nIndex * sizeof(TBUTTON_INFO));
2377 }
2378
2379 /* insert new button */
2380 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2381 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2382 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2383 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2384 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2385 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2386
2387 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2388 TTTOOLINFOW ti;
2389
2390 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2391 ti.cbSize = sizeof (TTTOOLINFOW);
2392 ti.hwnd = hwnd;
2393 ti.uId = lpTbb->idCommand;
2394 ti.hinst = 0;
2395 ti.lpszText = LPSTR_TEXTCALLBACKW;
2396
2397 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2398 0, (LPARAM)&ti);
2399 }
2400
2401 /* post insert copy */
2402 if (nIndex < infoPtr->nNumButtons - 1) {
2403 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2404 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2405 }
2406
2407 COMCTL32_Free (oldButtons);
2408
2409 TOOLBAR_CalcToolbar (hwnd);
2410
2411 InvalidateRect (hwnd, NULL, FALSE);
2412
2413 return TRUE;
2414}
2415
2416
2417/* << TOOLBAR_InsertMarkHitTest >> */
2418
2419
2420static LRESULT
2421TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2422{
2423 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2424 INT nIndex;
2425
2426 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2427 if (nIndex == -1)
2428 return FALSE;
2429
2430 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2431}
2432
2433
2434static LRESULT
2435TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2436{
2437 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2438 INT nIndex;
2439
2440 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2441 if (nIndex == -1)
2442 return FALSE;
2443
2444 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2445}
2446
2447
2448static LRESULT
2449TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2450{
2451 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2452 INT nIndex;
2453
2454 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2455 if (nIndex == -1)
2456 return FALSE;
2457
2458 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2459}
2460
2461
2462static LRESULT
2463TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2464{
2465 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2466 INT nIndex;
2467
2468 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2469 if (nIndex == -1)
2470 return FALSE;
2471
2472 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2473}
2474
2475
2476static LRESULT
2477TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2478{
2479 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2480 INT nIndex;
2481
2482 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2483 if (nIndex == -1)
2484 return FALSE;
2485
2486 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2487}
2488
2489
2490static LRESULT
2491TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2492{
2493 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2494 INT nIndex;
2495
2496 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2497 if (nIndex == -1)
2498 return FALSE;
2499
2500 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2501}
2502
2503
2504/* << TOOLBAR_LoadImages >> */
2505/* << TOOLBAR_MapAccelerator >> */
2506/* << TOOLBAR_MarkButton >> */
2507/* << TOOLBAR_MoveButton >> */
2508
2509
2510static LRESULT
2511TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2512{
2513 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2514 TBUTTON_INFO *btnPtr;
2515 INT nIndex;
2516
2517 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2518 if (nIndex == -1)
2519 return FALSE;
2520
2521 btnPtr = &infoPtr->buttons[nIndex];
2522 if (LOWORD(lParam) == FALSE)
2523 btnPtr->fsState &= ~TBSTATE_PRESSED;
2524 else
2525 btnPtr->fsState |= TBSTATE_PRESSED;
2526
2527 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2528
2529 return TRUE;
2530}
2531
2532
2533/* << TOOLBAR_ReplaceBitmap >> */
2534
2535
2536static LRESULT
2537TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2538{
2539#if 0
2540 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2541 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2542
2543 if (lpSave == NULL) return 0;
2544
2545 if ((BOOL)wParam) {
2546 /* save toolbar information */
2547 // FIXME("save to \"%s\" \"%s\"\n",
2548 lpSave->pszSubKey, lpSave->pszValueName);
2549
2550
2551 }
2552 else {
2553 /* restore toolbar information */
2554
2555 // FIXME("restore from \"%s\" \"%s\"\n",
2556 lpSave->pszSubKey, lpSave->pszValueName);
2557
2558
2559 }
2560#endif
2561
2562 return 0;
2563}
2564
2565
2566static LRESULT
2567TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2568{
2569#if 0
2570 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2571 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2572
2573 if (lpSave == NULL)
2574 return 0;
2575
2576 if ((BOOL)wParam) {
2577 /* save toolbar information */
2578 // FIXME("save to \"%s\" \"%s\"\n",
2579 lpSave->pszSubKey, lpSave->pszValueName);
2580
2581
2582 }
2583 else {
2584 /* restore toolbar information */
2585
2586 // FIXME("restore from \"%s\" \"%s\"\n",
2587 lpSave->pszSubKey, lpSave->pszValueName);
2588
2589
2590 }
2591#endif
2592
2593 return 0;
2594}
2595
2596
2597static LRESULT
2598TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2599{
2600 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2601 BOOL bOldAnchor = infoPtr->bAnchor;
2602
2603 infoPtr->bAnchor = (BOOL)wParam;
2604
2605 return (LRESULT)bOldAnchor;
2606}
2607
2608
2609static LRESULT
2610TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2611{
2612 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2613
2614 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2615 return FALSE;
2616
2617// if (infoPtr->nNumButtons > 0)
2618// WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
2619// infoPtr->nNumButtons,
2620// infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
2621// LOWORD(lParam), HIWORD(lParam));
2622
2623 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2624 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2625
2626 /* uses image list internals directly */
2627 if (infoPtr->himlDef) {
2628 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
2629 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
2630 }
2631
2632 return TRUE;
2633}
2634
2635
2636static LRESULT
2637TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2638{
2639 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2640 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2641 TBUTTON_INFO *btnPtr;
2642 INT nIndex;
2643
2644 if (lptbbi == NULL)
2645 return FALSE;
2646 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2647 return FALSE;
2648
2649 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2650 if (nIndex == -1)
2651 return FALSE;
2652
2653 btnPtr = &infoPtr->buttons[nIndex];
2654 if (lptbbi->dwMask & TBIF_COMMAND)
2655 btnPtr->idCommand = lptbbi->idCommand;
2656 if (lptbbi->dwMask & TBIF_IMAGE)
2657 btnPtr->iBitmap = lptbbi->iImage;
2658 if (lptbbi->dwMask & TBIF_LPARAM)
2659 btnPtr->dwData = lptbbi->lParam;
2660/* if (lptbbi->dwMask & TBIF_SIZE) */
2661/* btnPtr->cx = lptbbi->cx; */
2662 if (lptbbi->dwMask & TBIF_STATE)
2663 btnPtr->fsState = lptbbi->fsState;
2664 if (lptbbi->dwMask & TBIF_STYLE)
2665 btnPtr->fsStyle = lptbbi->fsStyle;
2666
2667 if (lptbbi->dwMask & TBIF_TEXT) {
2668 if ((btnPtr->iString >= 0) ||
2669 (btnPtr->iString < infoPtr->nNumStrings)) {
2670 // TRACE("Ooooooch\n");
2671#if 0
2672 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2673 INT len = lstrlenA (lptbbi->pszText);
2674 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2675#endif
2676
2677 /* this is the ultimate sollution */
2678/* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2679 }
2680 }
2681
2682 return TRUE;
2683}
2684
2685
2686static LRESULT
2687TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2688{
2689 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2690 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2691 TBUTTON_INFO *btnPtr;
2692 INT nIndex;
2693
2694 if (lptbbi == NULL)
2695 return FALSE;
2696 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2697 return FALSE;
2698
2699 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2700 if (nIndex == -1)
2701 return FALSE;
2702
2703 btnPtr = &infoPtr->buttons[nIndex];
2704 if (lptbbi->dwMask & TBIF_COMMAND)
2705 btnPtr->idCommand = lptbbi->idCommand;
2706 if (lptbbi->dwMask & TBIF_IMAGE)
2707 btnPtr->iBitmap = lptbbi->iImage;
2708 if (lptbbi->dwMask & TBIF_LPARAM)
2709 btnPtr->dwData = lptbbi->lParam;
2710/* if (lptbbi->dwMask & TBIF_SIZE) */
2711/* btnPtr->cx = lptbbi->cx; */
2712 if (lptbbi->dwMask & TBIF_STATE)
2713 btnPtr->fsState = lptbbi->fsState;
2714 if (lptbbi->dwMask & TBIF_STYLE)
2715 btnPtr->fsStyle = lptbbi->fsStyle;
2716
2717 if (lptbbi->dwMask & TBIF_TEXT) {
2718 if ((btnPtr->iString >= 0) ||
2719 (btnPtr->iString < infoPtr->nNumStrings)) {
2720#if 0
2721 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2722 INT len = lstrlenW (lptbbi->pszText);
2723 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2724#endif
2725
2726 /* this is the ultimate sollution */
2727/* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2728 }
2729 }
2730
2731 return TRUE;
2732}
2733
2734
2735static LRESULT
2736TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2737{
2738 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2739
2740 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2741 {
2742// ERR("invalid parameter\n");
2743 return FALSE;
2744 }
2745
2746 /* Button size can only be set before adding any button to the toolbar
2747 according to the documentation. */
2748 /* this appears to be wrong. WINZIP32.EXE (ver 8) calls this on
2749 one of its buttons after adding it to the toolbar, and it
2750 checks that the return value is nonzero - mjm */
2751 if( infoPtr->nNumButtons != 0 )
2752 {
2753 // FIXME("Button size set after button in toolbar\n");
2754 return TRUE;
2755 }
2756
2757 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2758 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2759 return TRUE;
2760}
2761
2762
2763static LRESULT
2764TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2765{
2766 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2767
2768 if (infoPtr == NULL)
2769 return FALSE;
2770
2771 infoPtr->cxMin = (INT)LOWORD(lParam);
2772 infoPtr->cxMax = (INT)HIWORD(lParam);
2773
2774 return TRUE;
2775}
2776
2777
2778static LRESULT
2779TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2780{
2781 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2782 INT nIndex = (INT)wParam;
2783
2784 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2785 return FALSE;
2786
2787 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2788
2789 if (infoPtr->hwndToolTip) {
2790
2791 // FIXME("change tool tip!\n");
2792
2793 }
2794
2795 return TRUE;
2796}
2797
2798
2799/* << TOOLBAR_SetColorScheme >> */
2800
2801
2802static LRESULT
2803TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2804{
2805 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2806 HIMAGELIST himlTemp;
2807
2808
2809 himlTemp = infoPtr->himlDis;
2810 infoPtr->himlDis = (HIMAGELIST)lParam;
2811
2812 /* FIXME: redraw ? */
2813
2814 return (LRESULT)himlTemp;
2815}
2816
2817
2818static LRESULT
2819TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2820{
2821 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2822 DWORD dwTemp;
2823
2824 dwTemp = infoPtr->dwDTFlags;
2825 infoPtr->dwDTFlags =
2826 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2827
2828 return (LRESULT)dwTemp;
2829}
2830
2831
2832static LRESULT
2833TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2834{
2835 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2836 DWORD dwTemp;
2837
2838 dwTemp = infoPtr->dwExStyle;
2839 infoPtr->dwExStyle = (DWORD)lParam;
2840
2841 return (LRESULT)dwTemp;
2842}
2843
2844
2845static LRESULT
2846TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2847{
2848 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2849 HIMAGELIST himlTemp;
2850
2851 himlTemp = infoPtr->himlHot;
2852 infoPtr->himlHot = (HIMAGELIST)lParam;
2853
2854 /* FIXME: redraw ? */
2855
2856 return (LRESULT)himlTemp;
2857}
2858
2859
2860static LRESULT
2861TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
2862{
2863 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2864 INT nOldHotItem = infoPtr->nHotItem;
2865
2866 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
2867 {
2868 infoPtr->nHotItem = (INT)wParam;
2869
2870 /* FIXME: What else must be done ??? */
2871
2872 }
2873
2874 if (nOldHotItem < 0)
2875 return -1;
2876
2877 return (LRESULT)nOldHotItem;
2878}
2879
2880
2881static LRESULT
2882TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2883{
2884 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2885 HIMAGELIST himlTemp;
2886
2887 himlTemp = infoPtr->himlDef;
2888 infoPtr->himlDef = (HIMAGELIST)lParam;
2889
2890 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
2891 /* FIXME: redraw ? */
2892
2893 return (LRESULT)himlTemp;
2894}
2895
2896
2897static LRESULT
2898TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2899{
2900 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2901
2902 infoPtr->nIndent = (INT)wParam;
2903
2904 TOOLBAR_CalcToolbar (hwnd);
2905
2906 InvalidateRect(hwnd, NULL, FALSE);
2907
2908 return TRUE;
2909}
2910
2911
2912/* << TOOLBAR_SetInsertMark >> */
2913
2914
2915static LRESULT
2916TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2917{
2918 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2919
2920 infoPtr->clrInsertMark = (COLORREF)lParam;
2921
2922 /* FIXME : redraw ??*/
2923
2924 return 0;
2925}
2926
2927
2928static LRESULT
2929TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2930{
2931 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2932
2933 if (infoPtr == NULL)
2934 return FALSE;
2935
2936 infoPtr->nMaxTextRows = (INT)wParam;
2937
2938 return TRUE;
2939}
2940
2941
2942/* << TOOLBAR_SetPadding >> */
2943
2944
2945static LRESULT
2946TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2947{
2948 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2949 HWND hwndOldNotify;
2950
2951 if (infoPtr == NULL)
2952 return 0;
2953 hwndOldNotify = infoPtr->hwndNotify;
2954 infoPtr->hwndNotify = (HWND)wParam;
2955
2956 return hwndOldNotify;
2957}
2958
2959
2960static LRESULT
2961TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2962{
2963 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2964 LPRECT lprc = (LPRECT)lParam;
2965
2966 if (LOWORD(wParam) > 1) {
2967
2968 // FIXME("multiple rows not supported!\n");
2969
2970 }
2971
2972 /* recalculate toolbar */
2973 TOOLBAR_CalcToolbar (hwnd);
2974
2975 /* return bounding rectangle */
2976 if (lprc) {
2977 lprc->left = infoPtr->rcBound.left;
2978 lprc->right = infoPtr->rcBound.right;
2979 lprc->top = infoPtr->rcBound.top;
2980 lprc->bottom = infoPtr->rcBound.bottom;
2981 }
2982
2983 /* repaint toolbar */
2984 InvalidateRect(hwnd, NULL, FALSE);
2985
2986 return 0;
2987}
2988
2989
2990static LRESULT
2991TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2992{
2993 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2994 TBUTTON_INFO *btnPtr;
2995 INT nIndex;
2996
2997 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2998 if (nIndex == -1)
2999 return FALSE;
3000
3001 btnPtr = &infoPtr->buttons[nIndex];
3002 btnPtr->fsState = LOWORD(lParam);
3003
3004 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3005
3006 return TRUE;
3007}
3008
3009
3010static LRESULT
3011TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3012{
3013 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3014 TBUTTON_INFO *btnPtr;
3015 INT nIndex;
3016
3017 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3018 if (nIndex == -1)
3019 return FALSE;
3020
3021 btnPtr = &infoPtr->buttons[nIndex];
3022 btnPtr->fsStyle = LOWORD(lParam);
3023
3024 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3025
3026 if (infoPtr->hwndToolTip) {
3027 // FIXME("change tool tip!\n");
3028 }
3029
3030 return TRUE;
3031}
3032
3033
3034inline static LRESULT
3035TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3036{
3037 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3038
3039 if (infoPtr == NULL)
3040 return 0;
3041 infoPtr->hwndToolTip = (HWND)wParam;
3042 return 0;
3043}
3044
3045
3046static LRESULT
3047TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3048{
3049 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3050 BOOL bTemp;
3051
3052 // TRACE("%s hwnd=0x%04x stub!\n",
3053// ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3054
3055 bTemp = infoPtr->bUnicode;
3056 infoPtr->bUnicode = (BOOL)wParam;
3057
3058 return bTemp;
3059}
3060
3061
3062static LRESULT
3063TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3064{
3065 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3066 INT iOldVersion = infoPtr->iVersion;
3067
3068 infoPtr->iVersion = iVersion;
3069
3070 return iOldVersion;
3071}
3072
3073
3074static LRESULT
3075TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3076{
3077 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3078 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3079 LOGFONTA logFont;
3080
3081 /* initialize info structure */
3082 infoPtr->nButtonHeight = 22;
3083 infoPtr->nButtonWidth = 24;
3084 infoPtr->nBitmapHeight = 15;
3085 infoPtr->nBitmapWidth = 16;
3086
3087 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3088 infoPtr->nRows = 1;
3089 infoPtr->nMaxTextRows = 1;
3090 infoPtr->cxMin = -1;
3091 infoPtr->cxMax = -1;
3092 infoPtr->nNumBitmaps = 0;
3093 infoPtr->nNumStrings = 0;
3094
3095 infoPtr->bCaptured = FALSE;
3096 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3097 infoPtr->nButtonDown = -1;
3098 infoPtr->nOldHit = -1;
3099 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3100 infoPtr->hwndNotify = GetParent (hwnd);
3101 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3102 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3103 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3104 infoPtr->iVersion = 0;
3105
3106 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3107 infoPtr->hFont = CreateFontIndirectA (&logFont);
3108
3109 if (dwStyle & TBSTYLE_TOOLTIPS) {
3110 /* Create tooltip control */
3111 infoPtr->hwndToolTip =
3112 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3113 CW_USEDEFAULT, CW_USEDEFAULT,
3114 CW_USEDEFAULT, CW_USEDEFAULT,
3115 hwnd, 0, 0, 0);
3116
3117 /* Send NM_TOOLTIPSCREATED notification */
3118 if (infoPtr->hwndToolTip) {
3119 NMTOOLTIPSCREATED nmttc;
3120
3121 nmttc.hdr.hwndFrom = hwnd;
3122 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3123 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3124 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3125
3126 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3127 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3128 }
3129 }
3130
3131 return 0;
3132}
3133
3134
3135static LRESULT
3136TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3137{
3138 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3139
3140 /* delete tooltip control */
3141 if (infoPtr->hwndToolTip)
3142 DestroyWindow (infoPtr->hwndToolTip);
3143
3144 /* delete button data */
3145 if (infoPtr->buttons)
3146 COMCTL32_Free (infoPtr->buttons);
3147
3148 /* delete strings */
3149 if (infoPtr->strings) {
3150 INT i;
3151 for (i = 0; i < infoPtr->nNumStrings; i++)
3152 if (infoPtr->strings[i])
3153 COMCTL32_Free (infoPtr->strings[i]);
3154
3155 COMCTL32_Free (infoPtr->strings);
3156 }
3157
3158 /* destroy internal image list */
3159 if (infoPtr->himlInt)
3160 ImageList_Destroy (infoPtr->himlInt);
3161
3162 /* delete default font */
3163 if (infoPtr->hFont)
3164 DeleteObject (infoPtr->hFont);
3165
3166 /* free toolbar info data */
3167 COMCTL32_Free (infoPtr);
3168 SetWindowLongA (hwnd, 0, 0);
3169
3170 return 0;
3171}
3172
3173
3174static LRESULT
3175TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3176{
3177 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3178
3179 if (infoPtr->bTransparent)
3180 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3181
3182 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3183}
3184
3185
3186static LRESULT
3187TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3188{
3189 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3190
3191 return infoPtr->hFont;
3192}
3193
3194
3195static LRESULT
3196TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3197{
3198 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3199 TBUTTON_INFO *btnPtr;
3200 POINT pt;
3201 INT nHit;
3202
3203 pt.x = (INT)LOWORD(lParam);
3204 pt.y = (INT)HIWORD(lParam);
3205 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3206
3207 if (nHit >= 0) {
3208 btnPtr = &infoPtr->buttons[nHit];
3209 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3210 return 0;
3211 SetCapture (hwnd);
3212 infoPtr->bCaptured = TRUE;
3213 infoPtr->nButtonDown = nHit;
3214
3215 btnPtr->fsState |= TBSTATE_PRESSED;
3216
3217 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3218 }
3219 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3220 TOOLBAR_Customize (hwnd);
3221
3222 return 0;
3223}
3224
3225
3226static LRESULT
3227TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3228{
3229 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3230 TBUTTON_INFO *btnPtr;
3231 POINT pt;
3232 INT nHit;
3233
3234 if (infoPtr->hwndToolTip)
3235 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3236 WM_LBUTTONDOWN, wParam, lParam);
3237
3238 pt.x = (INT)LOWORD(lParam);
3239 pt.y = (INT)HIWORD(lParam);
3240 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3241
3242 if (nHit >= 0) {
3243 btnPtr = &infoPtr->buttons[nHit];
3244 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3245 return 0;
3246
3247 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
3248 {
3249 NMTOOLBARA nmtb;
3250
3251 nmtb.hdr.hwndFrom = hwnd;
3252 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3253 nmtb.hdr.code = TBN_DROPDOWN;
3254 nmtb.iItem = btnPtr->idCommand;
3255
3256 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3257 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3258 }
3259
3260 SetCapture (hwnd);
3261 infoPtr->bCaptured = TRUE;
3262 infoPtr->nButtonDown = nHit;
3263 infoPtr->nOldHit = nHit;
3264
3265 btnPtr->fsState |= TBSTATE_PRESSED;
3266 btnPtr->bHot = FALSE;
3267
3268 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3269 }
3270
3271 return 0;
3272}
3273
3274static LRESULT
3275TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3276{
3277 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3278 TBUTTON_INFO *btnPtr;
3279 POINT pt;
3280 INT nHit;
3281 INT nOldIndex = -1;
3282 BOOL bSendMessage = TRUE;
3283
3284 if (infoPtr->hwndToolTip)
3285 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3286 WM_LBUTTONUP, wParam, lParam);
3287
3288 pt.x = (INT)LOWORD(lParam);
3289 pt.y = (INT)HIWORD(lParam);
3290 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3291
3292 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3293 if(infoPtr->nHotItem >= 0)
3294 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3295
3296 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3297 infoPtr->bCaptured = FALSE;
3298 ReleaseCapture ();
3299 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3300 btnPtr->fsState &= ~TBSTATE_PRESSED;
3301
3302 if (nHit == infoPtr->nButtonDown) {
3303 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3304 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3305 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3306 infoPtr->nButtonDown);
3307 if (nOldIndex == infoPtr->nButtonDown)
3308 bSendMessage = FALSE;
3309 if ((nOldIndex != infoPtr->nButtonDown) &&
3310 (nOldIndex != -1))
3311 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3312 btnPtr->fsState |= TBSTATE_CHECKED;
3313 }
3314 else {
3315 if (btnPtr->fsState & TBSTATE_CHECKED)
3316 btnPtr->fsState &= ~TBSTATE_CHECKED;
3317 else
3318 btnPtr->fsState |= TBSTATE_CHECKED;
3319 }
3320 }
3321 }
3322 else
3323 bSendMessage = FALSE;
3324
3325 if (nOldIndex != -1)
3326 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect, TRUE);
3327
3328 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3329
3330 if (bSendMessage) {
3331 SendMessageA (GetParent(hwnd), WM_COMMAND,
3332 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3333
3334// if ((GetWindowLongA(hwnd, GWL_STYLE) & TBSTYLE_DROPDOWN) ||
3335// (btnPtr->fsStyle & 0x08/* BTNS_DROPDOWN */)) {
3336 /*
3337 * This appears to be an error. Instead of checking the style of the
3338 * button in question wine was checking the style of the toolbar
3339 * itself. This caused a number of strange behaviors. In my
3340 * invistigation i think the whole dropdown thing is still fairly
3341 * broken. but this helps fix some of the problems.
3342 */
3343
3344 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
3345 NMTOOLBARW nmtb;
3346
3347 nmtb.hdr.hwndFrom = hwnd;
3348 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3349 nmtb.hdr.code = TBN_DROPDOWN;
3350 nmtb.iItem = nHit;
3351 /* nmtb.tbButton not used with TBN_DROPDOWN */
3352 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) {
3353 nmtb.pszText = infoPtr->strings[btnPtr->iString];
3354 nmtb.cchText = lstrlenW(nmtb.pszText);
3355 } else {
3356 nmtb.pszText = NULL;
3357 nmtb.cchText = 0;
3358 }
3359 nmtb.rcButton = btnPtr->rect;
3360
3361 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
3362 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3363 }
3364 }
3365 infoPtr->nButtonDown = -1;
3366 infoPtr->nOldHit = -1;
3367 }
3368
3369 return 0;
3370}
3371
3372static LRESULT
3373TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3374{
3375 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3376 TBUTTON_INFO *hotBtnPtr;
3377
3378 if (infoPtr->nOldHit < 0)
3379 return TRUE;
3380
3381 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3382
3383 /* Redraw the button if the last button we were over is the hot button and it
3384 is enabled */
3385 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3386 {
3387 hotBtnPtr->bHot = FALSE;
3388
3389 InvalidateRect (hwnd, &hotBtnPtr->rect, TRUE);
3390 }
3391
3392 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3393 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3394
3395 return TRUE;
3396}
3397
3398static LRESULT
3399TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3400{
3401 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3402 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3403 POINT pt;
3404 INT nHit;
3405 TRACKMOUSEEVENT trackinfo;
3406
3407 /* fill in the TRACKMOUSEEVENT struct */
3408 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3409 trackinfo.dwFlags = TME_QUERY;
3410 trackinfo.hwndTrack = hwnd;
3411 trackinfo.dwHoverTime = HOVER_DEFAULT;
3412
3413 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3414 _TrackMouseEvent(&trackinfo);
3415
3416 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3417 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3418 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3419
3420 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3421 /* and can properly deactivate the hot toolbar button */
3422 _TrackMouseEvent(&trackinfo);
3423 }
3424
3425 if (infoPtr->hwndToolTip)
3426 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3427 WM_MOUSEMOVE, wParam, lParam);
3428
3429 pt.x = (INT)LOWORD(lParam);
3430 pt.y = (INT)HIWORD(lParam);
3431
3432 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3433
3434 if (infoPtr->nOldHit != nHit)
3435 {
3436 /* Remove the effect of an old hot button if the button was enabled and was
3437 drawn with the hot button effect */
3438 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
3439 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3440 {
3441 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3442 oldBtnPtr->bHot = FALSE;
3443
3444 InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
3445 }
3446
3447 /* It's not a separator or in nowhere. It's a hot button. */
3448 if (nHit >= 0)
3449 {
3450 btnPtr = &infoPtr->buttons[nHit];
3451 btnPtr->bHot = TRUE;
3452
3453 infoPtr->nHotItem = nHit;
3454
3455 /* only enabled buttons show hot effect */
3456 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3457 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3458 }
3459
3460 if (infoPtr->bCaptured) {
3461 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3462 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3463 btnPtr->fsState &= ~TBSTATE_PRESSED;
3464 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3465 }
3466 else if (nHit == infoPtr->nButtonDown) {
3467 btnPtr->fsState |= TBSTATE_PRESSED;
3468 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3469 }
3470 }
3471 infoPtr->nOldHit = nHit;
3472 }
3473 return 0;
3474}
3475
3476
3477inline static LRESULT
3478TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3479{
3480/* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3481 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3482/* else */
3483/* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3484}
3485
3486
3487inline static LRESULT
3488TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3489{
3490 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3491 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3492
3493 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3494}
3495
3496
3497static LRESULT
3498TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3499{
3500 TOOLBAR_INFO *infoPtr;
3501
3502 /* allocate memory for info structure */
3503 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3504 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3505
3506 /* paranoid!! */
3507 infoPtr->dwStructSize = sizeof(TBBUTTON);
3508
3509 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3510 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3511 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3512 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3513 }
3514
3515 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3516}
3517
3518
3519static LRESULT
3520TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3521{
3522 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3523 RECT rcWindow;
3524 HDC hdc;
3525
3526 if (dwStyle & WS_MINIMIZE)
3527 return 0; /* Nothing to do */
3528
3529 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3530
3531 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3532 return 0;
3533
3534 if (!(dwStyle & CCS_NODIVIDER))
3535 {
3536 GetWindowRect (hwnd, &rcWindow);
3537 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3538 if( dwStyle & WS_BORDER )
3539 OffsetRect (&rcWindow, 1, 1);
3540 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3541 }
3542
3543 ReleaseDC( hwnd, hdc );
3544
3545 return 0;
3546}
3547
3548
3549inline static LRESULT
3550TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3551{
3552 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3553 LPNMHDR lpnmh = (LPNMHDR)lParam;
3554
3555 // TRACE("passing WM_NOTIFY!\n");
3556
3557 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3558 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3559
3560#if 0
3561 if (lpnmh->code == TTN_GETDISPINFOA) {
3562 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3563
3564 // FIXME("retrieving ASCII string\n");
3565
3566 }
3567 else if (lpnmh->code == TTN_GETDISPINFOW) {
3568 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3569
3570 // FIXME("retrieving UNICODE string\n");
3571
3572 }
3573#endif
3574 }
3575
3576 return 0;
3577}
3578
3579
3580static LRESULT
3581TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3582{
3583 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3584 HDC hdc;
3585 PAINTSTRUCT ps;
3586
3587 /* fill ps.rcPaint with a default rect */
3588 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
3589
3590 TOOLBAR_CalcToolbar( hwnd );
3591 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
3592 TOOLBAR_Refresh (hwnd, hdc, &ps);
3593 if (!wParam) EndPaint (hwnd, &ps);
3594
3595 return 0;
3596}
3597
3598
3599static LRESULT
3600TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3601{
3602 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3603 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3604 RECT parent_rect;
3605 RECT window_rect;
3606 HWND parent;
3607 INT x, y;
3608 INT cx, cy;
3609 INT flags;
3610 UINT uPosFlags = 0;
3611
3612 /* Resize deadlock check */
3613 if (infoPtr->bAutoSize) {
3614 infoPtr->bAutoSize = FALSE;
3615 return 0;
3616 }
3617
3618 flags = (INT) wParam;
3619
3620 /* FIXME for flags =
3621 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3622 */
3623
3624 // TRACE("sizing toolbar!\n");
3625
3626 if (flags == SIZE_RESTORED) {
3627 /* width and height don't apply */
3628 parent = GetParent (hwnd);
3629 GetClientRect(parent, &parent_rect);
3630 x = parent_rect.left;
3631 y = parent_rect.top;
3632
3633 if (dwStyle & CCS_NORESIZE) {
3634 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3635
3636 /*
3637 * this sets the working width of the toolbar, and
3638 * Calc Toolbar will not adjust it, only the height
3639 */
3640 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3641 cy = infoPtr->nHeight;
3642 cx = infoPtr->nWidth;
3643 TOOLBAR_CalcToolbar (hwnd);
3644 infoPtr->nWidth = cx;
3645 infoPtr->nHeight = cy;
3646 }
3647 else {
3648 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3649 TOOLBAR_CalcToolbar (hwnd);
3650 cy = infoPtr->nHeight;
3651 cx = infoPtr->nWidth;
3652
3653 if (dwStyle & CCS_NOMOVEY) {
3654 GetWindowRect(hwnd, &window_rect);
3655 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3656 y = window_rect.top;
3657 }
3658 }
3659
3660 if (dwStyle & CCS_NOPARENTALIGN) {
3661 uPosFlags |= SWP_NOMOVE;
3662 cy = infoPtr->nHeight;
3663 cx = infoPtr->nWidth;
3664 }
3665
3666 if (!(dwStyle & CCS_NODIVIDER))
3667 cy += GetSystemMetrics(SM_CYEDGE);
3668
3669 if (dwStyle & WS_BORDER)
3670 {
3671 x = y = 1;
3672 cy += GetSystemMetrics(SM_CYEDGE);
3673 cx += GetSystemMetrics(SM_CYEDGE);
3674 }
3675
3676 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3677 cx, cy, uPosFlags | SWP_NOZORDER);
3678 }
3679 return 0;
3680}
3681
3682
3683static LRESULT
3684TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3685{
3686 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3687
3688 if (nType == GWL_STYLE) {
3689 if (lpStyle->styleNew & TBSTYLE_LIST) {
3690 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3691 }
3692 else {
3693 infoPtr->dwDTFlags = DT_CENTER;
3694 }
3695 }
3696
3697 TOOLBAR_AutoSize (hwnd);
3698
3699 InvalidateRect(hwnd, NULL, FALSE);
3700
3701 return 0;
3702}
3703
3704
3705
3706static LRESULT WINAPI
3707ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3708{
3709
3710 switch (uMsg)
3711 {
3712 case WM_DESTROY:
3713 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3714
3715 case WM_NCCREATE:
3716 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3717 }
3718
3719 if (!TOOLBAR_GetInfoPtr (hwnd))
3720 {
3721 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3722 }
3723
3724 switch (uMsg)
3725 {
3726 case TB_ADDBITMAP:
3727 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3728
3729 case TB_ADDBUTTONSA:
3730 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3731
3732 case TB_ADDBUTTONSW:
3733 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3734
3735 case TB_ADDSTRINGA:
3736 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3737
3738 case TB_ADDSTRINGW:
3739 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3740
3741 case TB_AUTOSIZE:
3742 return TOOLBAR_AutoSize (hwnd);
3743
3744 case TB_BUTTONCOUNT:
3745 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3746
3747 case TB_BUTTONSTRUCTSIZE:
3748 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3749
3750 case TB_CHANGEBITMAP:
3751 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3752
3753 case TB_CHECKBUTTON:
3754 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3755
3756 case TB_COMMANDTOINDEX:
3757 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3758
3759 case TB_CUSTOMIZE:
3760 return TOOLBAR_Customize (hwnd);
3761
3762 case TB_DELETEBUTTON:
3763 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3764
3765 case TB_ENABLEBUTTON:
3766 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3767
3768 case TB_GETANCHORHIGHLIGHT:
3769 return TOOLBAR_GetAnchorHighlight (hwnd);
3770
3771 case TB_GETBITMAP:
3772 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3773
3774 case TB_GETBITMAPFLAGS:
3775 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3776
3777 case TB_GETBUTTON:
3778 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3779
3780 case TB_GETBUTTONINFOA:
3781 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3782
3783 case TB_GETBUTTONINFOW:
3784 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3785
3786 case TB_GETBUTTONSIZE:
3787 return TOOLBAR_GetButtonSize (hwnd);
3788
3789 case TB_GETBUTTONTEXTA:
3790 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3791
3792 case TB_GETBUTTONTEXTW:
3793 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
3794
3795/* case TB_GETCOLORSCHEME: */ /* 4.71 */
3796
3797 case TB_GETDISABLEDIMAGELIST:
3798 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3799
3800 case TB_GETEXTENDEDSTYLE:
3801 return TOOLBAR_GetExtendedStyle (hwnd);
3802
3803 case TB_GETHOTIMAGELIST:
3804 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3805
3806 case TB_GETHOTITEM:
3807 return TOOLBAR_GetHotItem (hwnd);
3808
3809 case TB_GETIMAGELIST:
3810 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3811
3812/* case TB_GETINSERTMARK: */ /* 4.71 */
3813/* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
3814
3815 case TB_GETITEMRECT:
3816 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3817
3818 case TB_GETMAXSIZE:
3819 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3820
3821/* case TB_GETOBJECT: */ /* 4.71 */
3822/* case TB_GETPADDING: */ /* 4.71 */
3823
3824 case TB_GETRECT:
3825 return TOOLBAR_GetRect (hwnd, wParam, lParam);
3826
3827 case TB_GETROWS:
3828 return TOOLBAR_GetRows (hwnd, wParam, lParam);
3829
3830 case TB_GETSTATE:
3831 return TOOLBAR_GetState (hwnd, wParam, lParam);
3832
3833 case TB_GETSTYLE:
3834 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3835
3836 case TB_GETTEXTROWS:
3837 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3838
3839 case TB_GETTOOLTIPS:
3840 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3841
3842 case TB_GETUNICODEFORMAT:
3843 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3844
3845 case CCM_GETVERSION:
3846 return TOOLBAR_GetVersion (hwnd);
3847
3848 case TB_HIDEBUTTON:
3849 return TOOLBAR_HideButton (hwnd, wParam, lParam);
3850
3851 case TB_HITTEST:
3852 return TOOLBAR_HitTest (hwnd, wParam, lParam);
3853
3854 case TB_INDETERMINATE:
3855 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3856
3857 case TB_INSERTBUTTONA:
3858 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3859
3860 case TB_INSERTBUTTONW:
3861 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
3862
3863/* case TB_INSERTMARKHITTEST: */ /* 4.71 */
3864
3865 case TB_ISBUTTONCHECKED:
3866 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3867
3868 case TB_ISBUTTONENABLED:
3869 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3870
3871 case TB_ISBUTTONHIDDEN:
3872 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3873
3874 case TB_ISBUTTONHIGHLIGHTED:
3875 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3876
3877 case TB_ISBUTTONINDETERMINATE:
3878 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3879
3880 case TB_ISBUTTONPRESSED:
3881 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3882
3883 case TB_LOADIMAGES: /* 4.70 */
3884 // FIXME("missing standard imagelists\n");
3885 return 0;
3886
3887/* case TB_MAPACCELERATORA: */ /* 4.71 */
3888/* case TB_MAPACCELERATORW: */ /* 4.71 */
3889/* case TB_MARKBUTTON: */ /* 4.71 */
3890/* case TB_MOVEBUTTON: */ /* 4.71 */
3891
3892 case TB_PRESSBUTTON:
3893 return TOOLBAR_PressButton (hwnd, wParam, lParam);
3894
3895/* case TB_REPLACEBITMAP: */
3896
3897 case TB_SAVERESTOREA:
3898 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3899
3900 case TB_SAVERESTOREW:
3901 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
3902
3903 case TB_SETANCHORHIGHLIGHT:
3904 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
3905
3906 case TB_SETBITMAPSIZE:
3907 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3908
3909 case TB_SETBUTTONINFOA:
3910 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3911
3912 case TB_SETBUTTONINFOW:
3913 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
3914
3915 case TB_SETBUTTONSIZE:
3916 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3917
3918 case TB_SETBUTTONWIDTH:
3919 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3920
3921 case TB_SETCMDID:
3922 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3923
3924/* case TB_SETCOLORSCHEME: */ /* 4.71 */
3925
3926 case TB_SETDISABLEDIMAGELIST:
3927 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3928
3929 case TB_SETDRAWTEXTFLAGS:
3930 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3931
3932 case TB_SETEXTENDEDSTYLE:
3933 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3934
3935 case TB_SETHOTIMAGELIST:
3936 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3937
3938 case TB_SETHOTITEM:
3939 return TOOLBAR_SetHotItem (hwnd, wParam);
3940
3941 case TB_SETIMAGELIST:
3942 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3943
3944 case TB_SETINDENT:
3945 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3946
3947/* case TB_SETINSERTMARK: */ /* 4.71 */
3948
3949 case TB_SETINSERTMARKCOLOR:
3950 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3951
3952 case TB_SETMAXTEXTROWS:
3953 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3954
3955/* case TB_SETPADDING: */ /* 4.71 */
3956
3957 case TB_SETPARENT:
3958 return TOOLBAR_SetParent (hwnd, wParam, lParam);
3959
3960 case TB_SETROWS:
3961 return TOOLBAR_SetRows (hwnd, wParam, lParam);
3962
3963 case TB_SETSTATE:
3964 return TOOLBAR_SetState (hwnd, wParam, lParam);
3965
3966 case TB_SETSTYLE:
3967 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3968
3969 case TB_SETTOOLTIPS:
3970 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3971
3972 case TB_SETUNICODEFORMAT:
3973 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3974
3975 case CCM_SETVERSION:
3976 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
3977
3978
3979/* case WM_CHAR: */
3980
3981 case WM_CREATE:
3982 return TOOLBAR_Create (hwnd, wParam, lParam);
3983
3984 case WM_ERASEBKGND:
3985 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
3986
3987 case WM_GETFONT:
3988 return TOOLBAR_GetFont (hwnd, wParam, lParam);
3989
3990/* case WM_KEYDOWN: */
3991/* case WM_KILLFOCUS: */
3992
3993 case WM_LBUTTONDBLCLK:
3994 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
3995
3996 case WM_LBUTTONDOWN:
3997 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
3998
3999 case WM_LBUTTONUP:
4000 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4001
4002 case WM_MOUSEMOVE:
4003 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4004
4005 case WM_MOUSELEAVE:
4006 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
4007
4008 case WM_NCACTIVATE:
4009 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4010
4011 case WM_NCCALCSIZE:
4012 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4013
4014 case WM_NCPAINT:
4015 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4016
4017 case WM_NOTIFY:
4018 return TOOLBAR_Notify (hwnd, wParam, lParam);
4019
4020/* case WM_NOTIFYFORMAT: */
4021
4022 case WM_PAINT:
4023 return TOOLBAR_Paint (hwnd, wParam);
4024
4025 case WM_SIZE:
4026 return TOOLBAR_Size (hwnd, wParam, lParam);
4027
4028 case WM_STYLECHANGED:
4029 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4030
4031/* case WM_SYSCOLORCHANGE: */
4032
4033/* case WM_WININICHANGE: */
4034
4035 case WM_CHARTOITEM:
4036 case WM_COMMAND:
4037 case WM_DRAWITEM:
4038 case WM_MEASUREITEM:
4039 case WM_VKEYTOITEM:
4040 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4041
4042 default:
4043// if (uMsg >= WM_USER)
4044// ERR (toolbar, "unknown msg %04x wp=%08x lp=%08lx\n",
4045// uMsg, wParam, lParam);
4046 return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
4047 }
4048 return 0;
4049}
4050
4051
4052VOID
4053TOOLBAR_Register (void)
4054{
4055 WNDCLASSA wndClass;
4056
4057 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4058 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4059 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4060 wndClass.cbClsExtra = 0;
4061 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4062 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4063 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4064 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4065
4066 RegisterClassA (&wndClass);
4067}
4068
4069
4070VOID
4071TOOLBAR_Unregister (void)
4072{
4073 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
4074}
4075
Note: See TracBrowser for help on using the repository browser.