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);
309 INT xOffset = (infoPtr->nButtonWidth / 2) - (infoPtr->nBitmapWidth / 2);
311 if (btnPtr->fsState & TBSTATE_HIDDEN)
315 CopyRect (&rcArrow, &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 TRACE("iBitmap: %d\n", btnPtr->iBitmap);
331 if (btnPtr->fsStyle & TBSTYLE_SEP) {
332 /* with the FLAT style, iBitmap is the width and has already */
333 /* been taken into consideration in calculating the width */
334 /* so now we need to draw the vertical separator */
335 /* empirical tests show that iBitmap can/will be non-zero */
336 /* when drawing the vertical bar... */
337 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
338 TOOLBAR_DrawFlatSeparator (&rc, hdc);
343 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
344 if (!(dwStyle & TBSTYLE_FLAT))
346 DrawEdge (hdc, &rc, EDGE_RAISED,
347 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
348 if (hasDropDownArrow)
349 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
350 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
353 if (hasDropDownArrow)
355 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
356 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
359 if (infoPtr->himlDis &&
360 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
361 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
362 rc.left + xOffset + 1, rc.top + 1, ILD_NORMAL);
364 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left + xOffset + 1, rc.top + 1);
366 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
370 /* pressed TBSTYLE_BUTTON */
371 if (btnPtr->fsState & TBSTATE_PRESSED) {
372 if (dwStyle & TBSTYLE_FLAT)
374 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
375 if (hasDropDownArrow)
376 DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
380 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
381 if (hasDropDownArrow)
382 DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
385 if (hasDropDownArrow)
386 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
388 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
389 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
390 rc.left + xOffset + 2, rc.top + 2, ILD_NORMAL);
392 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
396 /* checked TBSTYLE_CHECK */
397 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
398 (btnPtr->fsState & TBSTATE_CHECKED)) {
399 if (dwStyle & TBSTYLE_FLAT)
400 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
401 BF_RECT | BF_MIDDLE | BF_ADJUST);
403 DrawEdge (hdc, &rc, EDGE_SUNKEN,
404 BF_RECT | BF_MIDDLE | BF_ADJUST);
406 TOOLBAR_DrawPattern (hdc, &rc);
408 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
409 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
410 rc.left + xOffset, rc.top + 2, ILD_NORMAL);
412 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
417 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
418 DrawEdge (hdc, &rc, EDGE_RAISED,
419 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
421 TOOLBAR_DrawPattern (hdc, &rc);
422 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left + xOffset + 1, rc.top + 1);
423 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
428 if (dwStyle & TBSTYLE_FLAT)
432 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
433 if (hasDropDownArrow)
434 DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
438 FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
439 if (hasDropDownArrow)
440 FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
443 if (hasDropDownArrow)
444 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
446 if (btnPtr->bHot && infoPtr->himlHot &&
447 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
448 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
449 rc.left + xOffset + 2, rc.top + 2, ILD_NORMAL);
450 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
451 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
452 rc.left + xOffset + 2, rc.top + 2, ILD_NORMAL);
456 DrawEdge (hdc, &rc, EDGE_RAISED,
457 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
459 if (hasDropDownArrow)
461 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
462 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
463 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
466 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
467 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
468 rc.left + xOffset + 1, rc.top + 1, ILD_NORMAL);
471 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
476 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
478 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
479 TBUTTON_INFO *btnPtr;
483 /* redraw necessary buttons */
484 btnPtr = infoPtr->buttons;
485 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
487 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
488 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
493 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
495 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
496 TBUTTON_INFO *btnPtr;
503 hOldFont = SelectObject (hdc, infoPtr->hFont);
505 btnPtr = &infoPtr->buttons[index];
507 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
508 (btnPtr->iString > -1) &&
509 (btnPtr->iString < infoPtr->nNumStrings))
511 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
512 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
515 SelectObject (hdc, hOldFont);
518 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
522 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
524 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
525 TBUTTON_INFO *btnPtr;
533 btnPtr = infoPtr->buttons;
534 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
535 if(TOOLBAR_HasText(infoPtr, btnPtr))
537 TOOLBAR_MeasureString(hwnd,i,&sz);
538 if (sz.cx > lpSize->cx)
540 if (sz.cy > lpSize->cy)
545 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
548 /***********************************************************************
549 * TOOLBAR_WrapToolbar
551 * This function walks through the buttons and seperators in the
552 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
553 * wrapping should occur based on the width of the toolbar window.
554 * It does *not* calculate button placement itself. That task
555 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
556 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
557 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
561 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
563 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
564 TBUTTON_INFO *btnPtr;
567 BOOL bWrap, bButtonWrap;
569 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
570 /* no layout is necessary. Applications may use this style */
571 /* to perform their own layout on the toolbar. */
572 if( !(dwStyle & TBSTYLE_WRAPABLE) )
575 btnPtr = infoPtr->buttons;
576 x = infoPtr->nIndent;
578 /* this can get the parents width, to know how far we can extend
579 * this toolbar. We cannot use its height, as there may be multiple
580 * toolbars in a rebar control
582 GetClientRect( GetParent(hwnd), &rc );
583 infoPtr->nWidth = rc.right - rc.left;
586 for (i = 0; i < infoPtr->nNumButtons; i++ )
589 btnPtr[i].fsState &= ~TBSTATE_WRAP;
591 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
594 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
595 /* it is the actual width of the separator. This is used for */
596 /* custom controls in toolbars. */
597 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
598 cx = (btnPtr[i].iBitmap > 0) ?
599 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
601 cx = infoPtr->nButtonWidth;
603 /* Two or more adjacent separators form a separator group. */
604 /* The first separator in a group should be wrapped to the */
605 /* next row if the previous wrapping is on a button. */
607 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
608 (i + 1 < infoPtr->nNumButtons ) &&
609 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
611 btnPtr[i].fsState |= TBSTATE_WRAP;
612 x = infoPtr->nIndent;
618 /* The layout makes sure the bitmap is visible, but not the button. */
619 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
624 /* If the current button is a separator and not hidden, */
625 /* go to the next until it reaches a non separator. */
626 /* Wrap the last separator if it is before a button. */
627 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
628 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
629 i < infoPtr->nNumButtons )
635 if( bFound && i < infoPtr->nNumButtons )
638 btnPtr[i].fsState |= TBSTATE_WRAP;
639 x = infoPtr->nIndent;
643 else if ( i >= infoPtr->nNumButtons)
646 /* If the current button is not a separator, find the last */
647 /* separator and wrap it. */
648 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
650 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
651 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
655 x = infoPtr->nIndent;
656 btnPtr[j].fsState |= TBSTATE_WRAP;
662 /* If no separator available for wrapping, wrap one of */
663 /* non-hidden previous button. */
667 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
669 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
674 x = infoPtr->nIndent;
675 btnPtr[j].fsState |= TBSTATE_WRAP;
681 /* If all above failed, wrap the current button. */
684 btnPtr[i].fsState |= TBSTATE_WRAP;
686 x = infoPtr->nIndent;
687 if (btnPtr[i].fsState & TBSTYLE_SEP )
699 /***********************************************************************
700 * TOOLBAR_CalcToolbar
702 * This function calculates button and separator placement. It first
703 * calculates the button sizes, gets the toolbar window width and then
704 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
705 * on. It assigns a new location to each item and sends this location to
706 * the tooltip window if appropriate. Finally, it updates the rcBound
707 * rect and calculates the new required toolbar window height.
711 TOOLBAR_CalcToolbar (HWND hwnd)
713 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
714 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
715 TBUTTON_INFO *btnPtr;
716 INT i, nRows, nSepRows;
720 BOOL usesBitmaps = FALSE;
721 BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
723 TOOLBAR_CalcStrings (hwnd, &sizeString);
725 if (dwStyle & TBSTYLE_LIST)
727 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
728 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
731 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
733 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
737 if (sizeString.cy > 0)
740 infoPtr->nButtonHeight = sizeString.cy +
741 infoPtr->nBitmapHeight + 6;
743 infoPtr->nButtonHeight = sizeString.cy + 6;
745 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
746 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
748 if (sizeString.cx > infoPtr->nBitmapWidth)
749 infoPtr->nButtonWidth = sizeString.cx + 6;
750 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
751 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
754 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
755 infoPtr->nButtonWidth = infoPtr->cxMin;
756 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
757 infoPtr->nButtonWidth = infoPtr->cxMax;
759 TOOLBAR_WrapToolbar( hwnd, dwStyle );
761 x = infoPtr->nIndent;
762 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
765 * We will set the height below, and we set the width on entry
766 * so we do not reset them here..
769 GetClientRect( hwnd, &rc );
770 /* get initial values for toolbar */
771 infoPtr->nWidth = rc.right - rc.left;
772 infoPtr->nHeight = rc.bottom - rc.top;
775 /* from above, minimum is a button, and possible text */
776 cx = infoPtr->nButtonWidth;
778 /* cannot use just ButtonHeight, we may have no buttons! */
779 if (infoPtr->nNumButtons > 0)
780 infoPtr->nHeight = infoPtr->nButtonHeight;
782 cy = infoPtr->nHeight;
784 nRows = nSepRows = 0;
786 infoPtr->rcBound.top = y;
787 infoPtr->rcBound.left = x;
788 infoPtr->rcBound.bottom = y + cy;
789 infoPtr->rcBound.right = x;
791 btnPtr = infoPtr->buttons;
793 /* do not base height/width on parent, if the parent is a */
794 /* rebar control it could have multiple rows of toolbars */
795 /* GetClientRect( GetParent(hwnd), &rc ); */
796 /* cx = rc.right - rc.left; */
797 /* cy = rc.bottom - rc.top; */
799 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
802 if (btnPtr->fsState & TBSTATE_HIDDEN)
804 SetRectEmpty (&btnPtr->rect);
808 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
809 /* it is the actual width of the separator. This is used for */
810 /* custom controls in toolbars. */
811 if (btnPtr->fsStyle & TBSTYLE_SEP)
812 cx = (btnPtr->iBitmap > 0) ?
813 btnPtr->iBitmap : SEPARATOR_WIDTH;
816 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
819 TOOLBAR_MeasureString(hwnd,i,&sz);
823 cx = infoPtr->nButtonWidth;
825 if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
828 cy = infoPtr->nHeight;
830 if (btnPtr->fsState & TBSTATE_WRAP )
833 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
835 if (infoPtr->rcBound.left > x)
836 infoPtr->rcBound.left = x;
837 if (infoPtr->rcBound.right < x + cx)
838 infoPtr->rcBound.right = x + cx;
839 if (infoPtr->rcBound.bottom < y + cy)
840 infoPtr->rcBound.bottom = y + cy;
842 /* Set the toolTip only for non-hidden, non-separator button */
843 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
847 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
848 ti.cbSize = sizeof(TTTOOLINFOA);
850 ti.uId = btnPtr->idCommand;
851 ti.rect = btnPtr->rect;
852 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
856 /* btnPtr->nRow is zero based. The space between the rows is */
857 /* also considered as a row. */
858 btnPtr->nRow = nRows + nSepRows;
861 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
865 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
866 /* it is the actual width of the separator. This is used for */
867 /* custom controls in toolbars. */
868 y += cy + ( (btnPtr->iBitmap > 0 ) ?
869 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
871 /* nSepRows is used to calculate the extra height follwoing */
875 x = infoPtr->nIndent;
882 /* infoPtr->nRows is the number of rows on the toolbar */
883 infoPtr->nRows = nRows + nSepRows + 1;
885 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
887 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
888 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
889 nSepRows * (infoPtr->nBitmapHeight + 1) +
891 TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
896 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
898 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
899 TBUTTON_INFO *btnPtr;
902 btnPtr = infoPtr->buttons;
903 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
904 if (btnPtr->fsState & TBSTATE_HIDDEN)
907 if (btnPtr->fsStyle & TBSTYLE_SEP) {
908 if (PtInRect (&btnPtr->rect, *lpPt)) {
909 TRACE(" ON SEPARATOR %d!\n", i);
914 if (PtInRect (&btnPtr->rect, *lpPt)) {
915 TRACE(" ON BUTTON %d!\n", i);
921 TRACE(" NOWHERE!\n");
927 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
929 TBUTTON_INFO *btnPtr;
932 btnPtr = infoPtr->buttons;
933 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
934 if (btnPtr->idCommand == idCommand) {
935 TRACE("command=%d index=%d\n", idCommand, i);
939 TRACE("no index found for command=%d\n", idCommand);
945 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
947 TBUTTON_INFO *btnPtr;
950 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
953 /* check index button */
954 btnPtr = &infoPtr->buttons[nIndex];
955 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
956 if (btnPtr->fsState & TBSTATE_CHECKED)
960 /* check previous buttons */
961 nRunIndex = nIndex - 1;
962 while (nRunIndex >= 0) {
963 btnPtr = &infoPtr->buttons[nRunIndex];
964 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
965 if (btnPtr->fsState & TBSTATE_CHECKED)
973 /* check next buttons */
974 nRunIndex = nIndex + 1;
975 while (nRunIndex < infoPtr->nNumButtons) {
976 btnPtr = &infoPtr->buttons[nRunIndex];
977 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
978 if (btnPtr->fsState & TBSTATE_CHECKED)
991 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
992 WPARAM wParam, LPARAM lParam)
1000 msg.time = GetMessageTime ();
1001 msg.pt.x = LOWORD(GetMessagePos ());
1002 msg.pt.y = HIWORD(GetMessagePos ());
1004 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1008 /***********************************************************************
1009 * TOOLBAR_CustomizeDialogProc
1010 * This function implements the toolbar customization dialog.
1013 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1015 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
1016 static HDSA hDsa = NULL;
1021 infoPtr = (TOOLBAR_INFO *)lParam;
1022 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
1024 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
1028 TBUTTON_INFO *btnPtr;
1031 /* insert 'virtual' separator button into 'available buttons' list */
1032 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1034 /* copy all buttons and append them to the right listbox */
1035 btnPtr = infoPtr->buttons;
1036 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
1038 DSA_InsertItem (hDsa, i, btnPtr);
1040 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
1041 if (btnPtr->fsState & TBSTATE_HIDDEN)
1043 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1047 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1051 /* append 'virtual' separator button to the 'toolbar buttons' list */
1057 EndDialog(hwnd, FALSE);
1061 switch (LOWORD(wParam))
1064 EndDialog(hwnd, FALSE);
1075 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1077 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1078 TBUTTON_INFO btnPtr;
1083 COLORREF oldText = 0;
1086 FIXME("action: %x itemState: %x\n",
1087 lpdis->itemAction, lpdis->itemState);
1089 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
1091 if (lpdis->itemState & ODS_FOCUS)
1093 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
1094 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
1097 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1098 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1100 /* fill background rectangle */
1101 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1102 lpdis->rcItem.right, lpdis->rcItem.bottom);
1104 /* calculate button and text rectangles */
1105 CopyRect (&rcButton, &lpdis->rcItem);
1106 InflateRect (&rcButton, -1, -1);
1107 CopyRect (&rcText, &rcButton);
1108 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
1109 rcText.left = rcButton.right + 2;
1111 /* draw focus rectangle */
1112 if (lpdis->itemState & ODS_FOCUS)
1113 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1116 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1118 /* draw image and text */
1119 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
1121 /* virtual separator in the 'available' list */
1122 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
1123 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1129 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
1130 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
1132 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
1133 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1137 if (lpdis->itemState & ODS_FOCUS)
1139 SetBkColor (lpdis->hDC, oldBk);
1140 SetTextColor (lpdis->hDC, oldText);
1143 SelectObject (lpdis->hDC, hOldBrush);
1144 SelectObject (lpdis->hDC, hOldPen);
1150 case WM_MEASUREITEM:
1151 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1153 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1156 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
1158 lpmis->itemHeight = 15 + 8; /* default height */
1170 /***********************************************************************
1171 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1175 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1177 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1178 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1179 INT nIndex = 0, nButtons, nCount;
1182 TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1186 if (lpAddBmp->hInst == HINST_COMMCTRL)
1188 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1190 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1192 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1197 TRACE ("adding %d internal bitmaps!\n", nButtons);
1199 /* Windows resize all the buttons to the size of a newly added standard image */
1200 if (lpAddBmp->nID & 1)
1203 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
1204 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
1206 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1207 MAKELPARAM((WORD)24, (WORD)24));
1208 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1209 MAKELPARAM((WORD)31, (WORD)30));
1214 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1215 MAKELPARAM((WORD)16, (WORD)16));
1216 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1217 MAKELPARAM((WORD)22, (WORD)22));
1220 TOOLBAR_CalcToolbar (hwnd);
1224 nButtons = (INT)wParam;
1228 TRACE ("adding %d bitmaps!\n", nButtons);
1231 if (!(infoPtr->himlDef)) {
1232 /* create new default image list */
1233 TRACE ("creating default image list!\n");
1236 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1237 ILC_COLOR | ILC_MASK, nButtons, 2);
1238 infoPtr->himlInt = infoPtr->himlDef;
1241 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1243 /* Add bitmaps to the default image list */
1244 if (lpAddBmp->hInst == (HINSTANCE)0)
1247 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1250 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1252 /* Add system bitmaps */
1253 switch (lpAddBmp->nID)
1255 case IDB_STD_SMALL_COLOR:
1256 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1257 MAKEINTRESOURCEA(IDB_STD_SMALL));
1258 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1259 hbmLoad, CLR_DEFAULT);
1260 DeleteObject (hbmLoad);
1263 case IDB_STD_LARGE_COLOR:
1264 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1265 MAKEINTRESOURCEA(IDB_STD_LARGE));
1266 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1267 hbmLoad, CLR_DEFAULT);
1268 DeleteObject (hbmLoad);
1271 case IDB_VIEW_SMALL_COLOR:
1272 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1273 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1274 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1275 hbmLoad, CLR_DEFAULT);
1276 DeleteObject (hbmLoad);
1279 case IDB_VIEW_LARGE_COLOR:
1280 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1281 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1282 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1283 hbmLoad, CLR_DEFAULT);
1284 DeleteObject (hbmLoad);
1287 case IDB_HIST_SMALL_COLOR:
1288 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1289 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1290 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1291 hbmLoad, CLR_DEFAULT);
1292 DeleteObject (hbmLoad);
1295 case IDB_HIST_LARGE_COLOR:
1296 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1297 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1298 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1299 hbmLoad, CLR_DEFAULT);
1300 DeleteObject (hbmLoad);
1304 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1305 ERR ("invalid imagelist!\n");
1311 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1312 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1313 DeleteObject (hbmLoad);
1318 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1320 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1322 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",
1323 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1324 infoPtr->nNumBitmaps+nButtons,imagecount);
1326 infoPtr->nNumBitmaps = imagecount;
1329 infoPtr->nNumBitmaps += nButtons;
1337 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1339 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1340 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1341 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1343 TRACE("adding %d buttons!\n", wParam);
1345 nAddButtons = (UINT)wParam;
1346 nOldButtons = infoPtr->nNumButtons;
1347 nNewButtons = nOldButtons + nAddButtons;
1349 if (infoPtr->nNumButtons == 0) {
1351 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1354 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1356 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1357 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1358 nOldButtons * sizeof(TBUTTON_INFO));
1359 COMCTL32_Free (oldButtons);
1362 infoPtr->nNumButtons = nNewButtons;
1364 /* insert new button data */
1365 for (nCount = 0; nCount < nAddButtons; nCount++) {
1366 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1367 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1368 btnPtr->idCommand = lpTbb[nCount].idCommand;
1369 btnPtr->fsState = lpTbb[nCount].fsState;
1370 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1371 btnPtr->dwData = lpTbb[nCount].dwData;
1372 btnPtr->iString = lpTbb[nCount].iString;
1373 btnPtr->bHot = FALSE;
1375 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1378 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1379 ti.cbSize = sizeof (TTTOOLINFOA);
1381 ti.uId = btnPtr->idCommand;
1383 ti.lpszText = LPSTR_TEXTCALLBACKA;
1385 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1390 TOOLBAR_CalcToolbar (hwnd);
1392 InvalidateRect(hwnd, NULL, FALSE);
1399 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1401 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1402 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1403 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1405 TRACE("adding %d buttons!\n", wParam);
1407 nAddButtons = (UINT)wParam;
1408 nOldButtons = infoPtr->nNumButtons;
1409 nNewButtons = nOldButtons + nAddButtons;
1411 if (infoPtr->nNumButtons == 0) {
1413 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1416 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1418 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1419 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1420 nOldButtons * sizeof(TBUTTON_INFO));
1421 COMCTL32_Free (oldButtons);
1424 infoPtr->nNumButtons = nNewButtons;
1426 /* insert new button data */
1427 for (nCount = 0; nCount < nAddButtons; nCount++) {
1428 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1429 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1430 btnPtr->idCommand = lpTbb[nCount].idCommand;
1431 btnPtr->fsState = lpTbb[nCount].fsState;
1432 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1433 btnPtr->dwData = lpTbb[nCount].dwData;
1434 btnPtr->iString = lpTbb[nCount].iString;
1435 btnPtr->bHot = FALSE;
1437 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1440 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1441 ti.cbSize = sizeof (TTTOOLINFOW);
1443 ti.uId = btnPtr->idCommand;
1445 ti.lpszText = LPSTR_TEXTCALLBACKW;
1447 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1452 TOOLBAR_CalcToolbar (hwnd);
1454 InvalidateRect(hwnd, NULL, FALSE);
1461 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1463 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1466 if ((wParam) && (HIWORD(lParam) == 0)) {
1469 TRACE("adding string from resource!\n");
1471 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1474 TRACE("len=%d \"%s\"\n", len, szString);
1475 nIndex = infoPtr->nNumStrings;
1476 if (infoPtr->nNumStrings == 0) {
1478 COMCTL32_Alloc (sizeof(LPWSTR));
1481 LPWSTR *oldStrings = infoPtr->strings;
1483 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1484 memcpy (&infoPtr->strings[0], &oldStrings[0],
1485 sizeof(LPWSTR) * infoPtr->nNumStrings);
1486 COMCTL32_Free (oldStrings);
1489 infoPtr->strings[infoPtr->nNumStrings] =
1490 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1491 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1492 infoPtr->nNumStrings++;
1495 LPSTR p = (LPSTR)lParam;
1500 TRACE("adding string(s) from array!\n");
1502 nIndex = infoPtr->nNumStrings;
1505 TRACE("len=%d \"%s\"\n", len, p);
1507 if (infoPtr->nNumStrings == 0) {
1509 COMCTL32_Alloc (sizeof(LPWSTR));
1512 LPWSTR *oldStrings = infoPtr->strings;
1514 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1515 memcpy (&infoPtr->strings[0], &oldStrings[0],
1516 sizeof(LPWSTR) * infoPtr->nNumStrings);
1517 COMCTL32_Free (oldStrings);
1520 infoPtr->strings[infoPtr->nNumStrings] =
1521 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1522 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1523 infoPtr->nNumStrings++;
1534 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1536 #define MAX_RESOURCE_STRING_LENGTH 512
1537 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1540 if ((wParam) && (HIWORD(lParam) == 0)) {
1541 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1543 TRACE("adding string from resource!\n");
1545 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1546 szString, MAX_RESOURCE_STRING_LENGTH);
1548 TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1549 TRACE("First char: 0x%x\n", *szString);
1550 if (szString[0] == L'|')
1552 PWSTR p = szString + 1;
1554 nIndex = infoPtr->nNumStrings;
1555 while (*p != L'|') {
1557 if (infoPtr->nNumStrings == 0) {
1559 COMCTL32_Alloc (sizeof(LPWSTR));
1562 LPWSTR *oldStrings = infoPtr->strings;
1564 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1565 memcpy (&infoPtr->strings[0], &oldStrings[0],
1566 sizeof(LPWSTR) * infoPtr->nNumStrings);
1567 COMCTL32_Free (oldStrings);
1570 len = COMCTL32_StrChrW (p, L'|') - p;
1571 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1572 infoPtr->strings[infoPtr->nNumStrings] =
1573 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1574 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1575 infoPtr->nNumStrings++;
1582 nIndex = infoPtr->nNumStrings;
1583 if (infoPtr->nNumStrings == 0) {
1585 COMCTL32_Alloc (sizeof(LPWSTR));
1588 LPWSTR *oldStrings = infoPtr->strings;
1590 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1591 memcpy (&infoPtr->strings[0], &oldStrings[0],
1592 sizeof(LPWSTR) * infoPtr->nNumStrings);
1593 COMCTL32_Free (oldStrings);
1596 infoPtr->strings[infoPtr->nNumStrings] =
1597 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1598 strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1599 infoPtr->nNumStrings++;
1603 LPWSTR p = (LPWSTR)lParam;
1608 TRACE("adding string(s) from array!\n");
1609 nIndex = infoPtr->nNumStrings;
1613 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1614 if (infoPtr->nNumStrings == 0) {
1616 COMCTL32_Alloc (sizeof(LPWSTR));
1619 LPWSTR *oldStrings = infoPtr->strings;
1621 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1622 memcpy (&infoPtr->strings[0], &oldStrings[0],
1623 sizeof(LPWSTR) * infoPtr->nNumStrings);
1624 COMCTL32_Free (oldStrings);
1627 infoPtr->strings[infoPtr->nNumStrings] =
1628 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1629 strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1630 infoPtr->nNumStrings++;
1641 TOOLBAR_AutoSize (HWND hwnd)
1643 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1644 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1650 UINT uPosFlags = SWP_NOZORDER;
1652 TRACE("resize forced, style=%lx!\n", dwStyle);
1654 parent = GetParent (hwnd);
1655 GetClientRect(parent, &parent_rect);
1657 x = parent_rect.left;
1658 y = parent_rect.top;
1660 /* FIXME: we should be able to early out if nothing */
1661 /* has changed with nWidth != parent_rect width */
1663 if (dwStyle & CCS_NORESIZE) {
1664 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1669 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1670 TOOLBAR_CalcToolbar (hwnd);
1671 InvalidateRect( hwnd, NULL, TRUE );
1672 cy = infoPtr->nHeight;
1673 cx = infoPtr->nWidth;
1675 if (dwStyle & CCS_NOMOVEY) {
1676 GetWindowRect(hwnd, &window_rect);
1677 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1678 y = window_rect.top;
1682 if (dwStyle & CCS_NOPARENTALIGN)
1683 uPosFlags |= SWP_NOMOVE;
1685 if (!(dwStyle & CCS_NODIVIDER))
1686 cy += GetSystemMetrics(SM_CYEDGE);
1688 if (dwStyle & WS_BORDER)
1691 cy += GetSystemMetrics(SM_CYEDGE);
1692 cx += GetSystemMetrics(SM_CYEDGE);
1695 infoPtr->bAutoSize = TRUE;
1696 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1698 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1699 * the setwindowpos calls */
1700 infoPtr->bAutoSize = FALSE;
1707 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1709 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1711 return infoPtr->nNumButtons;
1716 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1718 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1720 if (infoPtr == NULL) {
1721 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1722 ERR("infoPtr == NULL!\n");
1726 infoPtr->dwStructSize = (DWORD)wParam;
1733 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1735 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1736 TBUTTON_INFO *btnPtr;
1739 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1743 btnPtr = &infoPtr->buttons[nIndex];
1744 btnPtr->iBitmap = LOWORD(lParam);
1746 /* we HAVE to erase the background, the new bitmap could be */
1748 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1755 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1757 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1758 TBUTTON_INFO *btnPtr;
1761 BOOL bChecked = FALSE;
1763 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1767 btnPtr = &infoPtr->buttons[nIndex];
1769 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1772 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1774 if (LOWORD(lParam) == FALSE)
1775 btnPtr->fsState &= ~TBSTATE_CHECKED;
1777 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1779 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1780 if (nOldIndex == nIndex)
1782 if (nOldIndex != -1)
1783 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1785 btnPtr->fsState |= TBSTATE_CHECKED;
1788 if( bChecked != LOWORD(lParam) )
1790 if (nOldIndex != -1)
1792 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
1793 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
1795 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1798 /* FIXME: Send a WM_NOTIFY?? */
1805 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1807 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1809 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1814 TOOLBAR_Customize (HWND hwnd)
1816 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1822 /* send TBN_BEGINADJUST notification */
1823 nmhdr.hwndFrom = hwnd;
1824 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1825 nmhdr.code = TBN_BEGINADJUST;
1827 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1828 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1830 if (!(hRes = FindResourceA (COMCTL32_hModule,
1831 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1835 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1838 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1839 (LPDLGTEMPLATEA)template,
1841 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1844 /* send TBN_ENDADJUST notification */
1845 nmhdr.code = TBN_ENDADJUST;
1847 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1848 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1855 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1857 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1858 INT nIndex = (INT)wParam;
1860 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1863 if ((infoPtr->hwndToolTip) &&
1864 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1867 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1868 ti.cbSize = sizeof (TTTOOLINFOA);
1870 ti.uId = infoPtr->buttons[nIndex].idCommand;
1872 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1875 if (infoPtr->nNumButtons == 1) {
1876 TRACE(" simple delete!\n");
1877 COMCTL32_Free (infoPtr->buttons);
1878 infoPtr->buttons = NULL;
1879 infoPtr->nNumButtons = 0;
1882 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1883 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1885 infoPtr->nNumButtons--;
1886 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1888 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1889 nIndex * sizeof(TBUTTON_INFO));
1892 if (nIndex < infoPtr->nNumButtons) {
1893 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1894 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1897 COMCTL32_Free (oldButtons);
1900 TOOLBAR_CalcToolbar (hwnd);
1902 InvalidateRect (hwnd, NULL, TRUE);
1909 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1911 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1912 TBUTTON_INFO *btnPtr;
1916 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1920 btnPtr = &infoPtr->buttons[nIndex];
1922 bState = btnPtr->fsState & TBSTATE_ENABLED;
1924 /* update the toolbar button state */
1925 if(LOWORD(lParam) == FALSE) {
1926 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1928 btnPtr->fsState |= TBSTATE_ENABLED;
1931 /* redraw the button only if the state of the button changed */
1932 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
1934 InvalidateRect(hwnd, &btnPtr->rect,
1935 TOOLBAR_HasText(infoPtr, btnPtr));
1942 static inline LRESULT
1943 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1945 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1947 return infoPtr->bAnchor;
1952 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1954 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1957 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1961 return infoPtr->buttons[nIndex].iBitmap;
1965 static inline LRESULT
1966 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1968 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1973 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1975 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1976 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1977 INT nIndex = (INT)wParam;
1978 TBUTTON_INFO *btnPtr;
1980 if (infoPtr == NULL)
1986 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1989 btnPtr = &infoPtr->buttons[nIndex];
1990 lpTbb->iBitmap = btnPtr->iBitmap;
1991 lpTbb->idCommand = btnPtr->idCommand;
1992 lpTbb->fsState = btnPtr->fsState;
1993 lpTbb->fsStyle = btnPtr->fsStyle;
1994 lpTbb->dwData = btnPtr->dwData;
1995 lpTbb->iString = btnPtr->iString;
2002 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2004 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2005 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2006 TBUTTON_INFO *btnPtr;
2009 if (infoPtr == NULL)
2011 if (lpTbInfo == NULL)
2013 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2016 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2020 btnPtr = &infoPtr->buttons[nIndex];
2022 if (lpTbInfo->dwMask & TBIF_COMMAND)
2023 lpTbInfo->idCommand = btnPtr->idCommand;
2024 if (lpTbInfo->dwMask & TBIF_IMAGE)
2025 lpTbInfo->iImage = btnPtr->iBitmap;
2026 if (lpTbInfo->dwMask & TBIF_LPARAM)
2027 lpTbInfo->lParam = btnPtr->dwData;
2028 if (lpTbInfo->dwMask & TBIF_SIZE)
2029 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2030 if (lpTbInfo->dwMask & TBIF_STATE)
2031 lpTbInfo->fsState = btnPtr->fsState;
2032 if (lpTbInfo->dwMask & TBIF_STYLE)
2033 lpTbInfo->fsStyle = btnPtr->fsStyle;
2034 if (lpTbInfo->dwMask & TBIF_TEXT) {
2035 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2037 lstrcpynWtoA (lpTbInfo->pszText,
2038 (LPWSTR)infoPtr->strings[btnPtr->iString],
2041 else lpTbInfo->pszText[0]=0;
2048 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2050 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2051 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2052 TBUTTON_INFO *btnPtr;
2055 if (infoPtr == NULL)
2057 if (lpTbInfo == NULL)
2059 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2062 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2066 btnPtr = &infoPtr->buttons[nIndex];
2068 if (lpTbInfo->dwMask & TBIF_COMMAND)
2069 lpTbInfo->idCommand = btnPtr->idCommand;
2070 if (lpTbInfo->dwMask & TBIF_IMAGE)
2071 lpTbInfo->iImage = btnPtr->iBitmap;
2072 if (lpTbInfo->dwMask & TBIF_LPARAM)
2073 lpTbInfo->lParam = btnPtr->dwData;
2074 if (lpTbInfo->dwMask & TBIF_SIZE)
2075 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2076 if (lpTbInfo->dwMask & TBIF_STATE)
2077 lpTbInfo->fsState = btnPtr->fsState;
2078 if (lpTbInfo->dwMask & TBIF_STYLE)
2079 lpTbInfo->fsStyle = btnPtr->fsStyle;
2080 if (lpTbInfo->dwMask & TBIF_TEXT) {
2081 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2082 lstrcpynW (lpTbInfo->pszText,
2083 (LPWSTR)infoPtr->strings[btnPtr->iString],
2092 TOOLBAR_GetButtonSize (HWND hwnd)
2094 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2096 return MAKELONG((WORD)infoPtr->nButtonWidth,
2097 (WORD)infoPtr->nButtonHeight);
2102 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2104 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2105 INT nIndex, nStringIndex;
2107 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2111 nStringIndex = infoPtr->buttons[nIndex].iString;
2113 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2115 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2121 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2123 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2128 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2130 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2131 INT nIndex, nStringIndex;
2133 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2137 nStringIndex = infoPtr->buttons[nIndex].iString;
2139 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2141 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2147 strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2149 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2153 /* << TOOLBAR_GetColorScheme >> */
2157 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2159 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2161 return (LRESULT)infoPtr->himlDis;
2165 inline static LRESULT
2166 TOOLBAR_GetExtendedStyle (HWND hwnd)
2168 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2170 return infoPtr->dwExStyle;
2175 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2177 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2179 return (LRESULT)infoPtr->himlHot;
2184 TOOLBAR_GetHotItem (HWND hwnd)
2186 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2188 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2191 if (infoPtr->nHotItem < 0)
2194 return (LRESULT)infoPtr->nHotItem;
2199 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2201 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2203 return (LRESULT)infoPtr->himlDef;
2207 /* << TOOLBAR_GetInsertMark >> */
2208 /* << TOOLBAR_GetInsertMarkColor >> */
2212 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2214 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2215 TBUTTON_INFO *btnPtr;
2219 if (infoPtr == NULL)
2221 nIndex = (INT)wParam;
2222 btnPtr = &infoPtr->buttons[nIndex];
2223 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2225 lpRect = (LPRECT)lParam;
2228 if (btnPtr->fsState & TBSTATE_HIDDEN)
2231 lpRect->left = btnPtr->rect.left;
2232 lpRect->right = btnPtr->rect.right;
2233 lpRect->bottom = btnPtr->rect.bottom;
2234 lpRect->top = btnPtr->rect.top;
2241 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2243 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2244 LPSIZE lpSize = (LPSIZE)lParam;
2249 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2250 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2252 TRACE("maximum size %d x %d\n",
2253 infoPtr->rcBound.right - infoPtr->rcBound.left,
2254 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2260 /* << TOOLBAR_GetObject >> */
2261 /* << TOOLBAR_GetPadding >> */
2265 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2267 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2268 TBUTTON_INFO *btnPtr;
2272 if (infoPtr == NULL)
2274 nIndex = (INT)wParam;
2275 btnPtr = &infoPtr->buttons[nIndex];
2276 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2278 lpRect = (LPRECT)lParam;
2282 lpRect->left = btnPtr->rect.left;
2283 lpRect->right = btnPtr->rect.right;
2284 lpRect->bottom = btnPtr->rect.bottom;
2285 lpRect->top = btnPtr->rect.top;
2292 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2294 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2296 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2297 return infoPtr->nRows;
2304 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2306 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2309 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2313 return infoPtr->buttons[nIndex].fsState;
2318 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2320 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2323 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2327 return infoPtr->buttons[nIndex].fsStyle;
2332 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2334 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2336 if (infoPtr == NULL)
2339 return infoPtr->nMaxTextRows;
2344 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2346 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2348 if (infoPtr == NULL)
2350 return infoPtr->hwndToolTip;
2355 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2357 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2359 TRACE("%s hwnd=0x%x stub!\n",
2360 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2362 return infoPtr->bUnicode;
2366 inline static LRESULT
2367 TOOLBAR_GetVersion (HWND hwnd)
2369 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2370 return infoPtr->iVersion;
2375 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2377 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2378 TBUTTON_INFO *btnPtr;
2383 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2387 btnPtr = &infoPtr->buttons[nIndex];
2388 if (LOWORD(lParam) == FALSE)
2389 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2391 btnPtr->fsState |= TBSTATE_HIDDEN;
2393 TOOLBAR_CalcToolbar (hwnd);
2395 InvalidateRect (hwnd, NULL, TRUE);
2401 inline static LRESULT
2402 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2404 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2409 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2411 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2412 TBUTTON_INFO *btnPtr;
2415 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2419 btnPtr = &infoPtr->buttons[nIndex];
2420 if (LOWORD(lParam) == FALSE)
2421 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2423 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2425 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2432 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2434 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2435 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2436 INT nIndex = (INT)wParam;
2437 TBUTTON_INFO *oldButtons;
2443 /* EPP: this seems to be an undocumented call (from my IE4)
2444 * I assume in that case that:
2445 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2446 * - index of insertion is at the end of existing buttons
2447 * I only see this happen with nIndex == -1, but it could have a special
2448 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2453 if(lpTbb->iString) {
2454 len = lstrlenA((char*)lpTbb->iString) + 2;
2455 ptr = COMCTL32_Alloc(len);
2456 nIndex = infoPtr->nNumButtons;
2457 strcpy(ptr, (char*)lpTbb->iString);
2458 ptr[len - 1] = 0; /* ended by two '\0' */
2459 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2463 ERR("lpTbb->iString is NULL\n");
2467 } else if (nIndex < 0)
2470 TRACE("inserting button index=%d\n", nIndex);
2471 if (nIndex > infoPtr->nNumButtons) {
2472 nIndex = infoPtr->nNumButtons;
2473 TRACE("adjust index=%d\n", nIndex);
2476 oldButtons = infoPtr->buttons;
2477 infoPtr->nNumButtons++;
2478 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2479 /* pre insert copy */
2481 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2482 nIndex * sizeof(TBUTTON_INFO));
2485 /* insert new button */
2486 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2487 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2488 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2489 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2490 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2491 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2493 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2496 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2497 ti.cbSize = sizeof (TTTOOLINFOA);
2499 ti.uId = lpTbb->idCommand;
2501 ti.lpszText = LPSTR_TEXTCALLBACKA;
2503 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2507 /* post insert copy */
2508 if (nIndex < infoPtr->nNumButtons - 1) {
2509 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2510 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2513 COMCTL32_Free (oldButtons);
2515 TOOLBAR_CalcToolbar (hwnd);
2517 InvalidateRect (hwnd, NULL, FALSE);
2524 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2526 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2527 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2528 INT nIndex = (INT)wParam;
2529 TBUTTON_INFO *oldButtons;
2536 TRACE("inserting button index=%d\n", nIndex);
2537 if (nIndex > infoPtr->nNumButtons) {
2538 nIndex = infoPtr->nNumButtons;
2539 TRACE("adjust index=%d\n", nIndex);
2542 oldButtons = infoPtr->buttons;
2543 infoPtr->nNumButtons++;
2544 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2545 /* pre insert copy */
2547 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2548 nIndex * sizeof(TBUTTON_INFO));
2551 /* insert new button */
2552 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2553 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2554 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2555 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2556 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2557 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2559 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2562 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2563 ti.cbSize = sizeof (TTTOOLINFOW);
2565 ti.uId = lpTbb->idCommand;
2567 ti.lpszText = LPSTR_TEXTCALLBACKW;
2569 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2573 /* post insert copy */
2574 if (nIndex < infoPtr->nNumButtons - 1) {
2575 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2576 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2579 COMCTL32_Free (oldButtons);
2581 TOOLBAR_CalcToolbar (hwnd);
2583 InvalidateRect (hwnd, NULL, FALSE);
2589 /* << TOOLBAR_InsertMarkHitTest >> */
2593 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2595 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2598 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2602 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2607 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2609 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2612 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2616 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2621 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2623 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2626 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2630 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2635 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2637 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2640 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2644 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2649 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2651 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2654 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2658 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2663 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2665 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2668 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2672 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2676 /* << TOOLBAR_LoadImages >> */
2677 /* << TOOLBAR_MapAccelerator >> */
2678 /* << TOOLBAR_MarkButton >> */
2679 /* << TOOLBAR_MoveButton >> */
2683 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2685 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2686 TBUTTON_INFO *btnPtr;
2689 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2693 btnPtr = &infoPtr->buttons[nIndex];
2694 if (LOWORD(lParam) == FALSE)
2695 btnPtr->fsState &= ~TBSTATE_PRESSED;
2697 btnPtr->fsState |= TBSTATE_PRESSED;
2699 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2705 /* << TOOLBAR_ReplaceBitmap >> */
2709 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2712 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2713 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2715 if (lpSave == NULL) return 0;
2718 /* save toolbar information */
2719 FIXME("save to \"%s\" \"%s\"\n",
2720 lpSave->pszSubKey, lpSave->pszValueName);
2725 /* restore toolbar information */
2727 FIXME("restore from \"%s\" \"%s\"\n",
2728 lpSave->pszSubKey, lpSave->pszValueName);
2739 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2742 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2743 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2749 /* save toolbar information */
2750 FIXME("save to \"%s\" \"%s\"\n",
2751 lpSave->pszSubKey, lpSave->pszValueName);
2756 /* restore toolbar information */
2758 FIXME("restore from \"%s\" \"%s\"\n",
2759 lpSave->pszSubKey, lpSave->pszValueName);
2770 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2772 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2773 BOOL bOldAnchor = infoPtr->bAnchor;
2775 infoPtr->bAnchor = (BOOL)wParam;
2777 return (LRESULT)bOldAnchor;
2782 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2784 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2786 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2789 if (infoPtr->nNumButtons > 0)
2790 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
2791 infoPtr->nNumButtons,
2792 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
2793 LOWORD(lParam), HIWORD(lParam));
2795 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2796 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2798 /* uses image list internals directly */
2799 if (infoPtr->himlDef) {
2800 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
2801 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
2809 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2811 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2812 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2813 TBUTTON_INFO *btnPtr;
2818 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2821 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2825 btnPtr = &infoPtr->buttons[nIndex];
2826 if (lptbbi->dwMask & TBIF_COMMAND)
2827 btnPtr->idCommand = lptbbi->idCommand;
2828 if (lptbbi->dwMask & TBIF_IMAGE)
2829 btnPtr->iBitmap = lptbbi->iImage;
2830 if (lptbbi->dwMask & TBIF_LPARAM)
2831 btnPtr->dwData = lptbbi->lParam;
2832 /* if (lptbbi->dwMask & TBIF_SIZE) */
2833 /* btnPtr->cx = lptbbi->cx; */
2834 if (lptbbi->dwMask & TBIF_STATE)
2835 btnPtr->fsState = lptbbi->fsState;
2836 if (lptbbi->dwMask & TBIF_STYLE)
2837 btnPtr->fsStyle = lptbbi->fsStyle;
2839 if (lptbbi->dwMask & TBIF_TEXT) {
2840 if ((btnPtr->iString >= 0) ||
2841 (btnPtr->iString < infoPtr->nNumStrings)) {
2842 TRACE("Ooooooch\n");
2844 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2845 INT len = lstrlenA (lptbbi->pszText);
2846 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2849 /* this is the ultimate sollution */
2850 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2859 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2861 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2862 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2863 TBUTTON_INFO *btnPtr;
2868 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2871 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2875 btnPtr = &infoPtr->buttons[nIndex];
2876 if (lptbbi->dwMask & TBIF_COMMAND)
2877 btnPtr->idCommand = lptbbi->idCommand;
2878 if (lptbbi->dwMask & TBIF_IMAGE)
2879 btnPtr->iBitmap = lptbbi->iImage;
2880 if (lptbbi->dwMask & TBIF_LPARAM)
2881 btnPtr->dwData = lptbbi->lParam;
2882 /* if (lptbbi->dwMask & TBIF_SIZE) */
2883 /* btnPtr->cx = lptbbi->cx; */
2884 if (lptbbi->dwMask & TBIF_STATE)
2885 btnPtr->fsState = lptbbi->fsState;
2886 if (lptbbi->dwMask & TBIF_STYLE)
2887 btnPtr->fsStyle = lptbbi->fsStyle;
2889 if (lptbbi->dwMask & TBIF_TEXT) {
2890 if ((btnPtr->iString >= 0) ||
2891 (btnPtr->iString < infoPtr->nNumStrings)) {
2893 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2894 INT len = lstrlenW (lptbbi->pszText);
2895 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2898 /* this is the ultimate solution */
2899 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2908 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2910 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2912 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2914 ERR("invalid parameter\n");
2918 /* Button size can only be set before adding any button to the toolbar
2919 according to the documentation. */
2920 /* this appears to be wrong. WINZIP32.EXE (ver 8) calls this on
2921 one of its buttons after adding it to the toolbar, and it
2922 checks that the return value is nonzero - mjm */
2923 if( infoPtr->nNumButtons != 0 )
2925 WARN("Button size set after button in toolbar\n");
2929 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2930 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2936 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2938 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2940 if (infoPtr == NULL)
2943 infoPtr->cxMin = (INT)LOWORD(lParam);
2944 infoPtr->cxMax = (INT)HIWORD(lParam);
2951 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2953 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2954 INT nIndex = (INT)wParam;
2956 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2959 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2961 if (infoPtr->hwndToolTip) {
2963 FIXME("change tool tip!\n");
2971 /* << TOOLBAR_SetColorScheme >> */
2975 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2977 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2978 HIMAGELIST himlTemp;
2981 himlTemp = infoPtr->himlDis;
2982 infoPtr->himlDis = (HIMAGELIST)lParam;
2984 /* FIXME: redraw ? */
2986 return (LRESULT)himlTemp;
2991 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2993 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2996 dwTemp = infoPtr->dwDTFlags;
2997 infoPtr->dwDTFlags =
2998 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
3000 return (LRESULT)dwTemp;
3005 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3007 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3010 dwTemp = infoPtr->dwExStyle;
3011 infoPtr->dwExStyle = (DWORD)lParam;
3013 return (LRESULT)dwTemp;
3018 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3020 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3021 HIMAGELIST himlTemp;
3023 himlTemp = infoPtr->himlHot;
3024 infoPtr->himlHot = (HIMAGELIST)lParam;
3026 /* FIXME: redraw ? */
3028 return (LRESULT)himlTemp;
3033 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3035 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3036 INT nOldHotItem = infoPtr->nHotItem;
3038 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3040 infoPtr->nHotItem = (INT)wParam;
3042 /* FIXME: What else must be done ??? */
3046 if (nOldHotItem < 0)
3049 return (LRESULT)nOldHotItem;
3054 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3056 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3057 HIMAGELIST himlTemp;
3059 himlTemp = infoPtr->himlDef;
3060 infoPtr->himlDef = (HIMAGELIST)lParam;
3062 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3063 /* FIXME: redraw ? */
3065 return (LRESULT)himlTemp;
3070 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3072 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3076 /* process only on indent changing */
3077 if(infoPtr->nIndent != (INT)wParam)
3079 infoPtr->nIndent = (INT)wParam;
3080 TOOLBAR_CalcToolbar (hwnd);
3081 InvalidateRect(hwnd, NULL, FALSE);
3088 /* << TOOLBAR_SetInsertMark >> */
3092 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3094 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3096 infoPtr->clrInsertMark = (COLORREF)lParam;
3098 /* FIXME : redraw ??*/
3105 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3107 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3109 if (infoPtr == NULL)
3112 infoPtr->nMaxTextRows = (INT)wParam;
3118 /* << TOOLBAR_SetPadding >> */
3122 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3124 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3129 if (infoPtr == NULL)
3131 hwndOldNotify = infoPtr->hwndNotify;
3132 infoPtr->hwndNotify = (HWND)wParam;
3134 return hwndOldNotify;
3139 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3141 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3142 LPRECT lprc = (LPRECT)lParam;
3146 if (LOWORD(wParam) > 1) {
3147 FIXME("multiple rows not supported!\n");
3150 if(infoPtr->nRows != LOWORD(wParam))
3152 infoPtr->nRows = LOWORD(wParam);
3154 /* recalculate toolbar */
3155 TOOLBAR_CalcToolbar (hwnd);
3157 /* repaint toolbar */
3158 InvalidateRect(hwnd, NULL, FALSE);
3161 /* return bounding rectangle */
3163 lprc->left = infoPtr->rcBound.left;
3164 lprc->right = infoPtr->rcBound.right;
3165 lprc->top = infoPtr->rcBound.top;
3166 lprc->bottom = infoPtr->rcBound.bottom;
3174 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3176 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3177 TBUTTON_INFO *btnPtr;
3180 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3184 btnPtr = &infoPtr->buttons[nIndex];
3186 /* process state changing if current state doesn't match new state */
3187 if(btnPtr->fsState != LOWORD(lParam))
3189 btnPtr->fsState = LOWORD(lParam);
3190 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3199 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3201 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3202 TBUTTON_INFO *btnPtr;
3205 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3209 btnPtr = &infoPtr->buttons[nIndex];
3211 /* process style change if current style doesn't match new style */
3212 if(btnPtr->fsStyle != LOWORD(lParam))
3214 btnPtr->fsStyle = LOWORD(lParam);
3215 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3218 if (infoPtr->hwndToolTip) {
3219 FIXME("change tool tip!\n");
3227 inline static LRESULT
3228 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3230 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3232 if (infoPtr == NULL)
3234 infoPtr->hwndToolTip = (HWND)wParam;
3240 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3242 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3245 TRACE("%s hwnd=0x%04x stub!\n",
3246 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3248 bTemp = infoPtr->bUnicode;
3249 infoPtr->bUnicode = (BOOL)wParam;
3256 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3258 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3259 INT iOldVersion = infoPtr->iVersion;
3261 infoPtr->iVersion = iVersion;
3268 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3270 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3271 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3274 /* initialize info structure */
3275 infoPtr->nButtonHeight = 22;
3276 infoPtr->nButtonWidth = 24;
3277 infoPtr->nBitmapHeight = 15;
3278 infoPtr->nBitmapWidth = 16;
3280 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3282 infoPtr->nMaxTextRows = 1;
3283 infoPtr->cxMin = -1;
3284 infoPtr->cxMax = -1;
3285 infoPtr->nNumBitmaps = 0;
3286 infoPtr->nNumStrings = 0;
3288 infoPtr->bCaptured = FALSE;
3289 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3290 infoPtr->nButtonDown = -1;
3291 infoPtr->nOldHit = -1;
3292 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3293 infoPtr->hwndNotify = GetParent (hwnd);
3294 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3295 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3296 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3297 infoPtr->iVersion = 0;
3299 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3300 infoPtr->hFont = CreateFontIndirectA (&logFont);
3302 if (dwStyle & TBSTYLE_TOOLTIPS) {
3303 /* Create tooltip control */
3304 infoPtr->hwndToolTip =
3305 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3306 CW_USEDEFAULT, CW_USEDEFAULT,
3307 CW_USEDEFAULT, CW_USEDEFAULT,
3310 /* Send NM_TOOLTIPSCREATED notification */
3311 if (infoPtr->hwndToolTip) {
3312 NMTOOLTIPSCREATED nmttc;
3314 nmttc.hdr.hwndFrom = hwnd;
3315 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3316 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3317 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3319 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3320 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3324 TOOLBAR_CalcToolbar(hwnd);
3331 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3333 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3335 /* delete tooltip control */
3336 if (infoPtr->hwndToolTip)
3337 DestroyWindow (infoPtr->hwndToolTip);
3339 /* delete button data */
3340 if (infoPtr->buttons)
3341 COMCTL32_Free (infoPtr->buttons);
3343 /* delete strings */
3344 if (infoPtr->strings) {
3346 for (i = 0; i < infoPtr->nNumStrings; i++)
3347 if (infoPtr->strings[i])
3348 COMCTL32_Free (infoPtr->strings[i]);
3350 COMCTL32_Free (infoPtr->strings);
3353 /* destroy internal image list */
3354 if (infoPtr->himlInt)
3355 ImageList_Destroy (infoPtr->himlInt);
3357 /* delete default font */
3359 DeleteObject (infoPtr->hFont);
3361 /* free toolbar info data */
3362 COMCTL32_Free (infoPtr);
3363 SetWindowLongA (hwnd, 0, 0);
3370 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3372 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3374 if (infoPtr->bTransparent)
3375 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3377 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3382 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3384 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3386 return infoPtr->hFont;
3391 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3393 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3394 TBUTTON_INFO *btnPtr;
3398 pt.x = (INT)LOWORD(lParam);
3399 pt.y = (INT)HIWORD(lParam);
3400 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3403 btnPtr = &infoPtr->buttons[nHit];
3404 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3407 infoPtr->bCaptured = TRUE;
3408 infoPtr->nButtonDown = nHit;
3410 btnPtr->fsState |= TBSTATE_PRESSED;
3412 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3415 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3416 TOOLBAR_Customize (hwnd);
3423 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3425 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3426 TBUTTON_INFO *btnPtr;
3430 if (infoPtr->hwndToolTip)
3431 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3432 WM_LBUTTONDOWN, wParam, lParam);
3434 pt.x = (INT)LOWORD(lParam);
3435 pt.y = (INT)HIWORD(lParam);
3436 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3440 btnPtr = &infoPtr->buttons[nHit];
3441 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3445 infoPtr->bCaptured = TRUE;
3446 infoPtr->nButtonDown = nHit;
3447 infoPtr->nOldHit = nHit;
3449 btnPtr->fsState |= TBSTATE_PRESSED;
3450 btnPtr->bHot = FALSE;
3452 CopyRect(&arrowRect, &btnPtr->rect);
3453 arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
3455 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
3456 if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
3457 !(TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && !PtInRect(&arrowRect, pt)))
3461 * this time we must force a Redraw, so the btn is
3462 * painted down before CaptureChanged repaints it up
3464 RedrawWindow(hwnd,&btnPtr->rect,0,
3465 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3467 nmtb.hdr.hwndFrom = hwnd;
3468 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3469 nmtb.hdr.code = TBN_DROPDOWN;
3470 nmtb.iItem = btnPtr->idCommand;
3472 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3473 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3476 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3484 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3486 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3487 TBUTTON_INFO *btnPtr;
3491 BOOL bSendMessage = TRUE;
3493 if (infoPtr->hwndToolTip)
3494 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3495 WM_LBUTTONUP, wParam, lParam);
3497 pt.x = (INT)LOWORD(lParam);
3498 pt.y = (INT)HIWORD(lParam);
3499 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3501 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3502 /* if the cursor is still inside of the toolbar */
3503 if((infoPtr->nHotItem >= 0) && (nHit != -1))
3504 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3506 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3507 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3508 btnPtr->fsState &= ~TBSTATE_PRESSED;
3510 if (nHit == infoPtr->nButtonDown) {
3511 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3512 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3513 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3514 infoPtr->nButtonDown);
3515 if (nOldIndex == infoPtr->nButtonDown)
3516 bSendMessage = FALSE;
3517 if ((nOldIndex != infoPtr->nButtonDown) &&
3519 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3520 btnPtr->fsState |= TBSTATE_CHECKED;
3523 if (btnPtr->fsState & TBSTATE_CHECKED)
3524 btnPtr->fsState &= ~TBSTATE_CHECKED;
3526 btnPtr->fsState |= TBSTATE_CHECKED;
3531 bSendMessage = FALSE;
3533 if (nOldIndex != -1)
3535 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
3536 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
3540 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
3541 * that resets bCaptured and btn TBSTATE_PRESSED flags,
3542 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
3547 SendMessageA (GetParent(hwnd), WM_COMMAND,
3548 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3555 TOOLBAR_CaptureChanged(HWND hwnd)
3557 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3558 TBUTTON_INFO *btnPtr;
3560 infoPtr->bCaptured = FALSE;
3562 if (infoPtr->nButtonDown >= 0)
3564 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3565 btnPtr->fsState &= ~TBSTATE_PRESSED;
3567 infoPtr->nButtonDown = -1;
3568 infoPtr->nOldHit = -1;
3570 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3577 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3579 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3580 TBUTTON_INFO *hotBtnPtr, *btnPtr;
3582 if (infoPtr->nOldHit < 0)
3585 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3587 /* Redraw the button if the last button we were over is the hot button and it
3589 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3591 hotBtnPtr->bHot = FALSE;
3593 InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
3597 /* If the last button we were over is depressed then make it not */
3598 /* depressed and redraw it */
3599 if(infoPtr->nOldHit == infoPtr->nButtonDown)
3601 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3603 btnPtr->fsState &= ~TBSTATE_PRESSED;
3605 InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
3608 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3609 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3615 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3617 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3618 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3621 TRACKMOUSEEVENT trackinfo;
3623 /* fill in the TRACKMOUSEEVENT struct */
3624 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3625 trackinfo.dwFlags = TME_QUERY;
3626 trackinfo.hwndTrack = hwnd;
3627 trackinfo.dwHoverTime = HOVER_DEFAULT;
3629 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3630 _TrackMouseEvent(&trackinfo);
3632 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3633 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3634 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3636 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3637 /* and can properly deactivate the hot toolbar button */
3638 _TrackMouseEvent(&trackinfo);
3641 if (infoPtr->hwndToolTip)
3642 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3643 WM_MOUSEMOVE, wParam, lParam);
3645 pt.x = (INT)LOWORD(lParam);
3646 pt.y = (INT)HIWORD(lParam);
3648 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3650 if (infoPtr->nOldHit != nHit)
3652 /* Remove the effect of an old hot button if the button was enabled and was
3653 drawn with the hot button effect */
3654 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
3655 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3657 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3658 oldBtnPtr->bHot = FALSE;
3660 InvalidateRect (hwnd, &oldBtnPtr->rect,
3661 TOOLBAR_HasText(infoPtr, oldBtnPtr));
3664 /* It's not a separator or in nowhere. It's a hot button. */
3667 btnPtr = &infoPtr->buttons[nHit];
3668 btnPtr->bHot = TRUE;
3670 infoPtr->nHotItem = nHit;
3672 /* only enabled buttons show hot effect */
3673 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3675 InvalidateRect(hwnd, &btnPtr->rect,
3676 TOOLBAR_HasText(infoPtr, btnPtr));
3681 if (infoPtr->bCaptured) {
3682 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3683 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3684 btnPtr->fsState &= ~TBSTATE_PRESSED;
3685 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3687 else if (nHit == infoPtr->nButtonDown) {
3688 btnPtr->fsState |= TBSTATE_PRESSED;
3689 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3692 infoPtr->nOldHit = nHit;
3698 inline static LRESULT
3699 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3701 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3702 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3704 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3708 inline static LRESULT
3709 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3711 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3712 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3714 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3719 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3721 TOOLBAR_INFO *infoPtr;
3723 /* allocate memory for info structure */
3724 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3725 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3728 infoPtr->dwStructSize = sizeof(TBBUTTON);
3730 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3731 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3732 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3733 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3736 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3741 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3743 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3747 if (dwStyle & WS_MINIMIZE)
3748 return 0; /* Nothing to do */
3750 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3752 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3755 if (!(dwStyle & CCS_NODIVIDER))
3757 GetWindowRect (hwnd, &rcWindow);
3758 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3759 if( dwStyle & WS_BORDER )
3760 OffsetRect (&rcWindow, 1, 1);
3761 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3764 ReleaseDC( hwnd, hdc );
3770 inline static LRESULT
3771 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3773 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3774 LPNMHDR lpnmh = (LPNMHDR)lParam;
3776 TRACE("passing WM_NOTIFY!\n");
3778 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3779 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3782 if (lpnmh->code == TTN_GETDISPINFOA) {
3783 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3785 FIXME("retrieving ASCII string\n");
3788 else if (lpnmh->code == TTN_GETDISPINFOW) {
3789 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3791 FIXME("retrieving UNICODE string\n");
3802 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3804 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3810 /* fill ps.rcPaint with a default rect */
3811 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
3813 TOOLBAR_CalcToolbar( hwnd );
3814 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
3815 TOOLBAR_Refresh (hwnd, hdc, &ps);
3816 if (!wParam) EndPaint (hwnd, &ps);
3823 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3825 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3826 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3835 /* Resize deadlock check */
3836 if (infoPtr->bAutoSize) {
3837 infoPtr->bAutoSize = FALSE;
3841 /* FIXME: optimize to only update size if the new size doesn't */
3842 /* match the current size */
3844 flags = (INT) wParam;
3846 /* FIXME for flags =
3847 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3850 TRACE("sizing toolbar!\n");
3852 if (flags == SIZE_RESTORED) {
3853 /* width and height don't apply */
3854 parent = GetParent (hwnd);
3855 GetClientRect(parent, &parent_rect);
3856 x = parent_rect.left;
3857 y = parent_rect.top;
3859 if (dwStyle & CCS_NORESIZE) {
3860 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3863 * this sets the working width of the toolbar, and
3864 * Calc Toolbar will not adjust it, only the height
3866 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3867 cy = infoPtr->nHeight;
3868 cx = infoPtr->nWidth;
3869 TOOLBAR_CalcToolbar (hwnd);
3870 infoPtr->nWidth = cx;
3871 infoPtr->nHeight = cy;
3874 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3875 TOOLBAR_CalcToolbar (hwnd);
3876 cy = infoPtr->nHeight;
3877 cx = infoPtr->nWidth;
3879 if (dwStyle & CCS_NOMOVEY) {
3880 GetWindowRect(hwnd, &window_rect);
3881 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3882 y = window_rect.top;
3886 if (dwStyle & CCS_NOPARENTALIGN) {
3887 uPosFlags |= SWP_NOMOVE;
3888 cy = infoPtr->nHeight;
3889 cx = infoPtr->nWidth;
3892 if (!(dwStyle & CCS_NODIVIDER))
3893 cy += GetSystemMetrics(SM_CYEDGE);
3895 if (dwStyle & WS_BORDER)
3898 cy += GetSystemMetrics(SM_CYEDGE);
3899 cx += GetSystemMetrics(SM_CYEDGE);
3902 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3903 cx, cy, uPosFlags | SWP_NOZORDER);
3910 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3912 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3914 if (nType == GWL_STYLE) {
3915 if (lpStyle->styleNew & TBSTYLE_LIST) {
3916 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3919 infoPtr->dwDTFlags = DT_CENTER;
3923 TOOLBAR_AutoSize (hwnd);
3925 InvalidateRect(hwnd, NULL, FALSE);
3932 static LRESULT WINAPI
3933 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3939 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3942 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3945 if (!TOOLBAR_GetInfoPtr (hwnd))
3947 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3953 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3955 case TB_ADDBUTTONSA:
3956 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3958 case TB_ADDBUTTONSW:
3959 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3962 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3965 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3968 return TOOLBAR_AutoSize (hwnd);
3970 case TB_BUTTONCOUNT:
3971 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3973 case TB_BUTTONSTRUCTSIZE:
3974 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3976 case TB_CHANGEBITMAP:
3977 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3979 case TB_CHECKBUTTON:
3980 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3982 case TB_COMMANDTOINDEX:
3983 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3986 return TOOLBAR_Customize (hwnd);
3988 case TB_DELETEBUTTON:
3989 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3991 case TB_ENABLEBUTTON:
3992 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3994 case TB_GETANCHORHIGHLIGHT:
3995 return TOOLBAR_GetAnchorHighlight (hwnd);
3998 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
4000 case TB_GETBITMAPFLAGS:
4001 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
4004 return TOOLBAR_GetButton (hwnd, wParam, lParam);
4006 case TB_GETBUTTONINFOA:
4007 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
4009 case TB_GETBUTTONINFOW:
4010 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
4012 case TB_GETBUTTONSIZE:
4013 return TOOLBAR_GetButtonSize (hwnd);
4015 case TB_GETBUTTONTEXTA:
4016 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
4018 case TB_GETBUTTONTEXTW:
4019 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
4021 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
4023 case TB_GETDISABLEDIMAGELIST:
4024 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
4026 case TB_GETEXTENDEDSTYLE:
4027 return TOOLBAR_GetExtendedStyle (hwnd);
4029 case TB_GETHOTIMAGELIST:
4030 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
4033 return TOOLBAR_GetHotItem (hwnd);
4035 case TB_GETIMAGELIST:
4036 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
4038 /* case TB_GETINSERTMARK: */ /* 4.71 */
4039 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
4041 case TB_GETITEMRECT:
4042 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
4045 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
4047 /* case TB_GETOBJECT: */ /* 4.71 */
4048 /* case TB_GETPADDING: */ /* 4.71 */
4051 return TOOLBAR_GetRect (hwnd, wParam, lParam);
4054 return TOOLBAR_GetRows (hwnd, wParam, lParam);
4057 return TOOLBAR_GetState (hwnd, wParam, lParam);
4060 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
4062 case TB_GETTEXTROWS:
4063 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
4065 case TB_GETTOOLTIPS:
4066 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
4068 case TB_GETUNICODEFORMAT:
4069 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
4071 case CCM_GETVERSION:
4072 return TOOLBAR_GetVersion (hwnd);
4075 return TOOLBAR_HideButton (hwnd, wParam, lParam);
4078 return TOOLBAR_HitTest (hwnd, wParam, lParam);
4080 case TB_INDETERMINATE:
4081 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
4083 case TB_INSERTBUTTONA:
4084 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
4086 case TB_INSERTBUTTONW:
4087 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
4089 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
4091 case TB_ISBUTTONCHECKED:
4092 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
4094 case TB_ISBUTTONENABLED:
4095 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
4097 case TB_ISBUTTONHIDDEN:
4098 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
4100 case TB_ISBUTTONHIGHLIGHTED:
4101 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
4103 case TB_ISBUTTONINDETERMINATE:
4104 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
4106 case TB_ISBUTTONPRESSED:
4107 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
4109 case TB_LOADIMAGES: /* 4.70 */
4110 FIXME("missing standard imagelists\n");
4113 /* case TB_MAPACCELERATORA: */ /* 4.71 */
4114 /* case TB_MAPACCELERATORW: */ /* 4.71 */
4115 /* case TB_MARKBUTTON: */ /* 4.71 */
4116 /* case TB_MOVEBUTTON: */ /* 4.71 */
4118 case TB_PRESSBUTTON:
4119 return TOOLBAR_PressButton (hwnd, wParam, lParam);
4121 /* case TB_REPLACEBITMAP: */
4123 case TB_SAVERESTOREA:
4124 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
4126 case TB_SAVERESTOREW:
4127 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
4129 case TB_SETANCHORHIGHLIGHT:
4130 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
4132 case TB_SETBITMAPSIZE:
4133 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
4135 case TB_SETBUTTONINFOA:
4136 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
4138 case TB_SETBUTTONINFOW:
4139 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
4141 case TB_SETBUTTONSIZE:
4142 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
4144 case TB_SETBUTTONWIDTH:
4145 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
4148 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
4150 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
4152 case TB_SETDISABLEDIMAGELIST:
4153 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
4155 case TB_SETDRAWTEXTFLAGS:
4156 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
4158 case TB_SETEXTENDEDSTYLE:
4159 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
4161 case TB_SETHOTIMAGELIST:
4162 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
4165 return TOOLBAR_SetHotItem (hwnd, wParam);
4167 case TB_SETIMAGELIST:
4168 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
4171 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
4173 /* case TB_SETINSERTMARK: */ /* 4.71 */
4175 case TB_SETINSERTMARKCOLOR:
4176 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
4178 case TB_SETMAXTEXTROWS:
4179 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
4181 /* case TB_SETPADDING: */ /* 4.71 */
4184 return TOOLBAR_SetParent (hwnd, wParam, lParam);
4187 return TOOLBAR_SetRows (hwnd, wParam, lParam);
4190 return TOOLBAR_SetState (hwnd, wParam, lParam);
4193 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
4195 case TB_SETTOOLTIPS:
4196 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
4198 case TB_SETUNICODEFORMAT:
4199 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
4201 case CCM_SETVERSION:
4202 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
4208 return TOOLBAR_Create (hwnd, wParam, lParam);
4211 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
4214 return TOOLBAR_GetFont (hwnd, wParam, lParam);
4216 /* case WM_KEYDOWN: */
4217 /* case WM_KILLFOCUS: */
4219 case WM_LBUTTONDBLCLK:
4220 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
4222 case WM_LBUTTONDOWN:
4223 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
4226 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4229 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4232 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
4234 case WM_CAPTURECHANGED:
4235 return TOOLBAR_CaptureChanged(hwnd);
4238 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4241 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4244 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4247 return TOOLBAR_Notify (hwnd, wParam, lParam);
4249 /* case WM_NOTIFYFORMAT: */
4252 return TOOLBAR_Paint (hwnd, wParam);
4255 return TOOLBAR_Size (hwnd, wParam, lParam);
4257 case WM_STYLECHANGED:
4258 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4260 /* case WM_SYSCOLORCHANGE: */
4262 /* case WM_WININICHANGE: */
4267 case WM_MEASUREITEM:
4269 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4272 if (uMsg >= WM_USER)
4273 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4274 uMsg, wParam, lParam);
4275 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4282 TOOLBAR_Register (void)
4286 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4287 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4288 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4289 wndClass.cbClsExtra = 0;
4290 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4291 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4292 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4293 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4295 RegisterClassA (&wndClass);
4300 TOOLBAR_Unregister (void)
4302 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);