4 * Copyright 1998,1999 Eric Kohl
7 * - A little bug in TOOLBAR_DrawMasked()
8 * - Button wrapping (under construction).
10 * - Notifications (under construction).
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.
18 * - iString of -1 is undocumented
21 * - Run tests using Waite Group Windows95 API Bible Volume 2.
22 * The second cdrom contains executables addstr.exe, btncount.exe,
23 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
24 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
25 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
26 * setparnt.exe, setrows.exe, toolwnd.exe.
27 * - Microsofts controlspy examples.
36 #include "wine/unicode.h"
37 #include "wine/winestring.h"
39 #include "imagelist.h"
42 #include "debugtools.h"
44 DEFAULT_DEBUG_CHANNEL(toolbar);
62 DWORD dwStructSize; /* size of TBBUTTON struct */
63 INT nHeight; /* height of the toolbar */
64 INT nWidth; /* width of the toolbar */
70 INT nRows; /* number of button rows */
71 INT nMaxTextRows; /* maximum number of text rows */
72 INT cxMin; /* minimum button width */
73 INT cxMax; /* maximum button width */
74 INT nNumButtons; /* number of buttons */
75 INT nNumBitmaps; /* number of bitmaps */
76 INT nNumStrings; /* number of strings */
77 BOOL bUnicode; /* ASCII (FALSE) or Unicode (TRUE)? */
78 BOOL bCaptured; /* mouse captured? */
81 INT nHotItem; /* index of the "hot" item */
82 HFONT hFont; /* text font */
83 HIMAGELIST himlInt; /* image list created internally */
84 HIMAGELIST himlDef; /* default image list */
85 HIMAGELIST himlHot; /* hot image list */
86 HIMAGELIST himlDis; /* disabled image list */
87 HWND hwndToolTip; /* handle to tool tip control */
88 HWND hwndNotify; /* handle to the window that gets notifications */
89 BOOL bTransparent; /* background transparency flag */
90 BOOL bAutoSize; /* auto size deadlock indicator */
91 BOOL bAnchor; /* anchor highlight enabled */
92 DWORD dwExStyle; /* extended toolbar style */
93 DWORD dwDTFlags; /* DrawText flags */
95 COLORREF clrInsertMark; /* insert mark color */
96 RECT rcBound; /* bounding rectangle */
99 TBUTTON_INFO *buttons; /* pointer to button array */
100 LPWSTR *strings; /* pointer to string array */
103 #define SEPARATOR_WIDTH 8
105 #define BOTTOM_BORDER 2
106 #define DDARROW_WIDTH 11
108 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
109 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
110 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
113 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
115 LPWSTR lpText = NULL;
117 /* FIXME: iString == -1 is undocumented */
118 if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
119 lpText = (LPWSTR)btnPtr->iString;
120 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
121 lpText = infoPtr->strings[btnPtr->iString];
127 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
129 if ((index>=0) && (index < infoPtr->nNumBitmaps))
137 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
139 INT x = (lpRect->left + lpRect->right) / 2 - 1;
140 INT yBottom = lpRect->bottom - 3;
141 INT yTop = lpRect->top + 1;
143 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
144 MoveToEx (hdc, x, yBottom, NULL);
145 LineTo (hdc, x, yTop);
147 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
148 MoveToEx (hdc, x, yBottom, NULL);
149 LineTo (hdc, x, yTop);
153 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
156 SelectObject ( hdc, GetSysColorPen (colorRef));
159 MoveToEx (hdc, x, y, NULL);
160 LineTo (hdc, x+5, y++); x++;
161 MoveToEx (hdc, x, y, NULL);
162 LineTo (hdc, x+3, y++); x++;
163 MoveToEx (hdc, x, y, NULL);
164 LineTo (hdc, x+1, y++);
168 * Draw the text string for this button.
169 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
170 * is non-zero, so we can simply check himlDef to see if we have
174 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
175 HDC hdc, INT nState, DWORD dwStyle)
177 RECT rcText = btnPtr->rect;
181 LPWSTR lpText = NULL;
182 HIMAGELIST himl = infoPtr->himlDef;
184 TRACE ("iString: %x\n", btnPtr->iString);
186 /* get a pointer to the text */
187 lpText = TOOLBAR_GetText(infoPtr, btnPtr);
189 TRACE ("lpText: \"%s\"\n", debugstr_w(lpText));
194 InflateRect (&rcText, -3, -3);
196 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
197 if ((dwStyle & TBSTYLE_LIST) &&
198 ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
199 (btnPtr->iBitmap != I_IMAGENONE)) {
200 rcText.left += infoPtr->nBitmapWidth;
203 rcText.top += infoPtr->nBitmapHeight;
207 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
208 OffsetRect (&rcText, 1, 1);
210 hOldFont = SelectObject (hdc, infoPtr->hFont);
211 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
212 if (!(nState & TBSTATE_ENABLED)) {
213 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
214 OffsetRect (&rcText, 1, 1);
215 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
216 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
217 OffsetRect (&rcText, -1, -1);
218 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
220 else if (nState & TBSTATE_INDETERMINATE) {
221 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
222 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
225 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
226 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
229 SetTextColor (hdc, clrOld);
230 SelectObject (hdc, hOldFont);
231 if (nOldBkMode != TRANSPARENT)
232 SetBkMode (hdc, nOldBkMode);
238 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
240 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
241 INT cx = lpRect->right - lpRect->left;
242 INT cy = lpRect->bottom - lpRect->top;
243 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
244 SelectObject (hdc, hbr);
249 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
250 HDC hdc, INT x, INT y)
252 /* FIXME: this function is a hack since it uses image list
253 internals directly */
255 HIMAGELIST himl = infoPtr->himlDef;
263 /* create new dc's */
264 hdcImageList = CreateCompatibleDC (0);
265 hdcMask = CreateCompatibleDC (0);
267 /* create new bitmap */
268 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
269 SelectObject (hdcMask, hbmMask);
271 /* copy the mask bitmap */
272 SelectObject (hdcImageList, himl->hbmMask);
273 SetBkColor (hdcImageList, RGB(255, 255, 255));
274 SetTextColor (hdcImageList, RGB(0, 0, 0));
275 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
276 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
279 /* add white mask from image */
280 SelectObject (hdcImageList, himl->hbmImage);
281 SetBkColor (hdcImageList, RGB(0, 0, 0));
282 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
283 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
286 /* draw the new mask */
287 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
288 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
289 hdcMask, 0, 0, 0xB8074A);
291 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
292 BitBlt (hdc, x, y, himl->cx, himl->cy,
293 hdcMask, 0, 0, 0xB8074A);
295 DeleteObject (hbmMask);
297 DeleteDC (hdcImageList);
302 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
304 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
305 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
306 BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
307 (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
308 RECT rc, rcArrow, rcBitmap;
310 if (btnPtr->fsState & TBSTATE_HIDDEN)
314 CopyRect (&rcArrow, &rc);
315 CopyRect(&rcBitmap, &rc);
317 FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
319 if (hasDropDownArrow)
321 if (dwStyle & TBSTYLE_FLAT)
322 rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
324 rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
325 rcArrow.left = rc.right;
328 /* Center the bitmap horizontally and vertically */
329 rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
331 if(TOOLBAR_HasText(infoPtr, btnPtr))
332 rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
334 rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
336 TRACE("iBitmap: %d\n", btnPtr->iBitmap);
339 if (btnPtr->fsStyle & TBSTYLE_SEP) {
340 /* with the FLAT style, iBitmap is the width and has already */
341 /* been taken into consideration in calculating the width */
342 /* so now we need to draw the vertical separator */
343 /* empirical tests show that iBitmap can/will be non-zero */
344 /* when drawing the vertical bar... */
345 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
346 TOOLBAR_DrawFlatSeparator (&rc, hdc);
351 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
352 if (!(dwStyle & TBSTYLE_FLAT))
354 DrawEdge (hdc, &rc, EDGE_RAISED,
355 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
356 if (hasDropDownArrow)
357 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
358 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
361 if (hasDropDownArrow)
363 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
364 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
367 if (infoPtr->himlDis &&
368 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
369 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
370 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
372 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
374 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
378 /* pressed TBSTYLE_BUTTON */
379 if (btnPtr->fsState & TBSTATE_PRESSED) {
380 if (dwStyle & TBSTYLE_FLAT)
382 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
383 if (hasDropDownArrow)
384 DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
388 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
389 if (hasDropDownArrow)
390 DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
393 if (hasDropDownArrow)
394 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
396 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
397 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
398 rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
400 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
404 /* checked TBSTYLE_CHECK */
405 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
406 (btnPtr->fsState & TBSTATE_CHECKED)) {
407 if (dwStyle & TBSTYLE_FLAT)
408 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
409 BF_RECT | BF_MIDDLE | BF_ADJUST);
411 DrawEdge (hdc, &rc, EDGE_SUNKEN,
412 BF_RECT | BF_MIDDLE | BF_ADJUST);
414 TOOLBAR_DrawPattern (hdc, &rc);
416 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
417 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
418 rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
419 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
424 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
425 DrawEdge (hdc, &rc, EDGE_RAISED,
426 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
428 TOOLBAR_DrawPattern (hdc, &rc);
429 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
430 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
435 if (dwStyle & TBSTYLE_FLAT)
439 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
440 if (hasDropDownArrow)
441 DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
445 FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
446 if (hasDropDownArrow)
447 FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
450 if (hasDropDownArrow)
451 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
453 if (btnPtr->bHot && infoPtr->himlHot &&
454 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
455 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
456 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
457 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
458 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
459 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
463 DrawEdge (hdc, &rc, EDGE_RAISED,
464 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
466 if (hasDropDownArrow)
468 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
469 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
470 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
473 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
474 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
475 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
478 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
483 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
485 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
486 TBUTTON_INFO *btnPtr;
490 /* redraw necessary buttons */
491 btnPtr = infoPtr->buttons;
492 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
494 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
495 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
500 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
502 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
503 TBUTTON_INFO *btnPtr;
510 hOldFont = SelectObject (hdc, infoPtr->hFont);
512 btnPtr = &infoPtr->buttons[index];
514 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
515 (btnPtr->iString > -1) &&
516 (btnPtr->iString < infoPtr->nNumStrings))
518 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
519 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
522 SelectObject (hdc, hOldFont);
525 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
529 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
531 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
532 TBUTTON_INFO *btnPtr;
540 btnPtr = infoPtr->buttons;
541 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
542 if(TOOLBAR_HasText(infoPtr, btnPtr))
544 TOOLBAR_MeasureString(hwnd,i,&sz);
545 if (sz.cx > lpSize->cx)
547 if (sz.cy > lpSize->cy)
552 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
555 /***********************************************************************
556 * TOOLBAR_WrapToolbar
558 * This function walks through the buttons and seperators in the
559 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
560 * wrapping should occur based on the width of the toolbar window.
561 * It does *not* calculate button placement itself. That task
562 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
563 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
564 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
568 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
570 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
571 TBUTTON_INFO *btnPtr;
574 BOOL bWrap, bButtonWrap;
576 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
577 /* no layout is necessary. Applications may use this style */
578 /* to perform their own layout on the toolbar. */
579 if( !(dwStyle & TBSTYLE_WRAPABLE) )
582 btnPtr = infoPtr->buttons;
583 x = infoPtr->nIndent;
585 /* this can get the parents width, to know how far we can extend
586 * this toolbar. We cannot use its height, as there may be multiple
587 * toolbars in a rebar control
589 GetClientRect( GetParent(hwnd), &rc );
590 infoPtr->nWidth = rc.right - rc.left;
593 for (i = 0; i < infoPtr->nNumButtons; i++ )
596 btnPtr[i].fsState &= ~TBSTATE_WRAP;
598 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
601 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
602 /* it is the actual width of the separator. This is used for */
603 /* custom controls in toolbars. */
604 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
605 cx = (btnPtr[i].iBitmap > 0) ?
606 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
608 cx = infoPtr->nButtonWidth;
610 /* Two or more adjacent separators form a separator group. */
611 /* The first separator in a group should be wrapped to the */
612 /* next row if the previous wrapping is on a button. */
614 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
615 (i + 1 < infoPtr->nNumButtons ) &&
616 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
618 btnPtr[i].fsState |= TBSTATE_WRAP;
619 x = infoPtr->nIndent;
625 /* The layout makes sure the bitmap is visible, but not the button. */
626 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
631 /* If the current button is a separator and not hidden, */
632 /* go to the next until it reaches a non separator. */
633 /* Wrap the last separator if it is before a button. */
634 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
635 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
636 i < infoPtr->nNumButtons )
642 if( bFound && i < infoPtr->nNumButtons )
645 btnPtr[i].fsState |= TBSTATE_WRAP;
646 x = infoPtr->nIndent;
650 else if ( i >= infoPtr->nNumButtons)
653 /* If the current button is not a separator, find the last */
654 /* separator and wrap it. */
655 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
657 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
658 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
662 x = infoPtr->nIndent;
663 btnPtr[j].fsState |= TBSTATE_WRAP;
669 /* If no separator available for wrapping, wrap one of */
670 /* non-hidden previous button. */
674 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
676 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
681 x = infoPtr->nIndent;
682 btnPtr[j].fsState |= TBSTATE_WRAP;
688 /* If all above failed, wrap the current button. */
691 btnPtr[i].fsState |= TBSTATE_WRAP;
693 x = infoPtr->nIndent;
694 if (btnPtr[i].fsState & TBSTYLE_SEP )
706 /***********************************************************************
707 * TOOLBAR_CalcToolbar
709 * This function calculates button and separator placement. It first
710 * calculates the button sizes, gets the toolbar window width and then
711 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
712 * on. It assigns a new location to each item and sends this location to
713 * the tooltip window if appropriate. Finally, it updates the rcBound
714 * rect and calculates the new required toolbar window height.
718 TOOLBAR_CalcToolbar (HWND hwnd)
720 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
721 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
722 TBUTTON_INFO *btnPtr;
723 INT i, nRows, nSepRows;
727 BOOL usesBitmaps = FALSE;
728 BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
730 TOOLBAR_CalcStrings (hwnd, &sizeString);
732 if (dwStyle & TBSTYLE_LIST)
734 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
735 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
738 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
740 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
744 if (sizeString.cy > 0)
747 infoPtr->nButtonHeight = sizeString.cy +
748 infoPtr->nBitmapHeight + 6;
750 infoPtr->nButtonHeight = sizeString.cy + 6;
752 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
753 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
755 if (sizeString.cx > infoPtr->nBitmapWidth)
756 infoPtr->nButtonWidth = sizeString.cx + 6;
757 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
758 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
761 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
762 infoPtr->nButtonWidth = infoPtr->cxMin;
763 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
764 infoPtr->nButtonWidth = infoPtr->cxMax;
766 TOOLBAR_WrapToolbar( hwnd, dwStyle );
768 x = infoPtr->nIndent;
769 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
772 * We will set the height below, and we set the width on entry
773 * so we do not reset them here..
776 GetClientRect( hwnd, &rc );
777 /* get initial values for toolbar */
778 infoPtr->nWidth = rc.right - rc.left;
779 infoPtr->nHeight = rc.bottom - rc.top;
782 /* from above, minimum is a button, and possible text */
783 cx = infoPtr->nButtonWidth;
785 /* cannot use just ButtonHeight, we may have no buttons! */
786 if (infoPtr->nNumButtons > 0)
787 infoPtr->nHeight = infoPtr->nButtonHeight;
789 cy = infoPtr->nHeight;
791 nRows = nSepRows = 0;
793 infoPtr->rcBound.top = y;
794 infoPtr->rcBound.left = x;
795 infoPtr->rcBound.bottom = y + cy;
796 infoPtr->rcBound.right = x;
798 btnPtr = infoPtr->buttons;
800 /* do not base height/width on parent, if the parent is a */
801 /* rebar control it could have multiple rows of toolbars */
802 /* GetClientRect( GetParent(hwnd), &rc ); */
803 /* cx = rc.right - rc.left; */
804 /* cy = rc.bottom - rc.top; */
806 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
809 if (btnPtr->fsState & TBSTATE_HIDDEN)
811 SetRectEmpty (&btnPtr->rect);
815 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
816 /* it is the actual width of the separator. This is used for */
817 /* custom controls in toolbars. */
818 if (btnPtr->fsStyle & TBSTYLE_SEP)
819 cx = (btnPtr->iBitmap > 0) ?
820 btnPtr->iBitmap : SEPARATOR_WIDTH;
823 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
826 TOOLBAR_MeasureString(hwnd,i,&sz);
830 cx = infoPtr->nButtonWidth;
832 if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
835 cy = infoPtr->nHeight;
837 if (btnPtr->fsState & TBSTATE_WRAP )
840 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
842 if (infoPtr->rcBound.left > x)
843 infoPtr->rcBound.left = x;
844 if (infoPtr->rcBound.right < x + cx)
845 infoPtr->rcBound.right = x + cx;
846 if (infoPtr->rcBound.bottom < y + cy)
847 infoPtr->rcBound.bottom = y + cy;
849 /* Set the toolTip only for non-hidden, non-separator button */
850 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
854 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
855 ti.cbSize = sizeof(TTTOOLINFOA);
857 ti.uId = btnPtr->idCommand;
858 ti.rect = btnPtr->rect;
859 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
863 /* btnPtr->nRow is zero based. The space between the rows is */
864 /* also considered as a row. */
865 btnPtr->nRow = nRows + nSepRows;
868 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
872 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
873 /* it is the actual width of the separator. This is used for */
874 /* custom controls in toolbars. */
875 y += cy + ( (btnPtr->iBitmap > 0 ) ?
876 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
878 /* nSepRows is used to calculate the extra height follwoing */
882 x = infoPtr->nIndent;
889 /* infoPtr->nRows is the number of rows on the toolbar */
890 infoPtr->nRows = nRows + nSepRows + 1;
892 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
894 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
895 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
896 nSepRows * (infoPtr->nBitmapHeight + 1) +
898 TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
903 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
905 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
906 TBUTTON_INFO *btnPtr;
909 btnPtr = infoPtr->buttons;
910 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
911 if (btnPtr->fsState & TBSTATE_HIDDEN)
914 if (btnPtr->fsStyle & TBSTYLE_SEP) {
915 if (PtInRect (&btnPtr->rect, *lpPt)) {
916 TRACE(" ON SEPARATOR %d!\n", i);
921 if (PtInRect (&btnPtr->rect, *lpPt)) {
922 TRACE(" ON BUTTON %d!\n", i);
928 TRACE(" NOWHERE!\n");
934 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
936 TBUTTON_INFO *btnPtr;
939 btnPtr = infoPtr->buttons;
940 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
941 if (btnPtr->idCommand == idCommand) {
942 TRACE("command=%d index=%d\n", idCommand, i);
946 TRACE("no index found for command=%d\n", idCommand);
952 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
954 TBUTTON_INFO *btnPtr;
957 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
960 /* check index button */
961 btnPtr = &infoPtr->buttons[nIndex];
962 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
963 if (btnPtr->fsState & TBSTATE_CHECKED)
967 /* check previous buttons */
968 nRunIndex = nIndex - 1;
969 while (nRunIndex >= 0) {
970 btnPtr = &infoPtr->buttons[nRunIndex];
971 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
972 if (btnPtr->fsState & TBSTATE_CHECKED)
980 /* check next buttons */
981 nRunIndex = nIndex + 1;
982 while (nRunIndex < infoPtr->nNumButtons) {
983 btnPtr = &infoPtr->buttons[nRunIndex];
984 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
985 if (btnPtr->fsState & TBSTATE_CHECKED)
998 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
999 WPARAM wParam, LPARAM lParam)
1005 msg.wParam = wParam;
1006 msg.lParam = lParam;
1007 msg.time = GetMessageTime ();
1008 msg.pt.x = LOWORD(GetMessagePos ());
1009 msg.pt.y = HIWORD(GetMessagePos ());
1011 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1015 /***********************************************************************
1016 * TOOLBAR_CustomizeDialogProc
1017 * This function implements the toolbar customization dialog.
1020 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1022 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
1023 static HDSA hDsa = NULL;
1028 infoPtr = (TOOLBAR_INFO *)lParam;
1029 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
1031 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
1035 TBUTTON_INFO *btnPtr;
1038 /* insert 'virtual' separator button into 'available buttons' list */
1039 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1041 /* copy all buttons and append them to the right listbox */
1042 btnPtr = infoPtr->buttons;
1043 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
1045 DSA_InsertItem (hDsa, i, btnPtr);
1047 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
1048 if (btnPtr->fsState & TBSTATE_HIDDEN)
1050 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1054 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1058 /* append 'virtual' separator button to the 'toolbar buttons' list */
1064 EndDialog(hwnd, FALSE);
1068 switch (LOWORD(wParam))
1071 EndDialog(hwnd, FALSE);
1082 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1084 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1085 TBUTTON_INFO btnPtr;
1090 COLORREF oldText = 0;
1093 FIXME("action: %x itemState: %x\n",
1094 lpdis->itemAction, lpdis->itemState);
1096 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
1098 if (lpdis->itemState & ODS_FOCUS)
1100 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
1101 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
1104 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1105 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1107 /* fill background rectangle */
1108 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1109 lpdis->rcItem.right, lpdis->rcItem.bottom);
1111 /* calculate button and text rectangles */
1112 CopyRect (&rcButton, &lpdis->rcItem);
1113 InflateRect (&rcButton, -1, -1);
1114 CopyRect (&rcText, &rcButton);
1115 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
1116 rcText.left = rcButton.right + 2;
1118 /* draw focus rectangle */
1119 if (lpdis->itemState & ODS_FOCUS)
1120 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1123 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1125 /* draw image and text */
1126 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
1128 /* virtual separator in the 'available' list */
1129 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
1130 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1136 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
1137 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
1139 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
1140 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1144 if (lpdis->itemState & ODS_FOCUS)
1146 SetBkColor (lpdis->hDC, oldBk);
1147 SetTextColor (lpdis->hDC, oldText);
1150 SelectObject (lpdis->hDC, hOldBrush);
1151 SelectObject (lpdis->hDC, hOldPen);
1157 case WM_MEASUREITEM:
1158 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1160 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1163 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
1165 lpmis->itemHeight = 15 + 8; /* default height */
1177 /***********************************************************************
1178 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1182 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1184 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1185 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1186 INT nIndex = 0, nButtons, nCount;
1189 TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1193 if (lpAddBmp->hInst == HINST_COMMCTRL)
1195 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1197 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1199 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1204 TRACE ("adding %d internal bitmaps!\n", nButtons);
1206 /* Windows resize all the buttons to the size of a newly added standard image */
1207 if (lpAddBmp->nID & 1)
1210 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
1211 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
1213 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1214 MAKELPARAM((WORD)24, (WORD)24));
1215 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1216 MAKELPARAM((WORD)31, (WORD)30));
1221 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1222 MAKELPARAM((WORD)16, (WORD)16));
1223 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1224 MAKELPARAM((WORD)22, (WORD)22));
1227 TOOLBAR_CalcToolbar (hwnd);
1231 nButtons = (INT)wParam;
1235 TRACE ("adding %d bitmaps!\n", nButtons);
1238 if (!(infoPtr->himlDef)) {
1239 /* create new default image list */
1240 TRACE ("creating default image list!\n");
1243 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1244 ILC_COLOR | ILC_MASK, nButtons, 2);
1245 infoPtr->himlInt = infoPtr->himlDef;
1248 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1250 /* Add bitmaps to the default image list */
1251 if (lpAddBmp->hInst == (HINSTANCE)0)
1254 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1257 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1259 /* Add system bitmaps */
1260 switch (lpAddBmp->nID)
1262 case IDB_STD_SMALL_COLOR:
1263 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1264 MAKEINTRESOURCEA(IDB_STD_SMALL));
1265 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1266 hbmLoad, CLR_DEFAULT);
1267 DeleteObject (hbmLoad);
1270 case IDB_STD_LARGE_COLOR:
1271 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1272 MAKEINTRESOURCEA(IDB_STD_LARGE));
1273 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1274 hbmLoad, CLR_DEFAULT);
1275 DeleteObject (hbmLoad);
1278 case IDB_VIEW_SMALL_COLOR:
1279 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1280 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1281 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1282 hbmLoad, CLR_DEFAULT);
1283 DeleteObject (hbmLoad);
1286 case IDB_VIEW_LARGE_COLOR:
1287 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1288 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1289 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1290 hbmLoad, CLR_DEFAULT);
1291 DeleteObject (hbmLoad);
1294 case IDB_HIST_SMALL_COLOR:
1295 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1296 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1297 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1298 hbmLoad, CLR_DEFAULT);
1299 DeleteObject (hbmLoad);
1302 case IDB_HIST_LARGE_COLOR:
1303 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1304 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1305 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1306 hbmLoad, CLR_DEFAULT);
1307 DeleteObject (hbmLoad);
1311 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1312 ERR ("invalid imagelist!\n");
1318 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1319 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1320 DeleteObject (hbmLoad);
1325 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1327 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1329 WARN("Desired images do not match received images : Previous image number %i Previous images in list %i added %i expecting total %i, Images in list %i\n",
1330 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1331 infoPtr->nNumBitmaps+nButtons,imagecount);
1333 infoPtr->nNumBitmaps = imagecount;
1336 infoPtr->nNumBitmaps += nButtons;
1344 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1346 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1347 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1348 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1350 TRACE("adding %d buttons!\n", wParam);
1352 nAddButtons = (UINT)wParam;
1353 nOldButtons = infoPtr->nNumButtons;
1354 nNewButtons = nOldButtons + nAddButtons;
1356 if (infoPtr->nNumButtons == 0) {
1358 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1361 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1363 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1364 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1365 nOldButtons * sizeof(TBUTTON_INFO));
1366 COMCTL32_Free (oldButtons);
1369 infoPtr->nNumButtons = nNewButtons;
1371 /* insert new button data */
1372 for (nCount = 0; nCount < nAddButtons; nCount++) {
1373 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1374 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1375 btnPtr->idCommand = lpTbb[nCount].idCommand;
1376 btnPtr->fsState = lpTbb[nCount].fsState;
1377 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1378 btnPtr->dwData = lpTbb[nCount].dwData;
1379 btnPtr->iString = lpTbb[nCount].iString;
1380 btnPtr->bHot = FALSE;
1382 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1385 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1386 ti.cbSize = sizeof (TTTOOLINFOA);
1388 ti.uId = btnPtr->idCommand;
1390 ti.lpszText = LPSTR_TEXTCALLBACKA;
1392 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1397 TOOLBAR_CalcToolbar (hwnd);
1399 InvalidateRect(hwnd, NULL, FALSE);
1406 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1408 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1409 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1410 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1412 TRACE("adding %d buttons!\n", wParam);
1414 nAddButtons = (UINT)wParam;
1415 nOldButtons = infoPtr->nNumButtons;
1416 nNewButtons = nOldButtons + nAddButtons;
1418 if (infoPtr->nNumButtons == 0) {
1420 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1423 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1425 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1426 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1427 nOldButtons * sizeof(TBUTTON_INFO));
1428 COMCTL32_Free (oldButtons);
1431 infoPtr->nNumButtons = nNewButtons;
1433 /* insert new button data */
1434 for (nCount = 0; nCount < nAddButtons; nCount++) {
1435 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1436 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1437 btnPtr->idCommand = lpTbb[nCount].idCommand;
1438 btnPtr->fsState = lpTbb[nCount].fsState;
1439 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1440 btnPtr->dwData = lpTbb[nCount].dwData;
1441 btnPtr->iString = lpTbb[nCount].iString;
1442 btnPtr->bHot = FALSE;
1444 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1447 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1448 ti.cbSize = sizeof (TTTOOLINFOW);
1450 ti.uId = btnPtr->idCommand;
1452 ti.lpszText = LPSTR_TEXTCALLBACKW;
1454 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1459 TOOLBAR_CalcToolbar (hwnd);
1461 InvalidateRect(hwnd, NULL, FALSE);
1468 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1470 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1473 if ((wParam) && (HIWORD(lParam) == 0)) {
1476 TRACE("adding string from resource!\n");
1478 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1481 TRACE("len=%d \"%s\"\n", len, szString);
1482 nIndex = infoPtr->nNumStrings;
1483 if (infoPtr->nNumStrings == 0) {
1485 COMCTL32_Alloc (sizeof(LPWSTR));
1488 LPWSTR *oldStrings = infoPtr->strings;
1490 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1491 memcpy (&infoPtr->strings[0], &oldStrings[0],
1492 sizeof(LPWSTR) * infoPtr->nNumStrings);
1493 COMCTL32_Free (oldStrings);
1496 infoPtr->strings[infoPtr->nNumStrings] =
1497 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1498 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1499 infoPtr->nNumStrings++;
1502 LPSTR p = (LPSTR)lParam;
1507 TRACE("adding string(s) from array!\n");
1509 nIndex = infoPtr->nNumStrings;
1512 TRACE("len=%d \"%s\"\n", len, p);
1514 if (infoPtr->nNumStrings == 0) {
1516 COMCTL32_Alloc (sizeof(LPWSTR));
1519 LPWSTR *oldStrings = infoPtr->strings;
1521 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1522 memcpy (&infoPtr->strings[0], &oldStrings[0],
1523 sizeof(LPWSTR) * infoPtr->nNumStrings);
1524 COMCTL32_Free (oldStrings);
1527 infoPtr->strings[infoPtr->nNumStrings] =
1528 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1529 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1530 infoPtr->nNumStrings++;
1541 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1543 #define MAX_RESOURCE_STRING_LENGTH 512
1544 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1547 if ((wParam) && (HIWORD(lParam) == 0)) {
1548 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1550 TRACE("adding string from resource!\n");
1552 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1553 szString, MAX_RESOURCE_STRING_LENGTH);
1555 TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1556 TRACE("First char: 0x%x\n", *szString);
1557 if (szString[0] == L'|')
1559 PWSTR p = szString + 1;
1561 nIndex = infoPtr->nNumStrings;
1562 while (*p != L'|') {
1564 if (infoPtr->nNumStrings == 0) {
1566 COMCTL32_Alloc (sizeof(LPWSTR));
1569 LPWSTR *oldStrings = infoPtr->strings;
1571 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1572 memcpy (&infoPtr->strings[0], &oldStrings[0],
1573 sizeof(LPWSTR) * infoPtr->nNumStrings);
1574 COMCTL32_Free (oldStrings);
1577 len = COMCTL32_StrChrW (p, L'|') - p;
1578 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1579 infoPtr->strings[infoPtr->nNumStrings] =
1580 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1581 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1582 infoPtr->nNumStrings++;
1589 nIndex = infoPtr->nNumStrings;
1590 if (infoPtr->nNumStrings == 0) {
1592 COMCTL32_Alloc (sizeof(LPWSTR));
1595 LPWSTR *oldStrings = infoPtr->strings;
1597 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1598 memcpy (&infoPtr->strings[0], &oldStrings[0],
1599 sizeof(LPWSTR) * infoPtr->nNumStrings);
1600 COMCTL32_Free (oldStrings);
1603 infoPtr->strings[infoPtr->nNumStrings] =
1604 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1605 strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1606 infoPtr->nNumStrings++;
1610 LPWSTR p = (LPWSTR)lParam;
1615 TRACE("adding string(s) from array!\n");
1616 nIndex = infoPtr->nNumStrings;
1620 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1621 if (infoPtr->nNumStrings == 0) {
1623 COMCTL32_Alloc (sizeof(LPWSTR));
1626 LPWSTR *oldStrings = infoPtr->strings;
1628 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1629 memcpy (&infoPtr->strings[0], &oldStrings[0],
1630 sizeof(LPWSTR) * infoPtr->nNumStrings);
1631 COMCTL32_Free (oldStrings);
1634 infoPtr->strings[infoPtr->nNumStrings] =
1635 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1636 strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1637 infoPtr->nNumStrings++;
1648 TOOLBAR_AutoSize (HWND hwnd)
1650 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1651 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1657 UINT uPosFlags = SWP_NOZORDER;
1659 TRACE("resize forced, style=%lx!\n", dwStyle);
1661 parent = GetParent (hwnd);
1662 GetClientRect(parent, &parent_rect);
1664 x = parent_rect.left;
1665 y = parent_rect.top;
1667 /* FIXME: we should be able to early out if nothing */
1668 /* has changed with nWidth != parent_rect width */
1670 if (dwStyle & CCS_NORESIZE) {
1671 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1676 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1677 TOOLBAR_CalcToolbar (hwnd);
1678 InvalidateRect( hwnd, NULL, TRUE );
1679 cy = infoPtr->nHeight;
1680 cx = infoPtr->nWidth;
1682 if (dwStyle & CCS_NOMOVEY) {
1683 GetWindowRect(hwnd, &window_rect);
1684 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1685 y = window_rect.top;
1689 if (dwStyle & CCS_NOPARENTALIGN)
1690 uPosFlags |= SWP_NOMOVE;
1692 if (!(dwStyle & CCS_NODIVIDER))
1693 cy += GetSystemMetrics(SM_CYEDGE);
1695 if (dwStyle & WS_BORDER)
1698 cy += GetSystemMetrics(SM_CYEDGE);
1699 cx += GetSystemMetrics(SM_CYEDGE);
1702 infoPtr->bAutoSize = TRUE;
1703 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1705 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1706 * the setwindowpos calls */
1707 infoPtr->bAutoSize = FALSE;
1714 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1716 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1718 return infoPtr->nNumButtons;
1723 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1725 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1727 if (infoPtr == NULL) {
1728 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1729 ERR("infoPtr == NULL!\n");
1733 infoPtr->dwStructSize = (DWORD)wParam;
1740 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1742 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1743 TBUTTON_INFO *btnPtr;
1746 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1750 btnPtr = &infoPtr->buttons[nIndex];
1751 btnPtr->iBitmap = LOWORD(lParam);
1753 /* we HAVE to erase the background, the new bitmap could be */
1755 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1762 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1764 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1765 TBUTTON_INFO *btnPtr;
1768 BOOL bChecked = FALSE;
1770 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1774 btnPtr = &infoPtr->buttons[nIndex];
1776 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1779 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1781 if (LOWORD(lParam) == FALSE)
1782 btnPtr->fsState &= ~TBSTATE_CHECKED;
1784 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1786 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1787 if (nOldIndex == nIndex)
1789 if (nOldIndex != -1)
1790 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1792 btnPtr->fsState |= TBSTATE_CHECKED;
1795 if( bChecked != LOWORD(lParam) )
1797 if (nOldIndex != -1)
1799 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
1800 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
1802 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1805 /* FIXME: Send a WM_NOTIFY?? */
1812 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1814 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1816 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1821 TOOLBAR_Customize (HWND hwnd)
1823 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1829 /* send TBN_BEGINADJUST notification */
1830 nmhdr.hwndFrom = hwnd;
1831 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1832 nmhdr.code = TBN_BEGINADJUST;
1834 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1835 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1837 if (!(hRes = FindResourceA (COMCTL32_hModule,
1838 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1842 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1845 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1846 (LPDLGTEMPLATEA)template,
1848 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1851 /* send TBN_ENDADJUST notification */
1852 nmhdr.code = TBN_ENDADJUST;
1854 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1855 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1862 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1864 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1865 INT nIndex = (INT)wParam;
1867 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1870 if ((infoPtr->hwndToolTip) &&
1871 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1874 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1875 ti.cbSize = sizeof (TTTOOLINFOA);
1877 ti.uId = infoPtr->buttons[nIndex].idCommand;
1879 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1882 if (infoPtr->nNumButtons == 1) {
1883 TRACE(" simple delete!\n");
1884 COMCTL32_Free (infoPtr->buttons);
1885 infoPtr->buttons = NULL;
1886 infoPtr->nNumButtons = 0;
1889 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1890 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1892 infoPtr->nNumButtons--;
1893 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1895 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1896 nIndex * sizeof(TBUTTON_INFO));
1899 if (nIndex < infoPtr->nNumButtons) {
1900 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1901 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1904 COMCTL32_Free (oldButtons);
1907 TOOLBAR_CalcToolbar (hwnd);
1909 InvalidateRect (hwnd, NULL, TRUE);
1916 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1918 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1919 TBUTTON_INFO *btnPtr;
1923 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1927 btnPtr = &infoPtr->buttons[nIndex];
1929 bState = btnPtr->fsState & TBSTATE_ENABLED;
1931 /* update the toolbar button state */
1932 if(LOWORD(lParam) == FALSE) {
1933 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1935 btnPtr->fsState |= TBSTATE_ENABLED;
1938 /* redraw the button only if the state of the button changed */
1939 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
1941 InvalidateRect(hwnd, &btnPtr->rect,
1942 TOOLBAR_HasText(infoPtr, btnPtr));
1949 static inline LRESULT
1950 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1952 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1954 return infoPtr->bAnchor;
1959 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1961 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1964 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1968 return infoPtr->buttons[nIndex].iBitmap;
1972 static inline LRESULT
1973 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1975 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1980 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1982 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1983 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1984 INT nIndex = (INT)wParam;
1985 TBUTTON_INFO *btnPtr;
1987 if (infoPtr == NULL)
1993 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1996 btnPtr = &infoPtr->buttons[nIndex];
1997 lpTbb->iBitmap = btnPtr->iBitmap;
1998 lpTbb->idCommand = btnPtr->idCommand;
1999 lpTbb->fsState = btnPtr->fsState;
2000 lpTbb->fsStyle = btnPtr->fsStyle;
2001 lpTbb->dwData = btnPtr->dwData;
2002 lpTbb->iString = btnPtr->iString;
2009 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2011 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2012 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2013 TBUTTON_INFO *btnPtr;
2016 if (infoPtr == NULL)
2018 if (lpTbInfo == NULL)
2020 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2023 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2027 btnPtr = &infoPtr->buttons[nIndex];
2029 if (lpTbInfo->dwMask & TBIF_COMMAND)
2030 lpTbInfo->idCommand = btnPtr->idCommand;
2031 if (lpTbInfo->dwMask & TBIF_IMAGE)
2032 lpTbInfo->iImage = btnPtr->iBitmap;
2033 if (lpTbInfo->dwMask & TBIF_LPARAM)
2034 lpTbInfo->lParam = btnPtr->dwData;
2035 if (lpTbInfo->dwMask & TBIF_SIZE)
2036 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2037 if (lpTbInfo->dwMask & TBIF_STATE)
2038 lpTbInfo->fsState = btnPtr->fsState;
2039 if (lpTbInfo->dwMask & TBIF_STYLE)
2040 lpTbInfo->fsStyle = btnPtr->fsStyle;
2041 if (lpTbInfo->dwMask & TBIF_TEXT) {
2042 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2044 lstrcpynWtoA (lpTbInfo->pszText,
2045 (LPWSTR)infoPtr->strings[btnPtr->iString],
2048 else lpTbInfo->pszText[0]=0;
2055 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2057 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2058 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2059 TBUTTON_INFO *btnPtr;
2062 if (infoPtr == NULL)
2064 if (lpTbInfo == NULL)
2066 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2069 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2073 btnPtr = &infoPtr->buttons[nIndex];
2075 if (lpTbInfo->dwMask & TBIF_COMMAND)
2076 lpTbInfo->idCommand = btnPtr->idCommand;
2077 if (lpTbInfo->dwMask & TBIF_IMAGE)
2078 lpTbInfo->iImage = btnPtr->iBitmap;
2079 if (lpTbInfo->dwMask & TBIF_LPARAM)
2080 lpTbInfo->lParam = btnPtr->dwData;
2081 if (lpTbInfo->dwMask & TBIF_SIZE)
2082 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2083 if (lpTbInfo->dwMask & TBIF_STATE)
2084 lpTbInfo->fsState = btnPtr->fsState;
2085 if (lpTbInfo->dwMask & TBIF_STYLE)
2086 lpTbInfo->fsStyle = btnPtr->fsStyle;
2087 if (lpTbInfo->dwMask & TBIF_TEXT) {
2088 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2089 lstrcpynW (lpTbInfo->pszText,
2090 (LPWSTR)infoPtr->strings[btnPtr->iString],
2099 TOOLBAR_GetButtonSize (HWND hwnd)
2101 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2103 return MAKELONG((WORD)infoPtr->nButtonWidth,
2104 (WORD)infoPtr->nButtonHeight);
2109 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2111 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2112 INT nIndex, nStringIndex;
2114 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2118 nStringIndex = infoPtr->buttons[nIndex].iString;
2120 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2122 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2128 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2130 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2135 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2137 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2138 INT nIndex, nStringIndex;
2140 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2144 nStringIndex = infoPtr->buttons[nIndex].iString;
2146 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2148 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2154 strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2156 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2160 /* << TOOLBAR_GetColorScheme >> */
2164 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2166 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2168 return (LRESULT)infoPtr->himlDis;
2172 inline static LRESULT
2173 TOOLBAR_GetExtendedStyle (HWND hwnd)
2175 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2177 return infoPtr->dwExStyle;
2182 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2184 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2186 return (LRESULT)infoPtr->himlHot;
2191 TOOLBAR_GetHotItem (HWND hwnd)
2193 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2195 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2198 if (infoPtr->nHotItem < 0)
2201 return (LRESULT)infoPtr->nHotItem;
2206 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2208 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2210 return (LRESULT)infoPtr->himlDef;
2214 /* << TOOLBAR_GetInsertMark >> */
2215 /* << TOOLBAR_GetInsertMarkColor >> */
2219 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2221 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2222 TBUTTON_INFO *btnPtr;
2226 if (infoPtr == NULL)
2228 nIndex = (INT)wParam;
2229 btnPtr = &infoPtr->buttons[nIndex];
2230 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2232 lpRect = (LPRECT)lParam;
2235 if (btnPtr->fsState & TBSTATE_HIDDEN)
2238 lpRect->left = btnPtr->rect.left;
2239 lpRect->right = btnPtr->rect.right;
2240 lpRect->bottom = btnPtr->rect.bottom;
2241 lpRect->top = btnPtr->rect.top;
2248 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2250 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2251 LPSIZE lpSize = (LPSIZE)lParam;
2256 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2257 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2259 TRACE("maximum size %d x %d\n",
2260 infoPtr->rcBound.right - infoPtr->rcBound.left,
2261 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2267 /* << TOOLBAR_GetObject >> */
2268 /* << TOOLBAR_GetPadding >> */
2272 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2274 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2275 TBUTTON_INFO *btnPtr;
2279 if (infoPtr == NULL)
2281 nIndex = (INT)wParam;
2282 btnPtr = &infoPtr->buttons[nIndex];
2283 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2285 lpRect = (LPRECT)lParam;
2289 lpRect->left = btnPtr->rect.left;
2290 lpRect->right = btnPtr->rect.right;
2291 lpRect->bottom = btnPtr->rect.bottom;
2292 lpRect->top = btnPtr->rect.top;
2299 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2301 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2303 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2304 return infoPtr->nRows;
2311 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2313 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2316 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2320 return infoPtr->buttons[nIndex].fsState;
2325 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2327 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2330 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2334 return infoPtr->buttons[nIndex].fsStyle;
2339 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2341 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2343 if (infoPtr == NULL)
2346 return infoPtr->nMaxTextRows;
2351 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2353 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2355 if (infoPtr == NULL)
2357 return infoPtr->hwndToolTip;
2362 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2364 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2366 TRACE("%s hwnd=0x%x stub!\n",
2367 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2369 return infoPtr->bUnicode;
2373 inline static LRESULT
2374 TOOLBAR_GetVersion (HWND hwnd)
2376 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2377 return infoPtr->iVersion;
2382 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2384 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2385 TBUTTON_INFO *btnPtr;
2390 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2394 btnPtr = &infoPtr->buttons[nIndex];
2395 if (LOWORD(lParam) == FALSE)
2396 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2398 btnPtr->fsState |= TBSTATE_HIDDEN;
2400 TOOLBAR_CalcToolbar (hwnd);
2402 InvalidateRect (hwnd, NULL, TRUE);
2408 inline static LRESULT
2409 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2411 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2416 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2418 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2419 TBUTTON_INFO *btnPtr;
2422 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2426 btnPtr = &infoPtr->buttons[nIndex];
2427 if (LOWORD(lParam) == FALSE)
2428 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2430 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2432 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2439 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2441 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2442 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2443 INT nIndex = (INT)wParam;
2444 TBUTTON_INFO *oldButtons;
2450 /* EPP: this seems to be an undocumented call (from my IE4)
2451 * I assume in that case that:
2452 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2453 * - index of insertion is at the end of existing buttons
2454 * I only see this happen with nIndex == -1, but it could have a special
2455 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2460 if(lpTbb->iString) {
2461 len = lstrlenA((char*)lpTbb->iString) + 2;
2462 ptr = COMCTL32_Alloc(len);
2463 nIndex = infoPtr->nNumButtons;
2464 strcpy(ptr, (char*)lpTbb->iString);
2465 ptr[len - 1] = 0; /* ended by two '\0' */
2466 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2470 ERR("lpTbb->iString is NULL\n");
2474 } else if (nIndex < 0)
2477 TRACE("inserting button index=%d\n", nIndex);
2478 if (nIndex > infoPtr->nNumButtons) {
2479 nIndex = infoPtr->nNumButtons;
2480 TRACE("adjust index=%d\n", nIndex);
2483 oldButtons = infoPtr->buttons;
2484 infoPtr->nNumButtons++;
2485 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2486 /* pre insert copy */
2488 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2489 nIndex * sizeof(TBUTTON_INFO));
2492 /* insert new button */
2493 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2494 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2495 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2496 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2497 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2498 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2500 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2503 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2504 ti.cbSize = sizeof (TTTOOLINFOA);
2506 ti.uId = lpTbb->idCommand;
2508 ti.lpszText = LPSTR_TEXTCALLBACKA;
2510 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2514 /* post insert copy */
2515 if (nIndex < infoPtr->nNumButtons - 1) {
2516 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2517 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2520 COMCTL32_Free (oldButtons);
2522 TOOLBAR_CalcToolbar (hwnd);
2524 InvalidateRect (hwnd, NULL, FALSE);
2531 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2533 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2534 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2535 INT nIndex = (INT)wParam;
2536 TBUTTON_INFO *oldButtons;
2543 TRACE("inserting button index=%d\n", nIndex);
2544 if (nIndex > infoPtr->nNumButtons) {
2545 nIndex = infoPtr->nNumButtons;
2546 TRACE("adjust index=%d\n", nIndex);
2549 oldButtons = infoPtr->buttons;
2550 infoPtr->nNumButtons++;
2551 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2552 /* pre insert copy */
2554 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2555 nIndex * sizeof(TBUTTON_INFO));
2558 /* insert new button */
2559 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2560 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2561 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2562 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2563 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2564 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2566 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2569 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2570 ti.cbSize = sizeof (TTTOOLINFOW);
2572 ti.uId = lpTbb->idCommand;
2574 ti.lpszText = LPSTR_TEXTCALLBACKW;
2576 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2580 /* post insert copy */
2581 if (nIndex < infoPtr->nNumButtons - 1) {
2582 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2583 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2586 COMCTL32_Free (oldButtons);
2588 TOOLBAR_CalcToolbar (hwnd);
2590 InvalidateRect (hwnd, NULL, FALSE);
2596 /* << TOOLBAR_InsertMarkHitTest >> */
2600 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2602 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2605 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2609 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2614 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2616 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2619 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2623 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2628 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2630 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2633 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2637 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2642 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2644 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2647 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2651 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2656 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2658 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2661 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2665 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2670 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2675 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2679 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2683 /* << TOOLBAR_LoadImages >> */
2684 /* << TOOLBAR_MapAccelerator >> */
2685 /* << TOOLBAR_MarkButton >> */
2686 /* << TOOLBAR_MoveButton >> */
2690 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2692 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2693 TBUTTON_INFO *btnPtr;
2696 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2700 btnPtr = &infoPtr->buttons[nIndex];
2701 if (LOWORD(lParam) == FALSE)
2702 btnPtr->fsState &= ~TBSTATE_PRESSED;
2704 btnPtr->fsState |= TBSTATE_PRESSED;
2706 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2712 /* << TOOLBAR_ReplaceBitmap >> */
2716 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2719 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2720 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2722 if (lpSave == NULL) return 0;
2725 /* save toolbar information */
2726 FIXME("save to \"%s\" \"%s\"\n",
2727 lpSave->pszSubKey, lpSave->pszValueName);
2732 /* restore toolbar information */
2734 FIXME("restore from \"%s\" \"%s\"\n",
2735 lpSave->pszSubKey, lpSave->pszValueName);
2746 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2749 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2750 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2756 /* save toolbar information */
2757 FIXME("save to \"%s\" \"%s\"\n",
2758 lpSave->pszSubKey, lpSave->pszValueName);
2763 /* restore toolbar information */
2765 FIXME("restore from \"%s\" \"%s\"\n",
2766 lpSave->pszSubKey, lpSave->pszValueName);
2777 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2779 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2780 BOOL bOldAnchor = infoPtr->bAnchor;
2782 infoPtr->bAnchor = (BOOL)wParam;
2784 return (LRESULT)bOldAnchor;
2789 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2791 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2793 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2796 if (infoPtr->nNumButtons > 0)
2797 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
2798 infoPtr->nNumButtons,
2799 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
2800 LOWORD(lParam), HIWORD(lParam));
2802 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2803 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2805 /* uses image list internals directly */
2806 if (infoPtr->himlDef) {
2807 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
2808 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
2816 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2818 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2819 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2820 TBUTTON_INFO *btnPtr;
2825 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2828 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2832 btnPtr = &infoPtr->buttons[nIndex];
2833 if (lptbbi->dwMask & TBIF_COMMAND)
2834 btnPtr->idCommand = lptbbi->idCommand;
2835 if (lptbbi->dwMask & TBIF_IMAGE)
2836 btnPtr->iBitmap = lptbbi->iImage;
2837 if (lptbbi->dwMask & TBIF_LPARAM)
2838 btnPtr->dwData = lptbbi->lParam;
2839 /* if (lptbbi->dwMask & TBIF_SIZE) */
2840 /* btnPtr->cx = lptbbi->cx; */
2841 if (lptbbi->dwMask & TBIF_STATE)
2842 btnPtr->fsState = lptbbi->fsState;
2843 if (lptbbi->dwMask & TBIF_STYLE)
2844 btnPtr->fsStyle = lptbbi->fsStyle;
2846 if (lptbbi->dwMask & TBIF_TEXT) {
2847 if ((btnPtr->iString >= 0) ||
2848 (btnPtr->iString < infoPtr->nNumStrings)) {
2849 TRACE("Ooooooch\n");
2851 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2852 INT len = lstrlenA (lptbbi->pszText);
2853 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2856 /* this is the ultimate sollution */
2857 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2866 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2868 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2869 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2870 TBUTTON_INFO *btnPtr;
2875 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2878 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2882 btnPtr = &infoPtr->buttons[nIndex];
2883 if (lptbbi->dwMask & TBIF_COMMAND)
2884 btnPtr->idCommand = lptbbi->idCommand;
2885 if (lptbbi->dwMask & TBIF_IMAGE)
2886 btnPtr->iBitmap = lptbbi->iImage;
2887 if (lptbbi->dwMask & TBIF_LPARAM)
2888 btnPtr->dwData = lptbbi->lParam;
2889 /* if (lptbbi->dwMask & TBIF_SIZE) */
2890 /* btnPtr->cx = lptbbi->cx; */
2891 if (lptbbi->dwMask & TBIF_STATE)
2892 btnPtr->fsState = lptbbi->fsState;
2893 if (lptbbi->dwMask & TBIF_STYLE)
2894 btnPtr->fsStyle = lptbbi->fsStyle;
2896 if (lptbbi->dwMask & TBIF_TEXT) {
2897 if ((btnPtr->iString >= 0) ||
2898 (btnPtr->iString < infoPtr->nNumStrings)) {
2900 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2901 INT len = lstrlenW (lptbbi->pszText);
2902 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2905 /* this is the ultimate solution */
2906 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2915 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2917 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2919 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2921 ERR("invalid parameter\n");
2925 /* Button size can only be set before adding any button to the toolbar
2926 according to the documentation. */
2927 /* this appears to be wrong. WINZIP32.EXE (ver 8) calls this on
2928 one of its buttons after adding it to the toolbar, and it
2929 checks that the return value is nonzero - mjm */
2930 if( infoPtr->nNumButtons != 0 )
2932 WARN("Button size set after button in toolbar\n");
2936 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2937 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2943 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2945 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2947 if (infoPtr == NULL)
2950 infoPtr->cxMin = (INT)LOWORD(lParam);
2951 infoPtr->cxMax = (INT)HIWORD(lParam);
2958 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2960 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2961 INT nIndex = (INT)wParam;
2963 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2966 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2968 if (infoPtr->hwndToolTip) {
2970 FIXME("change tool tip!\n");
2978 /* << TOOLBAR_SetColorScheme >> */
2982 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2984 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2985 HIMAGELIST himlTemp;
2988 himlTemp = infoPtr->himlDis;
2989 infoPtr->himlDis = (HIMAGELIST)lParam;
2991 /* FIXME: redraw ? */
2993 return (LRESULT)himlTemp;
2998 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
3000 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3003 dwTemp = infoPtr->dwDTFlags;
3004 infoPtr->dwDTFlags =
3005 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
3007 return (LRESULT)dwTemp;
3012 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3014 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3017 dwTemp = infoPtr->dwExStyle;
3018 infoPtr->dwExStyle = (DWORD)lParam;
3020 return (LRESULT)dwTemp;
3025 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3027 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3028 HIMAGELIST himlTemp;
3030 himlTemp = infoPtr->himlHot;
3031 infoPtr->himlHot = (HIMAGELIST)lParam;
3033 /* FIXME: redraw ? */
3035 return (LRESULT)himlTemp;
3040 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3042 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3043 INT nOldHotItem = infoPtr->nHotItem;
3045 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3047 infoPtr->nHotItem = (INT)wParam;
3049 /* FIXME: What else must be done ??? */
3053 if (nOldHotItem < 0)
3056 return (LRESULT)nOldHotItem;
3061 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3063 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3064 HIMAGELIST himlTemp;
3066 himlTemp = infoPtr->himlDef;
3067 infoPtr->himlDef = (HIMAGELIST)lParam;
3069 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3070 /* FIXME: redraw ? */
3072 return (LRESULT)himlTemp;
3077 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3079 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3083 /* process only on indent changing */
3084 if(infoPtr->nIndent != (INT)wParam)
3086 infoPtr->nIndent = (INT)wParam;
3087 TOOLBAR_CalcToolbar (hwnd);
3088 InvalidateRect(hwnd, NULL, FALSE);
3095 /* << TOOLBAR_SetInsertMark >> */
3099 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3101 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3103 infoPtr->clrInsertMark = (COLORREF)lParam;
3105 /* FIXME : redraw ??*/
3112 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3114 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3116 if (infoPtr == NULL)
3119 infoPtr->nMaxTextRows = (INT)wParam;
3125 /* << TOOLBAR_SetPadding >> */
3129 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3131 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3136 if (infoPtr == NULL)
3138 hwndOldNotify = infoPtr->hwndNotify;
3139 infoPtr->hwndNotify = (HWND)wParam;
3141 return hwndOldNotify;
3146 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3148 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3149 LPRECT lprc = (LPRECT)lParam;
3153 if (LOWORD(wParam) > 1) {
3154 FIXME("multiple rows not supported!\n");
3157 if(infoPtr->nRows != LOWORD(wParam))
3159 infoPtr->nRows = LOWORD(wParam);
3161 /* recalculate toolbar */
3162 TOOLBAR_CalcToolbar (hwnd);
3164 /* repaint toolbar */
3165 InvalidateRect(hwnd, NULL, FALSE);
3168 /* return bounding rectangle */
3170 lprc->left = infoPtr->rcBound.left;
3171 lprc->right = infoPtr->rcBound.right;
3172 lprc->top = infoPtr->rcBound.top;
3173 lprc->bottom = infoPtr->rcBound.bottom;
3181 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3183 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3184 TBUTTON_INFO *btnPtr;
3187 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3191 btnPtr = &infoPtr->buttons[nIndex];
3193 /* process state changing if current state doesn't match new state */
3194 if(btnPtr->fsState != LOWORD(lParam))
3196 btnPtr->fsState = LOWORD(lParam);
3197 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3206 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3208 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3209 TBUTTON_INFO *btnPtr;
3212 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3216 btnPtr = &infoPtr->buttons[nIndex];
3218 /* process style change if current style doesn't match new style */
3219 if(btnPtr->fsStyle != LOWORD(lParam))
3221 btnPtr->fsStyle = LOWORD(lParam);
3222 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3225 if (infoPtr->hwndToolTip) {
3226 FIXME("change tool tip!\n");
3234 inline static LRESULT
3235 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3237 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3239 if (infoPtr == NULL)
3241 infoPtr->hwndToolTip = (HWND)wParam;
3247 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3249 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3252 TRACE("%s hwnd=0x%04x stub!\n",
3253 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3255 bTemp = infoPtr->bUnicode;
3256 infoPtr->bUnicode = (BOOL)wParam;
3263 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3265 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3266 INT iOldVersion = infoPtr->iVersion;
3268 infoPtr->iVersion = iVersion;
3275 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3277 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3278 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3281 /* initialize info structure */
3282 infoPtr->nButtonHeight = 22;
3283 infoPtr->nButtonWidth = 24;
3284 infoPtr->nBitmapHeight = 15;
3285 infoPtr->nBitmapWidth = 16;
3287 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3289 infoPtr->nMaxTextRows = 1;
3290 infoPtr->cxMin = -1;
3291 infoPtr->cxMax = -1;
3292 infoPtr->nNumBitmaps = 0;
3293 infoPtr->nNumStrings = 0;
3295 infoPtr->bCaptured = FALSE;
3296 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3297 infoPtr->nButtonDown = -1;
3298 infoPtr->nOldHit = -1;
3299 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3300 infoPtr->hwndNotify = GetParent (hwnd);
3301 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3302 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3303 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3304 infoPtr->iVersion = 0;
3306 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3307 infoPtr->hFont = CreateFontIndirectA (&logFont);
3309 if (dwStyle & TBSTYLE_TOOLTIPS) {
3310 /* Create tooltip control */
3311 infoPtr->hwndToolTip =
3312 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3313 CW_USEDEFAULT, CW_USEDEFAULT,
3314 CW_USEDEFAULT, CW_USEDEFAULT,
3317 /* Send NM_TOOLTIPSCREATED notification */
3318 if (infoPtr->hwndToolTip) {
3319 NMTOOLTIPSCREATED nmttc;
3321 nmttc.hdr.hwndFrom = hwnd;
3322 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3323 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3324 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3326 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3327 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3331 TOOLBAR_CalcToolbar(hwnd);
3338 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3340 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3342 /* delete tooltip control */
3343 if (infoPtr->hwndToolTip)
3344 DestroyWindow (infoPtr->hwndToolTip);
3346 /* delete button data */
3347 if (infoPtr->buttons)
3348 COMCTL32_Free (infoPtr->buttons);
3350 /* delete strings */
3351 if (infoPtr->strings) {
3353 for (i = 0; i < infoPtr->nNumStrings; i++)
3354 if (infoPtr->strings[i])
3355 COMCTL32_Free (infoPtr->strings[i]);
3357 COMCTL32_Free (infoPtr->strings);
3360 /* destroy internal image list */
3361 if (infoPtr->himlInt)
3362 ImageList_Destroy (infoPtr->himlInt);
3364 /* delete default font */
3366 DeleteObject (infoPtr->hFont);
3368 /* free toolbar info data */
3369 COMCTL32_Free (infoPtr);
3370 SetWindowLongA (hwnd, 0, 0);
3377 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3379 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3381 if (infoPtr->bTransparent)
3382 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3384 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3389 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3391 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3393 return infoPtr->hFont;
3398 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3400 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3401 TBUTTON_INFO *btnPtr;
3405 pt.x = (INT)LOWORD(lParam);
3406 pt.y = (INT)HIWORD(lParam);
3407 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3410 btnPtr = &infoPtr->buttons[nHit];
3411 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3414 infoPtr->bCaptured = TRUE;
3415 infoPtr->nButtonDown = nHit;
3417 btnPtr->fsState |= TBSTATE_PRESSED;
3419 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3422 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3423 TOOLBAR_Customize (hwnd);
3430 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3432 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3433 TBUTTON_INFO *btnPtr;
3437 if (infoPtr->hwndToolTip)
3438 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3439 WM_LBUTTONDOWN, wParam, lParam);
3441 pt.x = (INT)LOWORD(lParam);
3442 pt.y = (INT)HIWORD(lParam);
3443 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3447 btnPtr = &infoPtr->buttons[nHit];
3448 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3452 infoPtr->bCaptured = TRUE;
3453 infoPtr->nButtonDown = nHit;
3454 infoPtr->nOldHit = nHit;
3456 btnPtr->fsState |= TBSTATE_PRESSED;
3457 btnPtr->bHot = FALSE;
3459 CopyRect(&arrowRect, &btnPtr->rect);
3460 arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
3462 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
3463 if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
3464 !(TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && !PtInRect(&arrowRect, pt)))
3468 * this time we must force a Redraw, so the btn is
3469 * painted down before CaptureChanged repaints it up
3471 RedrawWindow(hwnd,&btnPtr->rect,0,
3472 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3474 nmtb.hdr.hwndFrom = hwnd;
3475 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3476 nmtb.hdr.code = TBN_DROPDOWN;
3477 nmtb.iItem = btnPtr->idCommand;
3479 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3480 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3483 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3491 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3493 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3494 TBUTTON_INFO *btnPtr;
3498 BOOL bSendMessage = TRUE;
3500 if (infoPtr->hwndToolTip)
3501 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3502 WM_LBUTTONUP, wParam, lParam);
3504 pt.x = (INT)LOWORD(lParam);
3505 pt.y = (INT)HIWORD(lParam);
3506 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3508 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3509 /* if the cursor is still inside of the toolbar */
3510 if((infoPtr->nHotItem >= 0) && (nHit != -1))
3511 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3513 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3514 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3515 btnPtr->fsState &= ~TBSTATE_PRESSED;
3517 if (nHit == infoPtr->nButtonDown) {
3518 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3519 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3520 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3521 infoPtr->nButtonDown);
3522 if (nOldIndex == infoPtr->nButtonDown)
3523 bSendMessage = FALSE;
3524 if ((nOldIndex != infoPtr->nButtonDown) &&
3526 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3527 btnPtr->fsState |= TBSTATE_CHECKED;
3530 if (btnPtr->fsState & TBSTATE_CHECKED)
3531 btnPtr->fsState &= ~TBSTATE_CHECKED;
3533 btnPtr->fsState |= TBSTATE_CHECKED;
3538 bSendMessage = FALSE;
3540 if (nOldIndex != -1)
3542 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
3543 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
3547 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
3548 * that resets bCaptured and btn TBSTATE_PRESSED flags,
3549 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
3554 SendMessageA (GetParent(hwnd), WM_COMMAND,
3555 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3562 TOOLBAR_CaptureChanged(HWND hwnd)
3564 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3565 TBUTTON_INFO *btnPtr;
3567 infoPtr->bCaptured = FALSE;
3569 if (infoPtr->nButtonDown >= 0)
3571 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3572 btnPtr->fsState &= ~TBSTATE_PRESSED;
3574 infoPtr->nButtonDown = -1;
3575 infoPtr->nOldHit = -1;
3577 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3584 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3586 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3587 TBUTTON_INFO *hotBtnPtr, *btnPtr;
3589 if (infoPtr->nOldHit < 0)
3592 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3594 /* Redraw the button if the last button we were over is the hot button and it
3596 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3598 hotBtnPtr->bHot = FALSE;
3600 InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
3604 /* If the last button we were over is depressed then make it not */
3605 /* depressed and redraw it */
3606 if(infoPtr->nOldHit == infoPtr->nButtonDown)
3608 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3610 btnPtr->fsState &= ~TBSTATE_PRESSED;
3612 InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
3615 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3616 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3622 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3624 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3625 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3628 TRACKMOUSEEVENT trackinfo;
3630 /* fill in the TRACKMOUSEEVENT struct */
3631 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3632 trackinfo.dwFlags = TME_QUERY;
3633 trackinfo.hwndTrack = hwnd;
3634 trackinfo.dwHoverTime = HOVER_DEFAULT;
3636 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3637 _TrackMouseEvent(&trackinfo);
3639 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3640 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3641 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3643 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3644 /* and can properly deactivate the hot toolbar button */
3645 _TrackMouseEvent(&trackinfo);
3648 if (infoPtr->hwndToolTip)
3649 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3650 WM_MOUSEMOVE, wParam, lParam);
3652 pt.x = (INT)LOWORD(lParam);
3653 pt.y = (INT)HIWORD(lParam);
3655 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3657 if (infoPtr->nOldHit != nHit)
3659 /* Remove the effect of an old hot button if the button was enabled and was
3660 drawn with the hot button effect */
3661 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
3662 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3664 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3665 oldBtnPtr->bHot = FALSE;
3667 InvalidateRect (hwnd, &oldBtnPtr->rect,
3668 TOOLBAR_HasText(infoPtr, oldBtnPtr));
3671 /* It's not a separator or in nowhere. It's a hot button. */
3674 btnPtr = &infoPtr->buttons[nHit];
3675 btnPtr->bHot = TRUE;
3677 infoPtr->nHotItem = nHit;
3679 /* only enabled buttons show hot effect */
3680 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3682 InvalidateRect(hwnd, &btnPtr->rect,
3683 TOOLBAR_HasText(infoPtr, btnPtr));
3688 if (infoPtr->bCaptured) {
3689 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3690 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3691 btnPtr->fsState &= ~TBSTATE_PRESSED;
3692 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3694 else if (nHit == infoPtr->nButtonDown) {
3695 btnPtr->fsState |= TBSTATE_PRESSED;
3696 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3699 infoPtr->nOldHit = nHit;
3705 inline static LRESULT
3706 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3708 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3709 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3711 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3715 inline static LRESULT
3716 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3718 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3719 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3721 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3726 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3728 TOOLBAR_INFO *infoPtr;
3730 /* allocate memory for info structure */
3731 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3732 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3735 infoPtr->dwStructSize = sizeof(TBBUTTON);
3737 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3738 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3739 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3740 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3743 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3748 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3750 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3754 if (dwStyle & WS_MINIMIZE)
3755 return 0; /* Nothing to do */
3757 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3759 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3762 if (!(dwStyle & CCS_NODIVIDER))
3764 GetWindowRect (hwnd, &rcWindow);
3765 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3766 if( dwStyle & WS_BORDER )
3767 OffsetRect (&rcWindow, 1, 1);
3768 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3771 ReleaseDC( hwnd, hdc );
3777 inline static LRESULT
3778 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3780 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3781 LPNMHDR lpnmh = (LPNMHDR)lParam;
3783 TRACE("passing WM_NOTIFY!\n");
3785 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3786 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3789 if (lpnmh->code == TTN_GETDISPINFOA) {
3790 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3792 FIXME("retrieving ASCII string\n");
3795 else if (lpnmh->code == TTN_GETDISPINFOW) {
3796 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3798 FIXME("retrieving UNICODE string\n");
3809 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3811 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3817 /* fill ps.rcPaint with a default rect */
3818 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
3820 TOOLBAR_CalcToolbar( hwnd );
3821 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
3822 TOOLBAR_Refresh (hwnd, hdc, &ps);
3823 if (!wParam) EndPaint (hwnd, &ps);
3830 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3832 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3833 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3842 /* Resize deadlock check */
3843 if (infoPtr->bAutoSize) {
3844 infoPtr->bAutoSize = FALSE;
3848 /* FIXME: optimize to only update size if the new size doesn't */
3849 /* match the current size */
3851 flags = (INT) wParam;
3853 /* FIXME for flags =
3854 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3857 TRACE("sizing toolbar!\n");
3859 if (flags == SIZE_RESTORED) {
3860 /* width and height don't apply */
3861 parent = GetParent (hwnd);
3862 GetClientRect(parent, &parent_rect);
3863 x = parent_rect.left;
3864 y = parent_rect.top;
3866 if (dwStyle & CCS_NORESIZE) {
3867 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3870 * this sets the working width of the toolbar, and
3871 * Calc Toolbar will not adjust it, only the height
3873 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3874 cy = infoPtr->nHeight;
3875 cx = infoPtr->nWidth;
3876 TOOLBAR_CalcToolbar (hwnd);
3877 infoPtr->nWidth = cx;
3878 infoPtr->nHeight = cy;
3881 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3882 TOOLBAR_CalcToolbar (hwnd);
3883 cy = infoPtr->nHeight;
3884 cx = infoPtr->nWidth;
3886 if (dwStyle & CCS_NOMOVEY) {
3887 GetWindowRect(hwnd, &window_rect);
3888 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3889 y = window_rect.top;
3893 if (dwStyle & CCS_NOPARENTALIGN) {
3894 uPosFlags |= SWP_NOMOVE;
3895 cy = infoPtr->nHeight;
3896 cx = infoPtr->nWidth;
3899 if (!(dwStyle & CCS_NODIVIDER))
3900 cy += GetSystemMetrics(SM_CYEDGE);
3902 if (dwStyle & WS_BORDER)
3905 cy += GetSystemMetrics(SM_CYEDGE);
3906 cx += GetSystemMetrics(SM_CYEDGE);
3909 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3910 cx, cy, uPosFlags | SWP_NOZORDER);
3917 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3919 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3921 if (nType == GWL_STYLE) {
3922 if (lpStyle->styleNew & TBSTYLE_LIST) {
3923 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3926 infoPtr->dwDTFlags = DT_CENTER;
3930 TOOLBAR_AutoSize (hwnd);
3932 InvalidateRect(hwnd, NULL, FALSE);
3939 static LRESULT WINAPI
3940 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3946 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3949 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3952 if (!TOOLBAR_GetInfoPtr (hwnd))
3954 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3960 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3962 case TB_ADDBUTTONSA:
3963 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3965 case TB_ADDBUTTONSW:
3966 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3969 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3972 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3975 return TOOLBAR_AutoSize (hwnd);
3977 case TB_BUTTONCOUNT:
3978 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3980 case TB_BUTTONSTRUCTSIZE:
3981 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3983 case TB_CHANGEBITMAP:
3984 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3986 case TB_CHECKBUTTON:
3987 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3989 case TB_COMMANDTOINDEX:
3990 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3993 return TOOLBAR_Customize (hwnd);
3995 case TB_DELETEBUTTON:
3996 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3998 case TB_ENABLEBUTTON:
3999 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
4001 case TB_GETANCHORHIGHLIGHT:
4002 return TOOLBAR_GetAnchorHighlight (hwnd);
4005 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
4007 case TB_GETBITMAPFLAGS:
4008 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
4011 return TOOLBAR_GetButton (hwnd, wParam, lParam);
4013 case TB_GETBUTTONINFOA:
4014 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
4016 case TB_GETBUTTONINFOW:
4017 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
4019 case TB_GETBUTTONSIZE:
4020 return TOOLBAR_GetButtonSize (hwnd);
4022 case TB_GETBUTTONTEXTA:
4023 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
4025 case TB_GETBUTTONTEXTW:
4026 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
4028 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
4030 case TB_GETDISABLEDIMAGELIST:
4031 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
4033 case TB_GETEXTENDEDSTYLE:
4034 return TOOLBAR_GetExtendedStyle (hwnd);
4036 case TB_GETHOTIMAGELIST:
4037 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
4040 return TOOLBAR_GetHotItem (hwnd);
4042 case TB_GETIMAGELIST:
4043 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
4045 /* case TB_GETINSERTMARK: */ /* 4.71 */
4046 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
4048 case TB_GETITEMRECT:
4049 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
4052 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
4054 /* case TB_GETOBJECT: */ /* 4.71 */
4055 /* case TB_GETPADDING: */ /* 4.71 */
4058 return TOOLBAR_GetRect (hwnd, wParam, lParam);
4061 return TOOLBAR_GetRows (hwnd, wParam, lParam);
4064 return TOOLBAR_GetState (hwnd, wParam, lParam);
4067 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
4069 case TB_GETTEXTROWS:
4070 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
4072 case TB_GETTOOLTIPS:
4073 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
4075 case TB_GETUNICODEFORMAT:
4076 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
4078 case CCM_GETVERSION:
4079 return TOOLBAR_GetVersion (hwnd);
4082 return TOOLBAR_HideButton (hwnd, wParam, lParam);
4085 return TOOLBAR_HitTest (hwnd, wParam, lParam);
4087 case TB_INDETERMINATE:
4088 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
4090 case TB_INSERTBUTTONA:
4091 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
4093 case TB_INSERTBUTTONW:
4094 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
4096 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
4098 case TB_ISBUTTONCHECKED:
4099 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
4101 case TB_ISBUTTONENABLED:
4102 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
4104 case TB_ISBUTTONHIDDEN:
4105 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
4107 case TB_ISBUTTONHIGHLIGHTED:
4108 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
4110 case TB_ISBUTTONINDETERMINATE:
4111 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
4113 case TB_ISBUTTONPRESSED:
4114 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
4116 case TB_LOADIMAGES: /* 4.70 */
4117 FIXME("missing standard imagelists\n");
4120 /* case TB_MAPACCELERATORA: */ /* 4.71 */
4121 /* case TB_MAPACCELERATORW: */ /* 4.71 */
4122 /* case TB_MARKBUTTON: */ /* 4.71 */
4123 /* case TB_MOVEBUTTON: */ /* 4.71 */
4125 case TB_PRESSBUTTON:
4126 return TOOLBAR_PressButton (hwnd, wParam, lParam);
4128 /* case TB_REPLACEBITMAP: */
4130 case TB_SAVERESTOREA:
4131 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
4133 case TB_SAVERESTOREW:
4134 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
4136 case TB_SETANCHORHIGHLIGHT:
4137 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
4139 case TB_SETBITMAPSIZE:
4140 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
4142 case TB_SETBUTTONINFOA:
4143 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
4145 case TB_SETBUTTONINFOW:
4146 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
4148 case TB_SETBUTTONSIZE:
4149 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
4151 case TB_SETBUTTONWIDTH:
4152 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
4155 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
4157 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
4159 case TB_SETDISABLEDIMAGELIST:
4160 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
4162 case TB_SETDRAWTEXTFLAGS:
4163 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
4165 case TB_SETEXTENDEDSTYLE:
4166 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
4168 case TB_SETHOTIMAGELIST:
4169 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
4172 return TOOLBAR_SetHotItem (hwnd, wParam);
4174 case TB_SETIMAGELIST:
4175 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
4178 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
4180 /* case TB_SETINSERTMARK: */ /* 4.71 */
4182 case TB_SETINSERTMARKCOLOR:
4183 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
4185 case TB_SETMAXTEXTROWS:
4186 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
4188 /* case TB_SETPADDING: */ /* 4.71 */
4191 return TOOLBAR_SetParent (hwnd, wParam, lParam);
4194 return TOOLBAR_SetRows (hwnd, wParam, lParam);
4197 return TOOLBAR_SetState (hwnd, wParam, lParam);
4200 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
4202 case TB_SETTOOLTIPS:
4203 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
4205 case TB_SETUNICODEFORMAT:
4206 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
4208 case CCM_SETVERSION:
4209 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
4215 return TOOLBAR_Create (hwnd, wParam, lParam);
4218 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
4221 return TOOLBAR_GetFont (hwnd, wParam, lParam);
4223 /* case WM_KEYDOWN: */
4224 /* case WM_KILLFOCUS: */
4226 case WM_LBUTTONDBLCLK:
4227 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
4229 case WM_LBUTTONDOWN:
4230 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
4233 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4236 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4239 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
4241 case WM_CAPTURECHANGED:
4242 return TOOLBAR_CaptureChanged(hwnd);
4245 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4248 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4251 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4254 return TOOLBAR_Notify (hwnd, wParam, lParam);
4256 /* case WM_NOTIFYFORMAT: */
4259 return TOOLBAR_Paint (hwnd, wParam);
4262 return TOOLBAR_Size (hwnd, wParam, lParam);
4264 case WM_STYLECHANGED:
4265 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4267 /* case WM_SYSCOLORCHANGE: */
4269 /* case WM_WININICHANGE: */
4274 case WM_MEASUREITEM:
4276 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4279 if (uMsg >= WM_USER)
4280 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4281 uMsg, wParam, lParam);
4282 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4289 TOOLBAR_Register (void)
4293 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4294 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4295 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4296 wndClass.cbClsExtra = 0;
4297 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4298 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4299 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4300 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4302 RegisterClassA (&wndClass);
4307 TOOLBAR_Unregister (void)
4309 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);