Added handling of TBSTYLE_AUTOSIZE.
[wine.git] / dlls / comctl32 / toolbar.c
blob78502ff4065f77c9aaf78f2c7a92db3061c900f3
1 /*
2 * Toolbar control
4 * Copyright 1998,1999 Eric Kohl
6 * TODO:
7 * - A little bug in TOOLBAR_DrawMasked()
8 * - Button wrapping (under construction).
9 * - Messages.
10 * - Notifications (under construction).
11 * - Fix TB_SETROWS.
12 * - Tooltip support (almost complete).
13 * - Unicode suppport (under construction).
14 * - Fix TOOLBAR_SetButtonInfo32A/W.
15 * - Customize dialog (under construction).
16 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
17 * - I_IMAGECALLBACK support.
19 * Testing:
20 * - Run tests using Waite Group Windows95 API Bible Volume 2.
21 * The second cdrom contains executables addstr.exe, btncount.exe,
22 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
23 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
24 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
25 * setparnt.exe, setrows.exe, toolwnd.exe.
26 * - Microsofts controlspy examples.
29 #include <string.h>
31 #include "winbase.h"
32 #include "windef.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "commctrl.h"
36 #include "cache.h"
37 #include "comctl32.h"
38 #include "toolbar.h"
39 #include "debugtools.h"
41 DEFAULT_DEBUG_CHANNEL(toolbar)
43 #define SEPARATOR_WIDTH 8
44 #define TOP_BORDER 2
45 #define BOTTOM_BORDER 2
47 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
49 static BOOL
50 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
52 if ((index>=0) && (index < infoPtr->nNumBitmaps))
53 return TRUE;
54 else
55 return FALSE;
59 static void
60 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
62 INT x = (lpRect->left + lpRect->right) / 2 - 1;
63 INT yBottom = lpRect->bottom - 3;
64 INT yTop = lpRect->top + 1;
66 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
67 MoveToEx (hdc, x, yBottom, NULL);
68 LineTo (hdc, x, yTop);
69 x++;
70 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
71 MoveToEx (hdc, x, yBottom, NULL);
72 LineTo (hdc, x, yTop);
76 * Draw the text string for this button.
77 * note: himl is not used, except to determine whether this button has
78 * an associated bitmap. If so, the text is drawn below it, otherwise
79 * the text is drawn within the rectangle of the button itself.
81 static void
82 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
83 HDC hdc, INT nState, DWORD dwStyle, HIMAGELIST himl)
85 RECT rcText = btnPtr->rect;
86 HFONT hOldFont;
87 INT nOldBkMode;
88 COLORREF clrOld;
89 LPWSTR lpText = NULL;
91 TRACE ("iString: %x\n", btnPtr->iString);
93 /* get a pointer to the text */
94 if (btnPtr->iString == -1)
95 FIXME("Undocumented Index -1\n");
96 else if (HIWORD(btnPtr->iString) != 0)
97 lpText = (LPWSTR)btnPtr->iString;
98 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
99 lpText = infoPtr->strings[btnPtr->iString];
101 TRACE ("lpText: \"%s\"\n", debugstr_w(lpText));
103 /* draw text */
104 if (lpText) {
106 InflateRect (&rcText, -3, -3);
108 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
109 if ((dwStyle & TBSTYLE_LIST) &&
110 ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
111 (btnPtr->iBitmap != I_IMAGENONE)) {
112 rcText.left += infoPtr->nBitmapWidth;
114 else {
115 rcText.top += infoPtr->nBitmapHeight;
119 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
120 OffsetRect (&rcText, 1, 1);
122 hOldFont = SelectObject (hdc, infoPtr->hFont);
123 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
124 if (!(nState & TBSTATE_ENABLED)) {
125 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
126 OffsetRect (&rcText, 1, 1);
127 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
128 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
129 OffsetRect (&rcText, -1, -1);
130 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
132 else if (nState & TBSTATE_INDETERMINATE) {
133 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
134 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
136 else {
137 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
138 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
141 SetTextColor (hdc, clrOld);
142 SelectObject (hdc, hOldFont);
143 if (nOldBkMode != TRANSPARENT)
144 SetBkMode (hdc, nOldBkMode);
149 static void
150 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
152 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
153 INT cx = lpRect->right - lpRect->left;
154 INT cy = lpRect->bottom - lpRect->top;
155 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
156 SelectObject (hdc, hbr);
160 static void
161 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
162 HDC hdc, INT x, INT y)
164 /* FIXME: this function is a hack since it uses image list
165 internals directly */
167 HIMAGELIST himl = infoPtr->himlDef;
168 HBITMAP hbmMask;
169 HDC hdcImageList;
170 HDC hdcMask;
172 if (!himl)
173 return;
175 /* create new dc's */
176 hdcImageList = CreateCompatibleDC (0);
177 hdcMask = CreateCompatibleDC (0);
179 /* create new bitmap */
180 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
181 SelectObject (hdcMask, hbmMask);
183 /* copy the mask bitmap */
184 SelectObject (hdcImageList, himl->hbmMask);
185 SetBkColor (hdcImageList, RGB(255, 255, 255));
186 SetTextColor (hdcImageList, RGB(0, 0, 0));
187 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
188 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
190 #if 0
191 /* add white mask from image */
192 SelectObject (hdcImageList, himl->hbmImage);
193 SetBkColor (hdcImageList, RGB(0, 0, 0));
194 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
195 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
196 #endif
198 /* draw the new mask */
199 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
200 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
201 hdcMask, 0, 0, 0xB8074A);
203 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
204 BitBlt (hdc, x, y, himl->cx, himl->cy,
205 hdcMask, 0, 0, 0xB8074A);
207 DeleteObject (hbmMask);
208 DeleteDC (hdcMask);
209 DeleteDC (hdcImageList);
213 static void
214 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
216 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
217 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
218 RECT rc;
220 if (btnPtr->fsState & TBSTATE_HIDDEN)
221 return;
223 rc = btnPtr->rect;
225 TRACE("iBitmap: %d\n", btnPtr->iBitmap);
227 /* separator */
228 if (btnPtr->fsStyle & TBSTYLE_SEP) {
229 if ((dwStyle & TBSTYLE_FLAT) && (btnPtr->iBitmap == 0))
230 TOOLBAR_DrawFlatSeparator (&rc, hdc);
231 return;
234 /* disabled */
235 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
236 if (!(dwStyle & TBSTYLE_FLAT))
237 DrawEdge (hdc, &rc, EDGE_RAISED,
238 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
240 if (infoPtr->himlDis &&
241 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
242 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
243 rc.left+1, rc.top+1, ILD_NORMAL);
244 else
245 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
247 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
248 infoPtr->himlDis);
249 return;
252 /* pressed TBSTYLE_BUTTON */
253 if (btnPtr->fsState & TBSTATE_PRESSED) {
254 if (dwStyle & TBSTYLE_FLAT)
255 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
256 else
257 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
258 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
259 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
260 rc.left+2, rc.top+2, ILD_NORMAL);
261 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
262 infoPtr->himlDef);
263 return;
266 /* checked TBSTYLE_CHECK */
267 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
268 (btnPtr->fsState & TBSTATE_CHECKED)) {
269 if (dwStyle & TBSTYLE_FLAT)
270 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
271 BF_RECT | BF_MIDDLE | BF_ADJUST);
272 else
273 DrawEdge (hdc, &rc, EDGE_SUNKEN,
274 BF_RECT | BF_MIDDLE | BF_ADJUST);
276 TOOLBAR_DrawPattern (hdc, &rc);
278 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
279 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
280 rc.left+2, rc.top+2, ILD_NORMAL);
282 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
283 infoPtr->himlDef);
284 return;
287 /* indeterminate */
288 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
289 DrawEdge (hdc, &rc, EDGE_RAISED,
290 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
292 TOOLBAR_DrawPattern (hdc, &rc);
293 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
294 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
295 infoPtr->himlDef);
296 return;
299 /* normal state */
300 if (dwStyle & TBSTYLE_FLAT)
302 if (btnPtr->bHot)
303 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
304 if (btnPtr->bHot && infoPtr->himlHot &&
305 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
306 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
307 rc.left +2, rc.top +2, ILD_NORMAL);
308 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
309 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
310 rc.left +2, rc.top +2, ILD_NORMAL);
312 else
314 DrawEdge (hdc, &rc, EDGE_RAISED,
315 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
317 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
318 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
319 rc.left+1, rc.top+1, ILD_NORMAL);
322 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
323 infoPtr->himlDef);
327 static void
328 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
330 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
331 TBUTTON_INFO *btnPtr;
332 INT i;
333 RECT rcTemp;
335 /* redraw necessary buttons */
336 btnPtr = infoPtr->buttons;
337 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
339 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
340 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
344 static void
345 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
347 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
348 TBUTTON_INFO *btnPtr;
349 HDC hdc;
350 HFONT hOldFont;
352 lpSize->cx = 0;
353 lpSize->cy = 0;
354 hdc = GetDC (0);
355 hOldFont = SelectObject (hdc, infoPtr->hFont);
357 btnPtr = &infoPtr->buttons[index];
359 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
360 (btnPtr->iString > -1) &&
361 (btnPtr->iString < infoPtr->nNumStrings))
363 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
364 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
367 SelectObject (hdc, hOldFont);
368 ReleaseDC (0, hdc);
370 TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
373 static void
374 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
376 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
377 TBUTTON_INFO *btnPtr;
378 INT i;
379 SIZE sz;
382 lpSize->cx = 0;
383 lpSize->cy = 0;
385 btnPtr = infoPtr->buttons;
386 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
387 TOOLBAR_MeasureString(hwnd,i,&sz);
388 if (sz.cx > lpSize->cx)
389 lpSize->cx = sz.cx;
390 if (sz.cy > lpSize->cy)
391 lpSize->cy = sz.cy;
394 TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
397 /***********************************************************************
398 * TOOLBAR_WrapToolbar
400 * This function walks through the buttons and seperators in the
401 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
402 * wrapping should occur based on the width of the toolbar window.
403 * It does *not* calculate button placement itself. That task
404 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
405 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
406 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
409 static void
410 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
412 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
413 TBUTTON_INFO *btnPtr;
414 INT x, cx, i, j;
415 RECT rc;
416 BOOL bWrap, bButtonWrap;
418 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
419 /* no layout is necessary. Applications may use this style */
420 /* to perform their own layout on the toolbar. */
421 if( !(dwStyle & TBSTYLE_WRAPABLE) )
422 return;
424 btnPtr = infoPtr->buttons;
425 x = infoPtr->nIndent;
427 /* this can get the parents width, to know how far we can extend
428 * this toolbar. We cannot use its height, as there may be multiple
429 * toolbars in a rebar control
431 GetClientRect( GetParent(hwnd), &rc );
432 infoPtr->nWidth = rc.right - rc.left;
433 bButtonWrap = FALSE;
435 for (i = 0; i < infoPtr->nNumButtons; i++ )
437 bWrap = FALSE;
438 btnPtr[i].fsState &= ~TBSTATE_WRAP;
440 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
441 continue;
443 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
444 /* it is the actual width of the separator. This is used for */
445 /* custom controls in toolbars. */
446 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
447 cx = (btnPtr[i].iBitmap > 0) ?
448 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
449 else
450 cx = infoPtr->nButtonWidth;
452 /* Two or more adjacent separators form a separator group. */
453 /* The first separator in a group should be wrapped to the */
454 /* next row if the previous wrapping is on a button. */
455 if( bButtonWrap &&
456 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
457 (i + 1 < infoPtr->nNumButtons ) &&
458 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
460 btnPtr[i].fsState |= TBSTATE_WRAP;
461 x = infoPtr->nIndent;
462 i++;
463 bButtonWrap = FALSE;
464 continue;
467 /* The layout makes sure the bitmap is visible, but not the button. */
468 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
469 > infoPtr->nWidth )
471 BOOL bFound = FALSE;
473 /* If the current button is a separator and not hidden, */
474 /* go to the next until it reaches a non separator. */
475 /* Wrap the last separator if it is before a button. */
476 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
477 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
478 i < infoPtr->nNumButtons )
480 i++;
481 bFound = TRUE;
484 if( bFound && i < infoPtr->nNumButtons )
486 i--;
487 btnPtr[i].fsState |= TBSTATE_WRAP;
488 x = infoPtr->nIndent;
489 bButtonWrap = FALSE;
490 continue;
492 else if ( i >= infoPtr->nNumButtons)
493 break;
495 /* If the current button is not a separator, find the last */
496 /* separator and wrap it. */
497 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
499 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
500 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
502 bFound = TRUE;
503 i = j;
504 x = infoPtr->nIndent;
505 btnPtr[j].fsState |= TBSTATE_WRAP;
506 bButtonWrap = FALSE;
507 break;
511 /* If no separator available for wrapping, wrap one of */
512 /* non-hidden previous button. */
513 if (!bFound)
515 for ( j = i - 1;
516 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
518 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
519 continue;
521 bFound = TRUE;
522 i = j;
523 x = infoPtr->nIndent;
524 btnPtr[j].fsState |= TBSTATE_WRAP;
525 bButtonWrap = TRUE;
526 break;
530 /* If all above failed, wrap the current button. */
531 if (!bFound)
533 btnPtr[i].fsState |= TBSTATE_WRAP;
534 bFound = TRUE;
535 x = infoPtr->nIndent;
536 if (btnPtr[i].fsState & TBSTYLE_SEP )
537 bButtonWrap = FALSE;
538 else
539 bButtonWrap = TRUE;
542 else
543 x += cx;
547 /***********************************************************************
548 * TOOLBAR_CalcToolbar
550 * This function calculates button and separator placement. It first
551 * calculates the button sizes, gets the toolbar window width and then
552 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
553 * on. It assigns a new location to each item and sends this location to
554 * the tooltip window if appropriate. Finally, it updates the rcBound
555 * rect and calculates the new required toolbar window height.
558 static void
559 TOOLBAR_CalcToolbar (HWND hwnd)
561 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
562 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
563 TBUTTON_INFO *btnPtr;
564 INT i, nRows, nSepRows;
565 INT x, y, cx, cy;
566 SIZE sizeString;
567 BOOL bWrap;
569 TOOLBAR_CalcStrings (hwnd, &sizeString);
571 if (dwStyle & TBSTYLE_LIST) {
572 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
573 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
575 else {
576 BOOL usesBitmaps = FALSE;
577 INT i;
579 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
580 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
581 usesBitmaps = TRUE;
583 if (sizeString.cy > 0) {
584 if (usesBitmaps)
585 infoPtr->nButtonHeight = sizeString.cy + infoPtr->nBitmapHeight + 6;
586 else
587 infoPtr->nButtonHeight = sizeString.cy + 6;
589 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
590 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
592 if (sizeString.cx > infoPtr->nBitmapWidth)
593 infoPtr->nButtonWidth = sizeString.cx + 6;
594 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
595 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
598 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
599 infoPtr->nButtonWidth = infoPtr->cxMin;
600 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
601 infoPtr->nButtonWidth = infoPtr->cxMax;
603 TOOLBAR_WrapToolbar( hwnd, dwStyle );
605 x = infoPtr->nIndent;
606 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
609 * We wills et the height below, and we set the width on entry
610 * so we do not reset them here..
612 #if 0
613 GetClientRect( hwnd, &rc );
614 /* get initial values for toolbar */
615 infoPtr->nWidth = rc.right - rc.left;
616 infoPtr->nHeight = rc.bottom - rc.top;
617 #endif
619 /* from above, minimum is a button, and possible text */
620 cx = infoPtr->nButtonWidth;
621 /* cannot use just ButtonHeight, we may have no buttons! */
622 if (infoPtr->nNumButtons > 0)
623 infoPtr->nHeight = infoPtr->nButtonHeight;
624 cy = infoPtr->nHeight;
626 nRows = nSepRows = 0;
628 infoPtr->rcBound.top = y;
629 infoPtr->rcBound.left = x;
630 infoPtr->rcBound.bottom = y + cy;
631 infoPtr->rcBound.right = x;
633 btnPtr = infoPtr->buttons;
635 /* do not base height/width on parent, if the parent is a */
636 /* rebar control it could have multiple rows of toolbars */
637 /* GetClientRect( GetParent(hwnd), &rc ); */
638 /* cx = rc.right - rc.left; */
639 /* cy = rc.bottom - rc.top; */
641 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
643 bWrap = FALSE;
644 if (btnPtr->fsState & TBSTATE_HIDDEN)
646 SetRectEmpty (&btnPtr->rect);
647 continue;
650 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
651 /* it is the actual width of the separator. This is used for */
652 /* custom controls in toolbars. */
653 if (btnPtr->fsStyle & TBSTYLE_SEP)
654 cx = (btnPtr->iBitmap > 0) ?
655 btnPtr->iBitmap : SEPARATOR_WIDTH;
656 else {
657 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
659 SIZE sz;
660 TOOLBAR_MeasureString(hwnd,i,&sz);
661 cx = sz.cx + 6;
663 else
664 cx = infoPtr->nButtonWidth;
666 cy = infoPtr->nHeight;
668 if (btnPtr->fsState & TBSTATE_WRAP )
669 bWrap = TRUE;
671 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
673 if (infoPtr->rcBound.left > x)
674 infoPtr->rcBound.left = x;
675 if (infoPtr->rcBound.right < x + cx)
676 infoPtr->rcBound.right = x + cx;
677 if (infoPtr->rcBound.bottom < y + cy)
678 infoPtr->rcBound.bottom = y + cy;
680 /* Set the toolTip only for non-hidden, non-separator button */
681 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
683 TTTOOLINFOA ti;
685 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
686 ti.cbSize = sizeof(TTTOOLINFOA);
687 ti.hwnd = hwnd;
688 ti.uId = btnPtr->idCommand;
689 ti.rect = btnPtr->rect;
690 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
691 0, (LPARAM)&ti);
694 /* btnPtr->nRow is zero based. The space between the rows is */
695 /* also considered as a row. */
696 btnPtr->nRow = nRows + nSepRows;
697 if( bWrap )
699 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
700 y += cy;
701 else
703 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
704 /* it is the actual width of the separator. This is used for */
705 /* custom controls in toolbars. */
706 y += cy + ( (btnPtr->iBitmap > 0 ) ?
707 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
709 /* nSepRows is used to calculate the extra height follwoing */
710 /* the last row. */
711 nSepRows++;
713 x = infoPtr->nIndent;
714 nRows++;
716 else
717 x += cx;
720 /* infoPtr->nRows is the number of rows on the toolbar */
721 infoPtr->nRows = nRows + nSepRows + 1;
723 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
724 /* the last row. */
725 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
726 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
727 nSepRows * (infoPtr->nBitmapHeight + 1) +
728 BOTTOM_BORDER;
729 TRACE("toolbar height %d\n", infoPtr->nHeight);
733 static INT
734 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
736 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
737 TBUTTON_INFO *btnPtr;
738 INT i;
740 btnPtr = infoPtr->buttons;
741 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
742 if (btnPtr->fsState & TBSTATE_HIDDEN)
743 continue;
745 if (btnPtr->fsStyle & TBSTYLE_SEP) {
746 if (PtInRect (&btnPtr->rect, *lpPt)) {
747 TRACE(" ON SEPARATOR %d!\n", i);
748 return -i;
751 else {
752 if (PtInRect (&btnPtr->rect, *lpPt)) {
753 TRACE(" ON BUTTON %d!\n", i);
754 return i;
759 TRACE(" NOWHERE!\n");
760 return -1;
764 static INT
765 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
767 TBUTTON_INFO *btnPtr;
768 INT i;
770 btnPtr = infoPtr->buttons;
771 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
772 if (btnPtr->idCommand == idCommand) {
773 TRACE("command=%d index=%d\n", idCommand, i);
774 return i;
777 TRACE("no index found for command=%d\n", idCommand);
778 return -1;
782 static INT
783 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
785 TBUTTON_INFO *btnPtr;
786 INT nRunIndex;
788 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
789 return -1;
791 /* check index button */
792 btnPtr = &infoPtr->buttons[nIndex];
793 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
794 if (btnPtr->fsState & TBSTATE_CHECKED)
795 return nIndex;
798 /* check previous buttons */
799 nRunIndex = nIndex - 1;
800 while (nRunIndex >= 0) {
801 btnPtr = &infoPtr->buttons[nRunIndex];
802 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
803 if (btnPtr->fsState & TBSTATE_CHECKED)
804 return nRunIndex;
806 else
807 break;
808 nRunIndex--;
811 /* check next buttons */
812 nRunIndex = nIndex + 1;
813 while (nRunIndex < infoPtr->nNumButtons) {
814 btnPtr = &infoPtr->buttons[nRunIndex];
815 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
816 if (btnPtr->fsState & TBSTATE_CHECKED)
817 return nRunIndex;
819 else
820 break;
821 nRunIndex++;
824 return -1;
828 static VOID
829 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
830 WPARAM wParam, LPARAM lParam)
832 MSG msg;
834 msg.hwnd = hwndMsg;
835 msg.message = uMsg;
836 msg.wParam = wParam;
837 msg.lParam = lParam;
838 msg.time = GetMessageTime ();
839 msg.pt.x = LOWORD(GetMessagePos ());
840 msg.pt.y = HIWORD(GetMessagePos ());
842 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
846 /***********************************************************************
847 * TOOLBAR_CustomizeDialogProc
848 * This function implements the toolbar customization dialog.
850 static BOOL WINAPI
851 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
853 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
854 static HDSA hDsa = NULL;
856 switch (uMsg)
858 case WM_INITDIALOG:
859 infoPtr = (TOOLBAR_INFO *)lParam;
860 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
862 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
864 if (infoPtr)
866 TBUTTON_INFO *btnPtr;
867 INT i;
869 /* insert 'virtual' separator button into 'available buttons' list */
870 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
872 /* copy all buttons and append them to the right listbox */
873 btnPtr = infoPtr->buttons;
874 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
876 DSA_InsertItem (hDsa, i, btnPtr);
878 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
879 if (btnPtr->fsState & TBSTATE_HIDDEN)
881 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
883 else
885 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
889 /* append 'virtual' separator button to the 'toolbar buttons' list */
890 /* TODO */
892 return TRUE;
894 case WM_CLOSE:
895 EndDialog(hwnd, FALSE);
896 return TRUE;
898 case WM_COMMAND:
899 switch (LOWORD(wParam))
901 case IDCANCEL:
902 EndDialog(hwnd, FALSE);
903 break;
905 return TRUE;
907 case WM_DESTROY:
908 if (hDsa)
909 DSA_Destroy (hDsa);
910 return TRUE;
912 case WM_DRAWITEM:
913 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
915 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
916 TBUTTON_INFO btnPtr;
917 RECT rcButton;
918 RECT rcText;
919 HPEN hOldPen;
920 HBRUSH hOldBrush;
921 COLORREF oldText = 0;
922 COLORREF oldBk = 0;
924 FIXME("action: %x itemState: %x\n",
925 lpdis->itemAction, lpdis->itemState);
927 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
929 if (lpdis->itemState & ODS_FOCUS)
931 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
932 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
935 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
936 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
938 /* fill background rectangle */
939 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
940 lpdis->rcItem.right, lpdis->rcItem.bottom);
942 /* calculate button and text rectangles */
943 CopyRect (&rcButton, &lpdis->rcItem);
944 InflateRect (&rcButton, -1, -1);
945 CopyRect (&rcText, &rcButton);
946 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
947 rcText.left = rcButton.right + 2;
949 /* draw focus rectangle */
950 if (lpdis->itemState & ODS_FOCUS)
951 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
953 /* draw button */
954 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
956 /* draw image and text */
957 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
959 /* virtual separator in the 'available' list */
960 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
961 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
963 else
965 /* real button */
967 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
968 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
970 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
971 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
975 if (lpdis->itemState & ODS_FOCUS)
977 SetBkColor (lpdis->hDC, oldBk);
978 SetTextColor (lpdis->hDC, oldText);
981 SelectObject (lpdis->hDC, hOldBrush);
982 SelectObject (lpdis->hDC, hOldPen);
984 return TRUE;
986 return FALSE;
988 case WM_MEASUREITEM:
989 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
991 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
993 if (infoPtr)
994 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
995 else
996 lpmis->itemHeight = 15 + 8; /* default height */
998 return TRUE;
1000 return FALSE;
1002 default:
1003 return FALSE;
1008 /***********************************************************************
1009 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1012 static LRESULT
1013 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1015 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1016 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1017 INT nIndex = 0, nButtons, nCount;
1018 HBITMAP hbmLoad;
1020 if (!lpAddBmp)
1021 return -1;
1023 if (lpAddBmp->hInst == HINST_COMMCTRL)
1025 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1026 nButtons = 15;
1027 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1028 nButtons = 13;
1029 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1030 nButtons = 5;
1031 else
1032 return -1;
1034 TRACE ("adding %d internal bitmaps!\n", nButtons);
1036 /* Windows resize all the buttons to the size of a newly added standard image */
1037 if (lpAddBmp->nID & 1)
1039 /* large icons */
1040 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1041 MAKELPARAM((WORD)26, (WORD)26));
1042 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1043 MAKELPARAM((WORD)33, (WORD)33));
1045 else
1047 /* small icons */
1048 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1049 MAKELPARAM((WORD)16, (WORD)16));
1050 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1051 MAKELPARAM((WORD)22, (WORD)22));
1054 TOOLBAR_CalcToolbar (hwnd);
1056 else
1058 nButtons = (INT)wParam;
1059 if (nButtons <= 0)
1060 return -1;
1062 TRACE ("adding %d bitmaps!\n", nButtons);
1065 if (!(infoPtr->himlDef)) {
1066 /* create new default image list */
1067 TRACE ("creating default image list!\n");
1069 infoPtr->himlDef =
1070 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1071 ILC_COLOR | ILC_MASK, nButtons, 2);
1072 infoPtr->himlInt = infoPtr->himlDef;
1075 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1077 /* Add bitmaps to the default image list */
1078 if (lpAddBmp->hInst == (HINSTANCE)0)
1080 nIndex =
1081 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1082 CLR_DEFAULT);
1084 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1086 /* Add system bitmaps */
1087 switch (lpAddBmp->nID)
1089 case IDB_STD_SMALL_COLOR:
1090 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1091 MAKEINTRESOURCEA(IDB_STD_SMALL));
1092 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1093 hbmLoad, CLR_DEFAULT);
1094 DeleteObject (hbmLoad);
1095 break;
1097 case IDB_STD_LARGE_COLOR:
1098 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1099 MAKEINTRESOURCEA(IDB_STD_LARGE));
1100 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1101 hbmLoad, CLR_DEFAULT);
1102 DeleteObject (hbmLoad);
1103 break;
1105 case IDB_VIEW_SMALL_COLOR:
1106 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1107 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1108 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1109 hbmLoad, CLR_DEFAULT);
1110 DeleteObject (hbmLoad);
1111 break;
1113 case IDB_VIEW_LARGE_COLOR:
1114 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1115 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1116 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1117 hbmLoad, CLR_DEFAULT);
1118 DeleteObject (hbmLoad);
1119 break;
1121 case IDB_HIST_SMALL_COLOR:
1122 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1123 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1124 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1125 hbmLoad, CLR_DEFAULT);
1126 DeleteObject (hbmLoad);
1127 break;
1129 case IDB_HIST_LARGE_COLOR:
1130 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1131 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1132 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1133 hbmLoad, CLR_DEFAULT);
1134 DeleteObject (hbmLoad);
1135 break;
1137 default:
1138 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1139 ERR ("invalid imagelist!\n");
1140 break;
1143 else
1145 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1146 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1147 DeleteObject (hbmLoad);
1150 if (nIndex != -1)
1152 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1154 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1156 WARN("Desired images do not match recieved images : Previous image number %s Previous images in list %i added %i expecting total %i, Images in list %i\n",
1157 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1158 infoPtr->nNumBitmaps+nButtons,imagecount);
1160 infoPtr->nNumBitmaps = imagecount;
1162 else
1163 infoPtr->nNumBitmaps += nButtons;
1166 return nIndex;
1170 static LRESULT
1171 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1173 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1174 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1175 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1177 TRACE("adding %d buttons!\n", wParam);
1179 nAddButtons = (UINT)wParam;
1180 nOldButtons = infoPtr->nNumButtons;
1181 nNewButtons = nOldButtons + nAddButtons;
1183 if (infoPtr->nNumButtons == 0) {
1184 infoPtr->buttons =
1185 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1187 else {
1188 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1189 infoPtr->buttons =
1190 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1191 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1192 nOldButtons * sizeof(TBUTTON_INFO));
1193 COMCTL32_Free (oldButtons);
1196 infoPtr->nNumButtons = nNewButtons;
1198 /* insert new button data */
1199 for (nCount = 0; nCount < nAddButtons; nCount++) {
1200 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1201 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1202 btnPtr->idCommand = lpTbb[nCount].idCommand;
1203 btnPtr->fsState = lpTbb[nCount].fsState;
1204 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1205 btnPtr->dwData = lpTbb[nCount].dwData;
1206 btnPtr->iString = lpTbb[nCount].iString;
1207 btnPtr->bHot = FALSE;
1209 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1210 TTTOOLINFOA ti;
1212 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1213 ti.cbSize = sizeof (TTTOOLINFOA);
1214 ti.hwnd = hwnd;
1215 ti.uId = btnPtr->idCommand;
1216 ti.hinst = 0;
1217 ti.lpszText = LPSTR_TEXTCALLBACKA;
1219 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1220 0, (LPARAM)&ti);
1224 TOOLBAR_CalcToolbar (hwnd);
1226 InvalidateRect(hwnd, NULL, FALSE);
1228 return TRUE;
1232 static LRESULT
1233 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1235 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1236 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1237 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1239 TRACE("adding %d buttons!\n", wParam);
1241 nAddButtons = (UINT)wParam;
1242 nOldButtons = infoPtr->nNumButtons;
1243 nNewButtons = nOldButtons + nAddButtons;
1245 if (infoPtr->nNumButtons == 0) {
1246 infoPtr->buttons =
1247 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1249 else {
1250 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1251 infoPtr->buttons =
1252 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1253 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1254 nOldButtons * sizeof(TBUTTON_INFO));
1255 COMCTL32_Free (oldButtons);
1258 infoPtr->nNumButtons = nNewButtons;
1260 /* insert new button data */
1261 for (nCount = 0; nCount < nAddButtons; nCount++) {
1262 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1263 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1264 btnPtr->idCommand = lpTbb[nCount].idCommand;
1265 btnPtr->fsState = lpTbb[nCount].fsState;
1266 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1267 btnPtr->dwData = lpTbb[nCount].dwData;
1268 btnPtr->iString = lpTbb[nCount].iString;
1269 btnPtr->bHot = FALSE;
1271 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1272 TTTOOLINFOW ti;
1274 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1275 ti.cbSize = sizeof (TTTOOLINFOW);
1276 ti.hwnd = hwnd;
1277 ti.uId = btnPtr->idCommand;
1278 ti.hinst = 0;
1279 ti.lpszText = LPSTR_TEXTCALLBACKW;
1281 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1282 0, (LPARAM)&ti);
1286 TOOLBAR_CalcToolbar (hwnd);
1288 InvalidateRect(hwnd, NULL, FALSE);
1290 return TRUE;
1294 static LRESULT
1295 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1297 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1298 INT nIndex;
1300 if ((wParam) && (HIWORD(lParam) == 0)) {
1301 char szString[256];
1302 INT len;
1303 TRACE("adding string from resource!\n");
1305 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1306 szString, 256);
1308 TRACE("len=%d \"%s\"\n", len, szString);
1309 nIndex = infoPtr->nNumStrings;
1310 if (infoPtr->nNumStrings == 0) {
1311 infoPtr->strings =
1312 COMCTL32_Alloc (sizeof(LPWSTR));
1314 else {
1315 LPWSTR *oldStrings = infoPtr->strings;
1316 infoPtr->strings =
1317 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1318 memcpy (&infoPtr->strings[0], &oldStrings[0],
1319 sizeof(LPWSTR) * infoPtr->nNumStrings);
1320 COMCTL32_Free (oldStrings);
1323 infoPtr->strings[infoPtr->nNumStrings] =
1324 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1325 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1326 infoPtr->nNumStrings++;
1328 else {
1329 LPSTR p = (LPSTR)lParam;
1330 INT len;
1332 if (p == NULL)
1333 return -1;
1334 TRACE("adding string(s) from array!\n");
1336 nIndex = infoPtr->nNumStrings;
1337 while (*p) {
1338 len = lstrlenA (p);
1339 TRACE("len=%d \"%s\"\n", len, p);
1341 if (infoPtr->nNumStrings == 0) {
1342 infoPtr->strings =
1343 COMCTL32_Alloc (sizeof(LPWSTR));
1345 else {
1346 LPWSTR *oldStrings = infoPtr->strings;
1347 infoPtr->strings =
1348 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1349 memcpy (&infoPtr->strings[0], &oldStrings[0],
1350 sizeof(LPWSTR) * infoPtr->nNumStrings);
1351 COMCTL32_Free (oldStrings);
1354 infoPtr->strings[infoPtr->nNumStrings] =
1355 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1356 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1357 infoPtr->nNumStrings++;
1359 p += (len+1);
1363 return nIndex;
1367 static LRESULT
1368 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1370 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1371 INT nIndex;
1373 if ((wParam) && (HIWORD(lParam) == 0)) {
1374 WCHAR szString[256];
1375 INT len;
1376 TRACE("adding string from resource!\n");
1378 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1379 szString, 256);
1381 TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1382 TRACE("First char: 0x%x\n", *szString);
1383 if (szString[0] == L'|')
1385 PWSTR p = szString + 1;
1387 nIndex = infoPtr->nNumStrings;
1388 while (*p != L'|') {
1390 if (infoPtr->nNumStrings == 0) {
1391 infoPtr->strings =
1392 COMCTL32_Alloc (sizeof(LPWSTR));
1394 else {
1395 LPWSTR *oldStrings = infoPtr->strings;
1396 infoPtr->strings =
1397 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1398 memcpy (&infoPtr->strings[0], &oldStrings[0],
1399 sizeof(LPWSTR) * infoPtr->nNumStrings);
1400 COMCTL32_Free (oldStrings);
1403 len = COMCTL32_StrChrW (p, L'|') - p;
1404 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1405 infoPtr->strings[infoPtr->nNumStrings] =
1406 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1407 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1408 infoPtr->nNumStrings++;
1410 p += (len+1);
1413 else
1415 nIndex = infoPtr->nNumStrings;
1416 if (infoPtr->nNumStrings == 0) {
1417 infoPtr->strings =
1418 COMCTL32_Alloc (sizeof(LPWSTR));
1420 else {
1421 LPWSTR *oldStrings = infoPtr->strings;
1422 infoPtr->strings =
1423 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1424 memcpy (&infoPtr->strings[0], &oldStrings[0],
1425 sizeof(LPWSTR) * infoPtr->nNumStrings);
1426 COMCTL32_Free (oldStrings);
1429 infoPtr->strings[infoPtr->nNumStrings] =
1430 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1431 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1432 infoPtr->nNumStrings++;
1435 else {
1436 LPWSTR p = (LPWSTR)lParam;
1437 INT len;
1439 if (p == NULL)
1440 return -1;
1441 TRACE("adding string(s) from array!\n");
1442 nIndex = infoPtr->nNumStrings;
1443 while (*p) {
1444 len = lstrlenW (p);
1446 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1447 if (infoPtr->nNumStrings == 0) {
1448 infoPtr->strings =
1449 COMCTL32_Alloc (sizeof(LPWSTR));
1451 else {
1452 LPWSTR *oldStrings = infoPtr->strings;
1453 infoPtr->strings =
1454 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1455 memcpy (&infoPtr->strings[0], &oldStrings[0],
1456 sizeof(LPWSTR) * infoPtr->nNumStrings);
1457 COMCTL32_Free (oldStrings);
1460 infoPtr->strings[infoPtr->nNumStrings] =
1461 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1462 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1463 infoPtr->nNumStrings++;
1465 p += (len+1);
1469 return nIndex;
1473 static LRESULT
1474 TOOLBAR_AutoSize (HWND hwnd)
1476 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1477 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1478 RECT parent_rect;
1479 RECT window_rect;
1480 HWND parent;
1481 INT x, y;
1482 INT cx, cy;
1483 UINT uPosFlags = 0;
1485 TRACE("resize forced!\n");
1487 parent = GetParent (hwnd);
1488 GetClientRect(parent, &parent_rect);
1490 x = parent_rect.left;
1491 y = parent_rect.top;
1493 if (dwStyle & CCS_NORESIZE) {
1494 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1495 cx = 0;
1496 cy = 0;
1498 else {
1499 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1500 TOOLBAR_CalcToolbar (hwnd);
1501 InvalidateRect( hwnd, NULL, TRUE );
1502 cy = infoPtr->nHeight;
1503 cx = infoPtr->nWidth;
1505 if (dwStyle & CCS_NOMOVEY) {
1506 GetWindowRect(hwnd, &window_rect);
1507 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1508 y = window_rect.top;
1512 if (dwStyle & CCS_NOPARENTALIGN)
1513 uPosFlags |= SWP_NOMOVE;
1515 if (!(dwStyle & CCS_NODIVIDER))
1516 cy += GetSystemMetrics(SM_CYEDGE);
1518 if (dwStyle & WS_BORDER)
1520 x = y = 1;
1521 cy += GetSystemMetrics(SM_CYEDGE);
1522 cx += GetSystemMetrics(SM_CYEDGE);
1525 infoPtr->bAutoSize = TRUE;
1526 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1527 cx, cy, uPosFlags);
1528 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1529 * the setwindowpos calls */
1530 infoPtr->bAutoSize = FALSE;
1532 return 0;
1536 static LRESULT
1537 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1539 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1541 return infoPtr->nNumButtons;
1545 static LRESULT
1546 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1548 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1550 if (infoPtr == NULL) {
1551 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1552 ERR("infoPtr == NULL!\n");
1553 return 0;
1556 infoPtr->dwStructSize = (DWORD)wParam;
1558 return 0;
1562 static LRESULT
1563 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1565 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1566 TBUTTON_INFO *btnPtr;
1567 INT nIndex;
1569 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1570 if (nIndex == -1)
1571 return FALSE;
1573 btnPtr = &infoPtr->buttons[nIndex];
1574 btnPtr->iBitmap = LOWORD(lParam);
1576 RedrawWindow(hwnd,&btnPtr->rect,0,RDW_ERASE|RDW_INVALIDATE);
1578 return TRUE;
1582 static LRESULT
1583 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1585 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1586 TBUTTON_INFO *btnPtr;
1587 INT nIndex;
1588 INT nOldIndex = -1;
1589 BOOL bChecked = FALSE;
1591 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1592 if (nIndex == -1)
1593 return FALSE;
1595 btnPtr = &infoPtr->buttons[nIndex];
1597 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1598 return FALSE;
1600 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1602 if (LOWORD(lParam) == FALSE)
1603 btnPtr->fsState &= ~TBSTATE_CHECKED;
1604 else {
1605 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1606 nOldIndex =
1607 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1608 if (nOldIndex == nIndex)
1609 return 0;
1610 if (nOldIndex != -1)
1611 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1613 btnPtr->fsState |= TBSTATE_CHECKED;
1616 if( bChecked != LOWORD(lParam) )
1618 if (nOldIndex != -1)
1619 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,(HRGN)NULL,
1620 RDW_ERASE|RDW_INVALIDATE);
1621 RedrawWindow(hwnd,&btnPtr->rect,0,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1624 /* FIXME: Send a WM_NOTIFY?? */
1626 return TRUE;
1630 static LRESULT
1631 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1633 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1635 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1639 static LRESULT
1640 TOOLBAR_Customize (HWND hwnd)
1642 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1643 LRESULT ret;
1644 LPCVOID template;
1645 HRSRC hRes;
1646 NMHDR nmhdr;
1648 /* send TBN_BEGINADJUST notification */
1649 nmhdr.hwndFrom = hwnd;
1650 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1651 nmhdr.code = TBN_BEGINADJUST;
1653 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1654 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1656 if (!(hRes = FindResourceA (COMCTL32_hModule,
1657 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1658 RT_DIALOGA)))
1659 return FALSE;
1661 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1662 return FALSE;
1664 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1665 (LPDLGTEMPLATEA)template,
1666 hwnd,
1667 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1668 (LPARAM)infoPtr);
1670 /* send TBN_ENDADJUST notification */
1671 nmhdr.code = TBN_ENDADJUST;
1673 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1674 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1676 return ret;
1680 static LRESULT
1681 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1683 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1684 INT nIndex = (INT)wParam;
1686 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1687 return FALSE;
1689 if ((infoPtr->hwndToolTip) &&
1690 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1691 TTTOOLINFOA ti;
1693 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1694 ti.cbSize = sizeof (TTTOOLINFOA);
1695 ti.hwnd = hwnd;
1696 ti.uId = infoPtr->buttons[nIndex].idCommand;
1698 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1701 if (infoPtr->nNumButtons == 1) {
1702 TRACE(" simple delete!\n");
1703 COMCTL32_Free (infoPtr->buttons);
1704 infoPtr->buttons = NULL;
1705 infoPtr->nNumButtons = 0;
1707 else {
1708 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1709 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1711 infoPtr->nNumButtons--;
1712 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1713 if (nIndex > 0) {
1714 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1715 nIndex * sizeof(TBUTTON_INFO));
1718 if (nIndex < infoPtr->nNumButtons) {
1719 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1720 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1723 COMCTL32_Free (oldButtons);
1726 TOOLBAR_CalcToolbar (hwnd);
1728 InvalidateRect (hwnd, NULL, TRUE);
1730 return TRUE;
1734 static LRESULT
1735 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1737 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1738 TBUTTON_INFO *btnPtr;
1739 INT nIndex;
1740 DWORD bState;
1742 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1743 if (nIndex == -1)
1744 return FALSE;
1746 btnPtr = &infoPtr->buttons[nIndex];
1748 bState = btnPtr->fsState & TBSTATE_ENABLED;
1750 /* update the toolbar button state */
1751 if(LOWORD(lParam) == FALSE) {
1752 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1753 } else {
1754 btnPtr->fsState |= TBSTATE_ENABLED;
1757 /* redraw the button only if the state of the button changed */
1758 if(bState != (btnPtr->fsState & TBSTATE_ENABLED)) {
1759 RedrawWindow(hwnd,&btnPtr->rect,0,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1762 return TRUE;
1766 static inline LRESULT
1767 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1769 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1771 return infoPtr->bAnchor;
1775 static LRESULT
1776 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1778 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1779 INT nIndex;
1781 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1782 if (nIndex == -1)
1783 return -1;
1785 return infoPtr->buttons[nIndex].iBitmap;
1789 static inline LRESULT
1790 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1792 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1796 static LRESULT
1797 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1799 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1800 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1801 INT nIndex = (INT)wParam;
1802 TBUTTON_INFO *btnPtr;
1804 if (infoPtr == NULL)
1805 return FALSE;
1807 if (lpTbb == NULL)
1808 return FALSE;
1810 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1811 return FALSE;
1813 btnPtr = &infoPtr->buttons[nIndex];
1814 lpTbb->iBitmap = btnPtr->iBitmap;
1815 lpTbb->idCommand = btnPtr->idCommand;
1816 lpTbb->fsState = btnPtr->fsState;
1817 lpTbb->fsStyle = btnPtr->fsStyle;
1818 lpTbb->dwData = btnPtr->dwData;
1819 lpTbb->iString = btnPtr->iString;
1821 return TRUE;
1825 static LRESULT
1826 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1828 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1829 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1830 TBUTTON_INFO *btnPtr;
1831 INT nIndex;
1833 if (infoPtr == NULL)
1834 return -1;
1835 if (lpTbInfo == NULL)
1836 return -1;
1837 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1838 return -1;
1840 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1841 if (nIndex == -1)
1842 return -1;
1844 btnPtr = &infoPtr->buttons[nIndex];
1846 if (lpTbInfo->dwMask & TBIF_COMMAND)
1847 lpTbInfo->idCommand = btnPtr->idCommand;
1848 if (lpTbInfo->dwMask & TBIF_IMAGE)
1849 lpTbInfo->iImage = btnPtr->iBitmap;
1850 if (lpTbInfo->dwMask & TBIF_LPARAM)
1851 lpTbInfo->lParam = btnPtr->dwData;
1852 if (lpTbInfo->dwMask & TBIF_SIZE)
1853 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1854 if (lpTbInfo->dwMask & TBIF_STATE)
1855 lpTbInfo->fsState = btnPtr->fsState;
1856 if (lpTbInfo->dwMask & TBIF_STYLE)
1857 lpTbInfo->fsStyle = btnPtr->fsStyle;
1858 if (lpTbInfo->dwMask & TBIF_TEXT) {
1859 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
1861 lstrcpynWtoA (lpTbInfo->pszText,
1862 (LPWSTR)infoPtr->strings[btnPtr->iString],
1863 lpTbInfo->cchText);
1865 else lpTbInfo->pszText[0]=0;
1867 return nIndex;
1871 static LRESULT
1872 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1874 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1875 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
1876 TBUTTON_INFO *btnPtr;
1877 INT nIndex;
1879 if (infoPtr == NULL)
1880 return -1;
1881 if (lpTbInfo == NULL)
1882 return -1;
1883 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
1884 return -1;
1886 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1887 if (nIndex == -1)
1888 return -1;
1890 btnPtr = &infoPtr->buttons[nIndex];
1892 if (lpTbInfo->dwMask & TBIF_COMMAND)
1893 lpTbInfo->idCommand = btnPtr->idCommand;
1894 if (lpTbInfo->dwMask & TBIF_IMAGE)
1895 lpTbInfo->iImage = btnPtr->iBitmap;
1896 if (lpTbInfo->dwMask & TBIF_LPARAM)
1897 lpTbInfo->lParam = btnPtr->dwData;
1898 if (lpTbInfo->dwMask & TBIF_SIZE)
1899 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1900 if (lpTbInfo->dwMask & TBIF_STATE)
1901 lpTbInfo->fsState = btnPtr->fsState;
1902 if (lpTbInfo->dwMask & TBIF_STYLE)
1903 lpTbInfo->fsStyle = btnPtr->fsStyle;
1904 if (lpTbInfo->dwMask & TBIF_TEXT) {
1905 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1906 lstrcpynW (lpTbInfo->pszText,
1907 (LPWSTR)infoPtr->strings[btnPtr->iString],
1908 lpTbInfo->cchText);
1911 return nIndex;
1915 static LRESULT
1916 TOOLBAR_GetButtonSize (HWND hwnd)
1918 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1920 return MAKELONG((WORD)infoPtr->nButtonWidth,
1921 (WORD)infoPtr->nButtonHeight);
1925 static LRESULT
1926 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1928 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1929 INT nIndex, nStringIndex;
1931 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1932 if (nIndex == -1)
1933 return -1;
1935 nStringIndex = infoPtr->buttons[nIndex].iString;
1937 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1939 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1940 return -1;
1942 if (lParam == 0)
1943 return -1;
1945 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1947 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1951 static LRESULT
1952 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1954 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1955 INT nIndex, nStringIndex;
1957 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1958 if (nIndex == -1)
1959 return -1;
1961 nStringIndex = infoPtr->buttons[nIndex].iString;
1963 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1965 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1966 return -1;
1968 if (lParam == 0)
1969 return -1;
1971 lstrcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1973 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1977 /* << TOOLBAR_GetColorScheme >> */
1980 static LRESULT
1981 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1983 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1985 return (LRESULT)infoPtr->himlDis;
1989 inline static LRESULT
1990 TOOLBAR_GetExtendedStyle (HWND hwnd)
1992 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1994 return infoPtr->dwExStyle;
1998 static LRESULT
1999 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2001 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2003 return (LRESULT)infoPtr->himlHot;
2007 static LRESULT
2008 TOOLBAR_GetHotItem (HWND hwnd)
2010 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2012 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2013 return -1;
2015 if (infoPtr->nHotItem < 0)
2016 return -1;
2018 return (LRESULT)infoPtr->nHotItem;
2022 static LRESULT
2023 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2025 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2027 return (LRESULT)infoPtr->himlDef;
2031 /* << TOOLBAR_GetInsertMark >> */
2032 /* << TOOLBAR_GetInsertMarkColor >> */
2035 static LRESULT
2036 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2038 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2039 TBUTTON_INFO *btnPtr;
2040 LPRECT lpRect;
2041 INT nIndex;
2043 if (infoPtr == NULL)
2044 return FALSE;
2045 nIndex = (INT)wParam;
2046 btnPtr = &infoPtr->buttons[nIndex];
2047 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2048 return FALSE;
2049 lpRect = (LPRECT)lParam;
2050 if (lpRect == NULL)
2051 return FALSE;
2052 if (btnPtr->fsState & TBSTATE_HIDDEN)
2053 return FALSE;
2055 TOOLBAR_CalcToolbar( hwnd );
2057 lpRect->left = btnPtr->rect.left;
2058 lpRect->right = btnPtr->rect.right;
2059 lpRect->bottom = btnPtr->rect.bottom;
2060 lpRect->top = btnPtr->rect.top;
2062 return TRUE;
2066 static LRESULT
2067 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2069 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2070 LPSIZE lpSize = (LPSIZE)lParam;
2072 if (lpSize == NULL)
2073 return FALSE;
2075 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2076 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2078 TRACE("maximum size %d x %d\n",
2079 infoPtr->rcBound.right - infoPtr->rcBound.left,
2080 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2082 return TRUE;
2086 /* << TOOLBAR_GetObject >> */
2087 /* << TOOLBAR_GetPadding >> */
2090 static LRESULT
2091 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2093 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2094 TBUTTON_INFO *btnPtr;
2095 LPRECT lpRect;
2096 INT nIndex;
2098 if (infoPtr == NULL)
2099 return FALSE;
2100 nIndex = (INT)wParam;
2101 btnPtr = &infoPtr->buttons[nIndex];
2102 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2103 return FALSE;
2104 lpRect = (LPRECT)lParam;
2105 if (lpRect == NULL)
2106 return FALSE;
2108 lpRect->left = btnPtr->rect.left;
2109 lpRect->right = btnPtr->rect.right;
2110 lpRect->bottom = btnPtr->rect.bottom;
2111 lpRect->top = btnPtr->rect.top;
2113 return TRUE;
2117 static LRESULT
2118 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2120 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2122 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2123 return infoPtr->nRows;
2124 else
2125 return 1;
2129 static LRESULT
2130 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2132 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2133 INT nIndex;
2135 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2136 if (nIndex == -1)
2137 return -1;
2139 return infoPtr->buttons[nIndex].fsState;
2143 static LRESULT
2144 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2146 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2147 INT nIndex;
2149 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2150 if (nIndex == -1)
2151 return -1;
2153 return infoPtr->buttons[nIndex].fsStyle;
2157 static LRESULT
2158 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2160 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2162 if (infoPtr == NULL)
2163 return 0;
2165 return infoPtr->nMaxTextRows;
2169 static LRESULT
2170 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2172 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2174 if (infoPtr == NULL)
2175 return 0;
2176 return infoPtr->hwndToolTip;
2180 static LRESULT
2181 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2183 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2185 TRACE("%s hwnd=0x%x stub!\n",
2186 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2188 return infoPtr->bUnicode;
2192 inline static LRESULT
2193 TOOLBAR_GetVersion (HWND hwnd)
2195 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2196 return infoPtr->iVersion;
2200 static LRESULT
2201 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2203 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2204 TBUTTON_INFO *btnPtr;
2205 INT nIndex;
2207 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2208 if (nIndex == -1)
2209 return FALSE;
2211 btnPtr = &infoPtr->buttons[nIndex];
2212 if (LOWORD(lParam) == FALSE)
2213 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2214 else
2215 btnPtr->fsState |= TBSTATE_HIDDEN;
2217 TOOLBAR_CalcToolbar (hwnd);
2219 InvalidateRect (hwnd, NULL, TRUE);
2221 return TRUE;
2225 inline static LRESULT
2226 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2228 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2232 static LRESULT
2233 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2235 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2236 TBUTTON_INFO *btnPtr;
2237 INT nIndex;
2239 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2240 if (nIndex == -1)
2241 return FALSE;
2243 btnPtr = &infoPtr->buttons[nIndex];
2244 if (LOWORD(lParam) == FALSE)
2245 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2246 else
2247 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2249 RedrawWindow(hwnd,&btnPtr->rect,0,
2250 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2252 return TRUE;
2256 static LRESULT
2257 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2259 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2260 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2261 INT nIndex = (INT)wParam;
2262 TBUTTON_INFO *oldButtons;
2264 if (lpTbb == NULL)
2265 return FALSE;
2267 if (nIndex == -1) {
2268 /* EPP: this seems to be an undocumented call (from my IE4)
2269 * I assume in that case that:
2270 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2271 * - index of insertion is at the end of existing buttons
2272 * I only see this happen with nIndex == -1, but it could have a special
2273 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2275 int len = lstrlenA((char*)lpTbb->iString) + 2;
2276 LPSTR ptr = COMCTL32_Alloc(len);
2278 nIndex = infoPtr->nNumButtons;
2279 strcpy(ptr, (char*)lpTbb->iString);
2280 ptr[len - 1] = 0; /* ended by two '\0' */
2281 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2282 COMCTL32_Free(ptr);
2284 } else if (nIndex < 0)
2285 return FALSE;
2287 TRACE("inserting button index=%d\n", nIndex);
2288 if (nIndex > infoPtr->nNumButtons) {
2289 nIndex = infoPtr->nNumButtons;
2290 TRACE("adjust index=%d\n", nIndex);
2293 oldButtons = infoPtr->buttons;
2294 infoPtr->nNumButtons++;
2295 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2296 /* pre insert copy */
2297 if (nIndex > 0) {
2298 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2299 nIndex * sizeof(TBUTTON_INFO));
2302 /* insert new button */
2303 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2304 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2305 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2306 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2307 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2308 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2310 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2311 TTTOOLINFOA ti;
2313 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2314 ti.cbSize = sizeof (TTTOOLINFOA);
2315 ti.hwnd = hwnd;
2316 ti.uId = lpTbb->idCommand;
2317 ti.hinst = 0;
2318 ti.lpszText = LPSTR_TEXTCALLBACKA;
2320 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2321 0, (LPARAM)&ti);
2324 /* post insert copy */
2325 if (nIndex < infoPtr->nNumButtons - 1) {
2326 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2327 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2330 COMCTL32_Free (oldButtons);
2332 TOOLBAR_CalcToolbar (hwnd);
2334 InvalidateRect (hwnd, NULL, FALSE);
2336 return TRUE;
2340 static LRESULT
2341 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2343 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2344 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2345 INT nIndex = (INT)wParam;
2346 TBUTTON_INFO *oldButtons;
2348 if (lpTbb == NULL)
2349 return FALSE;
2350 if (nIndex < 0)
2351 return FALSE;
2353 TRACE("inserting button index=%d\n", nIndex);
2354 if (nIndex > infoPtr->nNumButtons) {
2355 nIndex = infoPtr->nNumButtons;
2356 TRACE("adjust index=%d\n", nIndex);
2359 oldButtons = infoPtr->buttons;
2360 infoPtr->nNumButtons++;
2361 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2362 /* pre insert copy */
2363 if (nIndex > 0) {
2364 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2365 nIndex * sizeof(TBUTTON_INFO));
2368 /* insert new button */
2369 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2370 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2371 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2372 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2373 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2374 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2376 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2377 TTTOOLINFOW ti;
2379 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2380 ti.cbSize = sizeof (TTTOOLINFOW);
2381 ti.hwnd = hwnd;
2382 ti.uId = lpTbb->idCommand;
2383 ti.hinst = 0;
2384 ti.lpszText = LPSTR_TEXTCALLBACKW;
2386 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2387 0, (LPARAM)&ti);
2390 /* post insert copy */
2391 if (nIndex < infoPtr->nNumButtons - 1) {
2392 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2393 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2396 COMCTL32_Free (oldButtons);
2398 TOOLBAR_CalcToolbar (hwnd);
2400 InvalidateRect (hwnd, NULL, FALSE);
2402 return TRUE;
2406 /* << TOOLBAR_InsertMarkHitTest >> */
2409 static LRESULT
2410 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2412 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2413 INT nIndex;
2415 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2416 if (nIndex == -1)
2417 return FALSE;
2419 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2423 static LRESULT
2424 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2426 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2427 INT nIndex;
2429 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2430 if (nIndex == -1)
2431 return FALSE;
2433 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2437 static LRESULT
2438 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2440 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2441 INT nIndex;
2443 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2444 if (nIndex == -1)
2445 return FALSE;
2447 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2451 static LRESULT
2452 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2454 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2455 INT nIndex;
2457 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2458 if (nIndex == -1)
2459 return FALSE;
2461 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2465 static LRESULT
2466 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2468 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2469 INT nIndex;
2471 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2472 if (nIndex == -1)
2473 return FALSE;
2475 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2479 static LRESULT
2480 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2482 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2483 INT nIndex;
2485 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2486 if (nIndex == -1)
2487 return FALSE;
2489 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2493 /* << TOOLBAR_LoadImages >> */
2494 /* << TOOLBAR_MapAccelerator >> */
2495 /* << TOOLBAR_MarkButton >> */
2496 /* << TOOLBAR_MoveButton >> */
2499 static LRESULT
2500 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2502 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2503 TBUTTON_INFO *btnPtr;
2504 INT nIndex;
2506 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2507 if (nIndex == -1)
2508 return FALSE;
2510 btnPtr = &infoPtr->buttons[nIndex];
2511 if (LOWORD(lParam) == FALSE)
2512 btnPtr->fsState &= ~TBSTATE_PRESSED;
2513 else
2514 btnPtr->fsState |= TBSTATE_PRESSED;
2516 RedrawWindow(hwnd,&btnPtr->rect,0,
2517 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2519 return TRUE;
2523 /* << TOOLBAR_ReplaceBitmap >> */
2526 static LRESULT
2527 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2529 #if 0
2530 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2531 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2533 if (lpSave == NULL) return 0;
2535 if ((BOOL)wParam) {
2536 /* save toolbar information */
2537 FIXME("save to \"%s\" \"%s\"\n",
2538 lpSave->pszSubKey, lpSave->pszValueName);
2542 else {
2543 /* restore toolbar information */
2545 FIXME("restore from \"%s\" \"%s\"\n",
2546 lpSave->pszSubKey, lpSave->pszValueName);
2550 #endif
2552 return 0;
2556 static LRESULT
2557 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2559 #if 0
2560 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2561 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2563 if (lpSave == NULL)
2564 return 0;
2566 if ((BOOL)wParam) {
2567 /* save toolbar information */
2568 FIXME("save to \"%s\" \"%s\"\n",
2569 lpSave->pszSubKey, lpSave->pszValueName);
2573 else {
2574 /* restore toolbar information */
2576 FIXME("restore from \"%s\" \"%s\"\n",
2577 lpSave->pszSubKey, lpSave->pszValueName);
2581 #endif
2583 return 0;
2587 static LRESULT
2588 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2590 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2591 BOOL bOldAnchor = infoPtr->bAnchor;
2593 infoPtr->bAnchor = (BOOL)wParam;
2595 return (LRESULT)bOldAnchor;
2599 static LRESULT
2600 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2602 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2604 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2605 return FALSE;
2607 /* Bitmap size can only be set before adding any button to the toolbar
2608 according to the documentation. */
2609 if( infoPtr->nNumButtons != 0 )
2610 return FALSE;
2612 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2613 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2615 return TRUE;
2619 static LRESULT
2620 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2622 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2623 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2624 TBUTTON_INFO *btnPtr;
2625 INT nIndex;
2627 if (lptbbi == NULL)
2628 return FALSE;
2629 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2630 return FALSE;
2632 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2633 if (nIndex == -1)
2634 return FALSE;
2636 btnPtr = &infoPtr->buttons[nIndex];
2637 if (lptbbi->dwMask & TBIF_COMMAND)
2638 btnPtr->idCommand = lptbbi->idCommand;
2639 if (lptbbi->dwMask & TBIF_IMAGE)
2640 btnPtr->iBitmap = lptbbi->iImage;
2641 if (lptbbi->dwMask & TBIF_LPARAM)
2642 btnPtr->dwData = lptbbi->lParam;
2643 /* if (lptbbi->dwMask & TBIF_SIZE) */
2644 /* btnPtr->cx = lptbbi->cx; */
2645 if (lptbbi->dwMask & TBIF_STATE)
2646 btnPtr->fsState = lptbbi->fsState;
2647 if (lptbbi->dwMask & TBIF_STYLE)
2648 btnPtr->fsStyle = lptbbi->fsStyle;
2650 if (lptbbi->dwMask & TBIF_TEXT) {
2651 if ((btnPtr->iString >= 0) ||
2652 (btnPtr->iString < infoPtr->nNumStrings)) {
2653 TRACE("Ooooooch\n");
2654 #if 0
2655 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2656 INT len = lstrlenA (lptbbi->pszText);
2657 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2658 #endif
2660 /* this is the ultimate sollution */
2661 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2665 return TRUE;
2669 static LRESULT
2670 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2673 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2674 TBUTTON_INFO *btnPtr;
2675 INT nIndex;
2677 if (lptbbi == NULL)
2678 return FALSE;
2679 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2680 return FALSE;
2682 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2683 if (nIndex == -1)
2684 return FALSE;
2686 btnPtr = &infoPtr->buttons[nIndex];
2687 if (lptbbi->dwMask & TBIF_COMMAND)
2688 btnPtr->idCommand = lptbbi->idCommand;
2689 if (lptbbi->dwMask & TBIF_IMAGE)
2690 btnPtr->iBitmap = lptbbi->iImage;
2691 if (lptbbi->dwMask & TBIF_LPARAM)
2692 btnPtr->dwData = lptbbi->lParam;
2693 /* if (lptbbi->dwMask & TBIF_SIZE) */
2694 /* btnPtr->cx = lptbbi->cx; */
2695 if (lptbbi->dwMask & TBIF_STATE)
2696 btnPtr->fsState = lptbbi->fsState;
2697 if (lptbbi->dwMask & TBIF_STYLE)
2698 btnPtr->fsStyle = lptbbi->fsStyle;
2700 if (lptbbi->dwMask & TBIF_TEXT) {
2701 if ((btnPtr->iString >= 0) ||
2702 (btnPtr->iString < infoPtr->nNumStrings)) {
2703 #if 0
2704 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2705 INT len = lstrlenW (lptbbi->pszText);
2706 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2707 #endif
2709 /* this is the ultimate sollution */
2710 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2714 return TRUE;
2718 static LRESULT
2719 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2721 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2723 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2724 return FALSE;
2726 /* Button size can only be set before adding any button to the toolbar
2727 according to the documentation. */
2728 if( infoPtr->nNumButtons != 0 )
2729 return FALSE;
2731 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2732 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2733 return TRUE;
2737 static LRESULT
2738 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2740 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2742 if (infoPtr == NULL)
2743 return FALSE;
2745 infoPtr->cxMin = (INT)LOWORD(lParam);
2746 infoPtr->cxMax = (INT)HIWORD(lParam);
2748 return TRUE;
2752 static LRESULT
2753 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2755 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2756 INT nIndex = (INT)wParam;
2758 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2759 return FALSE;
2761 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2763 if (infoPtr->hwndToolTip) {
2765 FIXME("change tool tip!\n");
2769 return TRUE;
2773 /* << TOOLBAR_SetColorScheme >> */
2776 static LRESULT
2777 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2779 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2780 HIMAGELIST himlTemp;
2783 himlTemp = infoPtr->himlDis;
2784 infoPtr->himlDis = (HIMAGELIST)lParam;
2786 /* FIXME: redraw ? */
2788 return (LRESULT)himlTemp;
2792 static LRESULT
2793 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2795 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2796 DWORD dwTemp;
2798 dwTemp = infoPtr->dwDTFlags;
2799 infoPtr->dwDTFlags =
2800 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2802 return (LRESULT)dwTemp;
2806 static LRESULT
2807 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2809 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2810 DWORD dwTemp;
2812 dwTemp = infoPtr->dwExStyle;
2813 infoPtr->dwExStyle = (DWORD)lParam;
2815 return (LRESULT)dwTemp;
2819 static LRESULT
2820 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2822 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2823 HIMAGELIST himlTemp;
2825 himlTemp = infoPtr->himlHot;
2826 infoPtr->himlHot = (HIMAGELIST)lParam;
2828 /* FIXME: redraw ? */
2830 return (LRESULT)himlTemp;
2834 static LRESULT
2835 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
2837 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2838 INT nOldHotItem = infoPtr->nHotItem;
2840 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
2842 infoPtr->nHotItem = (INT)wParam;
2844 /* FIXME: What else must be done ??? */
2848 if (nOldHotItem < 0)
2849 return -1;
2851 return (LRESULT)nOldHotItem;
2855 static LRESULT
2856 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2858 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2859 HIMAGELIST himlTemp;
2861 himlTemp = infoPtr->himlDef;
2862 infoPtr->himlDef = (HIMAGELIST)lParam;
2864 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
2865 /* FIXME: redraw ? */
2867 return (LRESULT)himlTemp;
2871 static LRESULT
2872 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2874 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2876 infoPtr->nIndent = (INT)wParam;
2878 TOOLBAR_CalcToolbar (hwnd);
2880 InvalidateRect(hwnd, NULL, FALSE);
2882 return TRUE;
2886 /* << TOOLBAR_SetInsertMark >> */
2889 static LRESULT
2890 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2892 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2894 infoPtr->clrInsertMark = (COLORREF)lParam;
2896 /* FIXME : redraw ??*/
2898 return 0;
2902 static LRESULT
2903 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2905 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2907 if (infoPtr == NULL)
2908 return FALSE;
2910 infoPtr->nMaxTextRows = (INT)wParam;
2912 return TRUE;
2916 /* << TOOLBAR_SetPadding >> */
2919 static LRESULT
2920 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2922 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2923 HWND hwndOldNotify;
2925 if (infoPtr == NULL)
2926 return 0;
2927 hwndOldNotify = infoPtr->hwndNotify;
2928 infoPtr->hwndNotify = (HWND)wParam;
2930 return hwndOldNotify;
2934 static LRESULT
2935 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2937 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2938 LPRECT lprc = (LPRECT)lParam;
2940 if (LOWORD(wParam) > 1) {
2942 FIXME("multiple rows not supported!\n");
2946 /* recalculate toolbar */
2947 TOOLBAR_CalcToolbar (hwnd);
2949 /* return bounding rectangle */
2950 if (lprc) {
2951 lprc->left = infoPtr->rcBound.left;
2952 lprc->right = infoPtr->rcBound.right;
2953 lprc->top = infoPtr->rcBound.top;
2954 lprc->bottom = infoPtr->rcBound.bottom;
2957 /* repaint toolbar */
2958 InvalidateRect(hwnd, NULL, FALSE);
2960 return 0;
2964 static LRESULT
2965 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2967 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2968 TBUTTON_INFO *btnPtr;
2969 INT nIndex;
2971 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2972 if (nIndex == -1)
2973 return FALSE;
2975 btnPtr = &infoPtr->buttons[nIndex];
2976 btnPtr->fsState = LOWORD(lParam);
2978 RedrawWindow(hwnd,&btnPtr->rect,0,
2979 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2981 return TRUE;
2985 static LRESULT
2986 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2988 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2989 TBUTTON_INFO *btnPtr;
2990 INT nIndex;
2992 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2993 if (nIndex == -1)
2994 return FALSE;
2996 btnPtr = &infoPtr->buttons[nIndex];
2997 btnPtr->fsStyle = LOWORD(lParam);
2999 RedrawWindow(hwnd,&btnPtr->rect,0,
3000 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3002 if (infoPtr->hwndToolTip) {
3004 FIXME("change tool tip!\n");
3008 return TRUE;
3012 inline static LRESULT
3013 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3015 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3017 if (infoPtr == NULL)
3018 return 0;
3019 infoPtr->hwndToolTip = (HWND)wParam;
3020 return 0;
3024 static LRESULT
3025 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3027 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3028 BOOL bTemp;
3030 TRACE("%s hwnd=0x%04x stub!\n",
3031 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3033 bTemp = infoPtr->bUnicode;
3034 infoPtr->bUnicode = (BOOL)wParam;
3036 return bTemp;
3040 static LRESULT
3041 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3043 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3044 INT iOldVersion = infoPtr->iVersion;
3046 infoPtr->iVersion = iVersion;
3048 return iOldVersion;
3052 static LRESULT
3053 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3055 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3056 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3057 LOGFONTA logFont;
3059 /* initialize info structure */
3060 infoPtr->nButtonHeight = 22;
3061 infoPtr->nButtonWidth = 24;
3062 infoPtr->nBitmapHeight = 15;
3063 infoPtr->nBitmapWidth = 16;
3065 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3066 infoPtr->nRows = 1;
3067 infoPtr->nMaxTextRows = 1;
3068 infoPtr->cxMin = -1;
3069 infoPtr->cxMax = -1;
3070 infoPtr->nNumBitmaps = 0;
3071 infoPtr->nNumStrings = 0;
3073 infoPtr->bCaptured = FALSE;
3074 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3075 infoPtr->nButtonDown = -1;
3076 infoPtr->nOldHit = -1;
3077 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3078 infoPtr->hwndNotify = GetParent (hwnd);
3079 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3080 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3081 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3082 infoPtr->iVersion = 0;
3084 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3085 infoPtr->hFont = CreateFontIndirectA (&logFont);
3087 if (dwStyle & TBSTYLE_TOOLTIPS) {
3088 /* Create tooltip control */
3089 infoPtr->hwndToolTip =
3090 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3091 CW_USEDEFAULT, CW_USEDEFAULT,
3092 CW_USEDEFAULT, CW_USEDEFAULT,
3093 hwnd, 0, 0, 0);
3095 /* Send NM_TOOLTIPSCREATED notification */
3096 if (infoPtr->hwndToolTip) {
3097 NMTOOLTIPSCREATED nmttc;
3099 nmttc.hdr.hwndFrom = hwnd;
3100 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3101 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3102 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3104 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3105 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3109 return 0;
3113 static LRESULT
3114 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3116 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3118 /* delete tooltip control */
3119 if (infoPtr->hwndToolTip)
3120 DestroyWindow (infoPtr->hwndToolTip);
3122 /* delete button data */
3123 if (infoPtr->buttons)
3124 COMCTL32_Free (infoPtr->buttons);
3126 /* delete strings */
3127 if (infoPtr->strings) {
3128 INT i;
3129 for (i = 0; i < infoPtr->nNumStrings; i++)
3130 if (infoPtr->strings[i])
3131 COMCTL32_Free (infoPtr->strings[i]);
3133 COMCTL32_Free (infoPtr->strings);
3136 /* destroy internal image list */
3137 if (infoPtr->himlInt)
3138 ImageList_Destroy (infoPtr->himlInt);
3140 /* delete default font */
3141 if (infoPtr->hFont)
3142 DeleteObject (infoPtr->hFont);
3144 /* free toolbar info data */
3145 COMCTL32_Free (infoPtr);
3146 SetWindowLongA (hwnd, 0, 0);
3148 return 0;
3152 static LRESULT
3153 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3155 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3157 if (infoPtr->bTransparent)
3158 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3160 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3164 static LRESULT
3165 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3167 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3169 return infoPtr->hFont;
3173 static LRESULT
3174 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3176 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3177 TBUTTON_INFO *btnPtr;
3178 POINT pt;
3179 INT nHit;
3181 pt.x = (INT)LOWORD(lParam);
3182 pt.y = (INT)HIWORD(lParam);
3183 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3185 if (nHit >= 0) {
3186 btnPtr = &infoPtr->buttons[nHit];
3187 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3188 return 0;
3189 SetCapture (hwnd);
3190 infoPtr->bCaptured = TRUE;
3191 infoPtr->nButtonDown = nHit;
3193 btnPtr->fsState |= TBSTATE_PRESSED;
3195 RedrawWindow(hwnd,&btnPtr->rect,0,
3196 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3198 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3199 TOOLBAR_Customize (hwnd);
3201 return 0;
3205 static LRESULT
3206 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3208 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3209 TBUTTON_INFO *btnPtr;
3210 POINT pt;
3211 INT nHit;
3213 if (infoPtr->hwndToolTip)
3214 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3215 WM_LBUTTONDOWN, wParam, lParam);
3217 pt.x = (INT)LOWORD(lParam);
3218 pt.y = (INT)HIWORD(lParam);
3219 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3221 if (nHit >= 0) {
3222 btnPtr = &infoPtr->buttons[nHit];
3223 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3224 return 0;
3226 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
3228 NMTOOLBARA nmtb;
3230 nmtb.hdr.hwndFrom = hwnd;
3231 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3232 nmtb.hdr.code = TBN_DROPDOWN;
3233 nmtb.iItem = btnPtr->idCommand;
3235 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3236 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3239 SetCapture (hwnd);
3240 infoPtr->bCaptured = TRUE;
3241 infoPtr->nButtonDown = nHit;
3242 infoPtr->nOldHit = nHit;
3244 btnPtr->fsState |= TBSTATE_PRESSED;
3245 btnPtr->bHot = FALSE;
3247 RedrawWindow(hwnd,&btnPtr->rect,0,
3248 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3251 return 0;
3254 static LRESULT
3255 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3257 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3258 TBUTTON_INFO *btnPtr;
3259 POINT pt;
3260 INT nHit;
3261 INT nOldIndex = -1;
3262 BOOL bSendMessage = TRUE;
3264 if (infoPtr->hwndToolTip)
3265 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3266 WM_LBUTTONUP, wParam, lParam);
3268 pt.x = (INT)LOWORD(lParam);
3269 pt.y = (INT)HIWORD(lParam);
3270 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3272 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3273 if(infoPtr->nHotItem >= 0)
3274 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3276 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3277 infoPtr->bCaptured = FALSE;
3278 ReleaseCapture ();
3279 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3280 btnPtr->fsState &= ~TBSTATE_PRESSED;
3282 if (nHit == infoPtr->nButtonDown) {
3283 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3284 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3285 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3286 infoPtr->nButtonDown);
3287 if (nOldIndex == infoPtr->nButtonDown)
3288 bSendMessage = FALSE;
3289 if ((nOldIndex != infoPtr->nButtonDown) &&
3290 (nOldIndex != -1))
3291 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3292 btnPtr->fsState |= TBSTATE_CHECKED;
3294 else {
3295 if (btnPtr->fsState & TBSTATE_CHECKED)
3296 btnPtr->fsState &= ~TBSTATE_CHECKED;
3297 else
3298 btnPtr->fsState |= TBSTATE_CHECKED;
3302 else
3303 bSendMessage = FALSE;
3305 if (nOldIndex != -1)
3306 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,0,
3307 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3308 RedrawWindow(hwnd,&btnPtr->rect,0,
3309 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3311 if (bSendMessage) {
3312 SendMessageA (GetParent(hwnd), WM_COMMAND,
3313 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3315 // if ((GetWindowLongA(hwnd, GWL_STYLE) & TBSTYLE_DROPDOWN) ||
3316 // (btnPtr->fsStyle & 0x08/* BTNS_DROPDOWN */)) {
3318 * This appears to be an error. Instead of checking the style of the
3319 * button in question wine was checking the style of the toolbar
3320 * itself. This caused a number of strange behaviors. In my
3321 * invistigation i think the whole dropdown thing is still fairly
3322 * broken. but this helps fix some of the problems.
3325 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
3326 NMTOOLBARW nmtb;
3328 nmtb.hdr.hwndFrom = hwnd;
3329 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3330 nmtb.hdr.code = TBN_DROPDOWN;
3331 nmtb.iItem = nHit;
3332 /* nmtb.tbButton not used with TBN_DROPDOWN */
3333 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) {
3334 nmtb.pszText = infoPtr->strings[btnPtr->iString];
3335 nmtb.cchText = lstrlenW(nmtb.pszText);
3336 } else {
3337 nmtb.pszText = NULL;
3338 nmtb.cchText = 0;
3340 nmtb.rcButton = btnPtr->rect;
3342 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
3343 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3346 infoPtr->nButtonDown = -1;
3347 infoPtr->nOldHit = -1;
3350 return 0;
3353 static LRESULT
3354 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3356 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3357 TBUTTON_INFO *hotBtnPtr;
3359 if (infoPtr->nOldHit < 0)
3360 return TRUE;
3362 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3364 /* Redraw the button if the last button we were over is the hot button and it
3365 is enabled */
3366 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3368 hotBtnPtr->bHot = FALSE;
3370 InvalidateRect (hwnd, &hotBtnPtr->rect, TRUE);
3373 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3374 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3376 return TRUE;
3379 static LRESULT
3380 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3382 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3383 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3384 POINT pt;
3385 INT nHit;
3386 TRACKMOUSEEVENT trackinfo;
3388 /* fill in the TRACKMOUSEEVENT struct */
3389 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3390 trackinfo.dwFlags = TME_QUERY;
3391 trackinfo.hwndTrack = hwnd;
3392 trackinfo.dwHoverTime = HOVER_DEFAULT;
3394 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3395 _TrackMouseEvent(&trackinfo);
3397 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3398 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3399 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3401 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3402 /* and can properly deactivate the hot toolbar button */
3403 _TrackMouseEvent(&trackinfo);
3406 if (infoPtr->hwndToolTip)
3407 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3408 WM_MOUSEMOVE, wParam, lParam);
3410 pt.x = (INT)LOWORD(lParam);
3411 pt.y = (INT)HIWORD(lParam);
3413 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3415 if (infoPtr->nOldHit != nHit)
3417 /* Remove the effect of an old hot button if the button was enabled and was
3418 drawn with the hot button effect */
3419 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
3420 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3422 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3423 oldBtnPtr->bHot = FALSE;
3425 InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
3428 /* It's not a separator or in nowhere. It's a hot button. */
3429 if (nHit >= 0)
3431 btnPtr = &infoPtr->buttons[nHit];
3432 btnPtr->bHot = TRUE;
3434 infoPtr->nHotItem = nHit;
3436 /* only enabled buttons show hot effect */
3437 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3439 RedrawWindow(hwnd,&btnPtr->rect,0,
3440 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3444 if (infoPtr->bCaptured) {
3445 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3446 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3447 btnPtr->fsState &= ~TBSTATE_PRESSED;
3448 RedrawWindow(hwnd,&btnPtr->rect,0,
3449 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3451 else if (nHit == infoPtr->nButtonDown) {
3452 btnPtr->fsState |= TBSTATE_PRESSED;
3453 RedrawWindow(hwnd,&btnPtr->rect,0,
3454 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3457 infoPtr->nOldHit = nHit;
3459 return 0;
3463 inline static LRESULT
3464 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3466 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3467 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3468 /* else */
3469 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3473 inline static LRESULT
3474 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3476 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3477 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3479 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3483 static LRESULT
3484 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3486 TOOLBAR_INFO *infoPtr;
3488 /* allocate memory for info structure */
3489 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3490 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3492 /* paranoid!! */
3493 infoPtr->dwStructSize = sizeof(TBBUTTON);
3495 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3496 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3497 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3498 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3501 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3505 static LRESULT
3506 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3508 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3509 RECT rcWindow;
3510 HDC hdc;
3512 if (dwStyle & WS_MINIMIZE)
3513 return 0; /* Nothing to do */
3515 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3517 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3518 return 0;
3520 if (!(dwStyle & CCS_NODIVIDER))
3522 GetWindowRect (hwnd, &rcWindow);
3523 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3524 if( dwStyle & WS_BORDER )
3525 OffsetRect (&rcWindow, 1, 1);
3526 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3529 ReleaseDC( hwnd, hdc );
3531 return 0;
3535 inline static LRESULT
3536 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3538 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3539 LPNMHDR lpnmh = (LPNMHDR)lParam;
3541 TRACE("passing WM_NOTIFY!\n");
3543 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3544 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3546 #if 0
3547 if (lpnmh->code == TTN_GETDISPINFOA) {
3548 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3550 FIXME("retrieving ASCII string\n");
3553 else if (lpnmh->code == TTN_GETDISPINFOW) {
3554 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3556 FIXME("retrieving UNICODE string\n");
3559 #endif
3562 return 0;
3566 static LRESULT
3567 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3569 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3570 HDC hdc;
3571 PAINTSTRUCT ps;
3573 /* fill ps.rcPaint with a default rect */
3574 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
3576 TOOLBAR_CalcToolbar( hwnd );
3577 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
3578 TOOLBAR_Refresh (hwnd, hdc, &ps);
3579 if (!wParam) EndPaint (hwnd, &ps);
3581 return 0;
3585 static LRESULT
3586 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3588 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3589 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3590 RECT parent_rect;
3591 RECT window_rect;
3592 HWND parent;
3593 INT x, y;
3594 INT cx, cy;
3595 INT flags;
3596 UINT uPosFlags = 0;
3598 /* Resize deadlock check */
3599 if (infoPtr->bAutoSize) {
3600 infoPtr->bAutoSize = FALSE;
3601 return 0;
3604 flags = (INT) wParam;
3606 /* FIXME for flags =
3607 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3610 TRACE("sizing toolbar!\n");
3612 if (flags == SIZE_RESTORED) {
3613 /* width and height don't apply */
3614 parent = GetParent (hwnd);
3615 GetClientRect(parent, &parent_rect);
3616 x = parent_rect.left;
3617 y = parent_rect.top;
3619 if (dwStyle & CCS_NORESIZE) {
3620 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3623 * this sets the working width of the toolbar, and
3624 * Calc Toolbar will not adjust it, only the height
3626 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3627 cy = infoPtr->nHeight;
3628 cx = infoPtr->nWidth;
3629 TOOLBAR_CalcToolbar (hwnd);
3630 infoPtr->nWidth = cx;
3631 infoPtr->nHeight = cy;
3633 else {
3634 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3635 TOOLBAR_CalcToolbar (hwnd);
3636 cy = infoPtr->nHeight;
3637 cx = infoPtr->nWidth;
3639 if (dwStyle & CCS_NOMOVEY) {
3640 GetWindowRect(hwnd, &window_rect);
3641 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3642 y = window_rect.top;
3646 if (dwStyle & CCS_NOPARENTALIGN) {
3647 uPosFlags |= SWP_NOMOVE;
3648 cy = infoPtr->nHeight;
3649 cx = infoPtr->nWidth;
3652 if (!(dwStyle & CCS_NODIVIDER))
3653 cy += GetSystemMetrics(SM_CYEDGE);
3655 if (dwStyle & WS_BORDER)
3657 x = y = 1;
3658 cy += GetSystemMetrics(SM_CYEDGE);
3659 cx += GetSystemMetrics(SM_CYEDGE);
3662 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3663 cx, cy, uPosFlags | SWP_NOZORDER);
3665 return 0;
3669 static LRESULT
3670 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3672 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3674 if (nType == GWL_STYLE) {
3675 if (lpStyle->styleNew & TBSTYLE_LIST) {
3676 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3678 else {
3679 infoPtr->dwDTFlags = DT_CENTER;
3683 TOOLBAR_AutoSize (hwnd);
3685 InvalidateRect(hwnd, NULL, FALSE);
3687 return 0;
3692 static LRESULT WINAPI
3693 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3696 switch (uMsg)
3698 case WM_DESTROY:
3699 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3701 case WM_NCCREATE:
3702 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3705 if (!TOOLBAR_GetInfoPtr (hwnd))
3707 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3710 switch (uMsg)
3712 case TB_ADDBITMAP:
3713 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3715 case TB_ADDBUTTONSA:
3716 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3718 case TB_ADDBUTTONSW:
3719 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3721 case TB_ADDSTRINGA:
3722 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3724 case TB_ADDSTRINGW:
3725 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3727 case TB_AUTOSIZE:
3728 return TOOLBAR_AutoSize (hwnd);
3730 case TB_BUTTONCOUNT:
3731 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3733 case TB_BUTTONSTRUCTSIZE:
3734 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3736 case TB_CHANGEBITMAP:
3737 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3739 case TB_CHECKBUTTON:
3740 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3742 case TB_COMMANDTOINDEX:
3743 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3745 case TB_CUSTOMIZE:
3746 return TOOLBAR_Customize (hwnd);
3748 case TB_DELETEBUTTON:
3749 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3751 case TB_ENABLEBUTTON:
3752 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3754 case TB_GETANCHORHIGHLIGHT:
3755 return TOOLBAR_GetAnchorHighlight (hwnd);
3757 case TB_GETBITMAP:
3758 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3760 case TB_GETBITMAPFLAGS:
3761 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3763 case TB_GETBUTTON:
3764 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3766 case TB_GETBUTTONINFOA:
3767 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3769 case TB_GETBUTTONINFOW:
3770 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3772 case TB_GETBUTTONSIZE:
3773 return TOOLBAR_GetButtonSize (hwnd);
3775 case TB_GETBUTTONTEXTA:
3776 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3778 case TB_GETBUTTONTEXTW:
3779 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
3781 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
3783 case TB_GETDISABLEDIMAGELIST:
3784 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3786 case TB_GETEXTENDEDSTYLE:
3787 return TOOLBAR_GetExtendedStyle (hwnd);
3789 case TB_GETHOTIMAGELIST:
3790 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3792 case TB_GETHOTITEM:
3793 return TOOLBAR_GetHotItem (hwnd);
3795 case TB_GETIMAGELIST:
3796 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3798 /* case TB_GETINSERTMARK: */ /* 4.71 */
3799 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
3801 case TB_GETITEMRECT:
3802 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3804 case TB_GETMAXSIZE:
3805 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3807 /* case TB_GETOBJECT: */ /* 4.71 */
3808 /* case TB_GETPADDING: */ /* 4.71 */
3810 case TB_GETRECT:
3811 return TOOLBAR_GetRect (hwnd, wParam, lParam);
3813 case TB_GETROWS:
3814 return TOOLBAR_GetRows (hwnd, wParam, lParam);
3816 case TB_GETSTATE:
3817 return TOOLBAR_GetState (hwnd, wParam, lParam);
3819 case TB_GETSTYLE:
3820 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3822 case TB_GETTEXTROWS:
3823 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3825 case TB_GETTOOLTIPS:
3826 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3828 case TB_GETUNICODEFORMAT:
3829 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3831 case CCM_GETVERSION:
3832 return TOOLBAR_GetVersion (hwnd);
3834 case TB_HIDEBUTTON:
3835 return TOOLBAR_HideButton (hwnd, wParam, lParam);
3837 case TB_HITTEST:
3838 return TOOLBAR_HitTest (hwnd, wParam, lParam);
3840 case TB_INDETERMINATE:
3841 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3843 case TB_INSERTBUTTONA:
3844 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3846 case TB_INSERTBUTTONW:
3847 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
3849 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
3851 case TB_ISBUTTONCHECKED:
3852 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3854 case TB_ISBUTTONENABLED:
3855 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3857 case TB_ISBUTTONHIDDEN:
3858 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3860 case TB_ISBUTTONHIGHLIGHTED:
3861 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3863 case TB_ISBUTTONINDETERMINATE:
3864 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3866 case TB_ISBUTTONPRESSED:
3867 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3869 case TB_LOADIMAGES: /* 4.70 */
3870 FIXME("missing standard imagelists\n");
3871 return 0;
3873 /* case TB_MAPACCELERATORA: */ /* 4.71 */
3874 /* case TB_MAPACCELERATORW: */ /* 4.71 */
3875 /* case TB_MARKBUTTON: */ /* 4.71 */
3876 /* case TB_MOVEBUTTON: */ /* 4.71 */
3878 case TB_PRESSBUTTON:
3879 return TOOLBAR_PressButton (hwnd, wParam, lParam);
3881 /* case TB_REPLACEBITMAP: */
3883 case TB_SAVERESTOREA:
3884 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3886 case TB_SAVERESTOREW:
3887 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
3889 case TB_SETANCHORHIGHLIGHT:
3890 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
3892 case TB_SETBITMAPSIZE:
3893 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3895 case TB_SETBUTTONINFOA:
3896 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3898 case TB_SETBUTTONINFOW:
3899 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
3901 case TB_SETBUTTONSIZE:
3902 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3904 case TB_SETBUTTONWIDTH:
3905 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3907 case TB_SETCMDID:
3908 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3910 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
3912 case TB_SETDISABLEDIMAGELIST:
3913 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3915 case TB_SETDRAWTEXTFLAGS:
3916 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3918 case TB_SETEXTENDEDSTYLE:
3919 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3921 case TB_SETHOTIMAGELIST:
3922 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3924 case TB_SETHOTITEM:
3925 return TOOLBAR_SetHotItem (hwnd, wParam);
3927 case TB_SETIMAGELIST:
3928 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3930 case TB_SETINDENT:
3931 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3933 /* case TB_SETINSERTMARK: */ /* 4.71 */
3935 case TB_SETINSERTMARKCOLOR:
3936 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3938 case TB_SETMAXTEXTROWS:
3939 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3941 /* case TB_SETPADDING: */ /* 4.71 */
3943 case TB_SETPARENT:
3944 return TOOLBAR_SetParent (hwnd, wParam, lParam);
3946 case TB_SETROWS:
3947 return TOOLBAR_SetRows (hwnd, wParam, lParam);
3949 case TB_SETSTATE:
3950 return TOOLBAR_SetState (hwnd, wParam, lParam);
3952 case TB_SETSTYLE:
3953 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3955 case TB_SETTOOLTIPS:
3956 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3958 case TB_SETUNICODEFORMAT:
3959 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3961 case CCM_SETVERSION:
3962 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
3965 /* case WM_CHAR: */
3967 case WM_CREATE:
3968 return TOOLBAR_Create (hwnd, wParam, lParam);
3970 case WM_ERASEBKGND:
3971 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
3973 case WM_GETFONT:
3974 return TOOLBAR_GetFont (hwnd, wParam, lParam);
3976 /* case WM_KEYDOWN: */
3977 /* case WM_KILLFOCUS: */
3979 case WM_LBUTTONDBLCLK:
3980 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
3982 case WM_LBUTTONDOWN:
3983 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
3985 case WM_LBUTTONUP:
3986 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
3988 case WM_MOUSEMOVE:
3989 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
3991 case WM_MOUSELEAVE:
3992 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
3994 case WM_NCACTIVATE:
3995 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
3997 case WM_NCCALCSIZE:
3998 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4000 case WM_NCPAINT:
4001 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4003 case WM_NOTIFY:
4004 return TOOLBAR_Notify (hwnd, wParam, lParam);
4006 /* case WM_NOTIFYFORMAT: */
4008 case WM_PAINT:
4009 return TOOLBAR_Paint (hwnd, wParam);
4011 case WM_SIZE:
4012 return TOOLBAR_Size (hwnd, wParam, lParam);
4014 case WM_STYLECHANGED:
4015 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4017 /* case WM_SYSCOLORCHANGE: */
4019 /* case WM_WININICHANGE: */
4021 case WM_CHARTOITEM:
4022 case WM_COMMAND:
4023 case WM_DRAWITEM:
4024 case WM_MEASUREITEM:
4025 case WM_VKEYTOITEM:
4026 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4028 default:
4029 if (uMsg >= WM_USER)
4030 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4031 uMsg, wParam, lParam);
4032 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4034 return 0;
4038 VOID
4039 TOOLBAR_Register (void)
4041 WNDCLASSA wndClass;
4043 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4044 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4045 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4046 wndClass.cbClsExtra = 0;
4047 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4048 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4049 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4050 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4052 RegisterClassA (&wndClass);
4056 VOID
4057 TOOLBAR_Unregister (void)
4059 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);