4 * Copyright 1998,1999 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
8 * - A little bug in TOOLBAR_DrawMasked()
9 * - Button wrapping (under construction).
11 * - Notifications (under construction).
13 * - Tooltip support (almost complete).
14 * - Unicode suppport (under construction).
15 * - Fix TOOLBAR_SetButtonInfo32A/W.
16 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
17 * - I_IMAGECALLBACK support.
18 * - iString of -1 is undocumented
19 * - Customization dialog:
21 * - Minor buglet in 'available buttons' list:
22 * Buttons are not listed in M$-like order. M$ seems to use a single
23 * internal list to store the button information of both listboxes.
24 * - Drag list support.
25 * - Help and Reset button support.
28 * - Run tests using Waite Group Windows95 API Bible Volume 2.
29 * The second cdrom contains executables addstr.exe, btncount.exe,
30 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
31 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
32 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
33 * setparnt.exe, setrows.exe, toolwnd.exe.
34 * - Microsofts controlspy examples.
35 * - Charles Petzold's 'Programming Windows': gadgets.exe
44 #include "wine/unicode.h"
46 #include "imagelist.h"
48 #include "debugtools.h"
50 DEFAULT_DEBUG_CHANNEL(toolbar);
68 DWORD dwStructSize; /* size of TBBUTTON struct */
69 INT nHeight; /* height of the toolbar */
70 INT nWidth; /* width of the toolbar */
76 INT nRows; /* number of button rows */
77 INT nMaxTextRows; /* maximum number of text rows */
78 INT cxMin; /* minimum button width */
79 INT cxMax; /* maximum button width */
80 INT nNumButtons; /* number of buttons */
81 INT nNumBitmaps; /* number of bitmaps */
82 INT nNumStrings; /* number of strings */
83 BOOL bUnicode; /* ASCII (FALSE) or Unicode (TRUE)? */
84 BOOL bCaptured; /* mouse captured? */
87 INT nHotItem; /* index of the "hot" item */
88 HFONT hFont; /* text font */
89 HIMAGELIST himlInt; /* image list created internally */
90 HIMAGELIST himlDef; /* default image list */
91 HIMAGELIST himlHot; /* hot image list */
92 HIMAGELIST himlDis; /* disabled image list */
93 HWND hwndToolTip; /* handle to tool tip control */
94 HWND hwndNotify; /* handle to the window that gets notifications */
95 BOOL bTransparent; /* background transparency flag */
96 BOOL bAutoSize; /* auto size deadlock indicator */
97 BOOL bAnchor; /* anchor highlight enabled */
98 DWORD dwExStyle; /* extended toolbar style */
99 DWORD dwDTFlags; /* DrawText flags */
101 COLORREF clrInsertMark; /* insert mark color */
102 RECT rcBound; /* bounding rectangle */
105 TBUTTON_INFO *buttons; /* pointer to button array */
106 LPWSTR *strings; /* pointer to string array */
107 } TOOLBAR_INFO, *PTOOLBAR_INFO;
110 /* used by customization dialog */
113 PTOOLBAR_INFO tbInfo;
115 } CUSTDLG_INFO, *PCUSTDLG_INFO;
123 } CUSTOMBUTTON, *PCUSTOMBUTTON;
126 #define SEPARATOR_WIDTH 8
128 #define BOTTOM_BORDER 2
129 #define DDARROW_WIDTH 11
131 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
132 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
133 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
136 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
138 LPWSTR lpText = NULL;
140 /* FIXME: iString == -1 is undocumented */
141 if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
142 lpText = (LPWSTR)btnPtr->iString;
143 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
144 lpText = infoPtr->strings[btnPtr->iString];
150 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
152 if ((index>=0) && (index < infoPtr->nNumBitmaps))
160 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
162 INT x = (lpRect->left + lpRect->right) / 2 - 1;
163 INT yBottom = lpRect->bottom - 3;
164 INT yTop = lpRect->top + 1;
166 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
167 MoveToEx (hdc, x, yBottom, NULL);
168 LineTo (hdc, x, yTop);
170 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
171 MoveToEx (hdc, x, yBottom, NULL);
172 LineTo (hdc, x, yTop);
176 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
179 SelectObject ( hdc, GetSysColorPen (colorRef));
182 MoveToEx (hdc, x, y, NULL);
183 LineTo (hdc, x+5, y++); x++;
184 MoveToEx (hdc, x, y, NULL);
185 LineTo (hdc, x+3, y++); x++;
186 MoveToEx (hdc, x, y, NULL);
187 LineTo (hdc, x+1, y++);
191 * Draw the text string for this button.
192 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
193 * is non-zero, so we can simply check himlDef to see if we have
197 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
198 HDC hdc, INT nState, DWORD dwStyle)
200 RECT rcText = btnPtr->rect;
204 LPWSTR lpText = NULL;
205 HIMAGELIST himl = infoPtr->himlDef;
207 TRACE ("iString: %x\n", btnPtr->iString);
209 /* get a pointer to the text */
210 lpText = TOOLBAR_GetText(infoPtr, btnPtr);
212 TRACE ("lpText: %s\n", debugstr_w(lpText));
217 InflateRect (&rcText, -3, -3);
219 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
220 if ((dwStyle & TBSTYLE_LIST) &&
221 ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
222 (btnPtr->iBitmap != I_IMAGENONE)) {
223 rcText.left += infoPtr->nBitmapWidth;
226 rcText.top += infoPtr->nBitmapHeight;
230 rcText.top += infoPtr->nBitmapHeight;
233 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
234 OffsetRect (&rcText, 1, 1);
236 hOldFont = SelectObject (hdc, infoPtr->hFont);
237 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
238 if (!(nState & TBSTATE_ENABLED)) {
239 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
240 OffsetRect (&rcText, 1, 1);
241 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
242 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
243 OffsetRect (&rcText, -1, -1);
244 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
246 else if (nState & TBSTATE_INDETERMINATE) {
247 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
248 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
251 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
252 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
255 SetTextColor (hdc, clrOld);
256 SelectObject (hdc, hOldFont);
257 if (nOldBkMode != TRANSPARENT)
258 SetBkMode (hdc, nOldBkMode);
264 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
266 HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush);
267 INT cx = lpRect->right - lpRect->left;
268 INT cy = lpRect->bottom - lpRect->top;
269 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
270 SelectObject (hdc, hbr);
275 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
276 HDC hdc, INT x, INT y)
278 /* FIXME: this function is a hack since it uses image list
279 internals directly */
281 HIMAGELIST himl = infoPtr->himlDef;
289 /* create new dc's */
290 hdcImageList = CreateCompatibleDC (0);
291 hdcMask = CreateCompatibleDC (0);
293 /* create new bitmap */
294 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
295 SelectObject (hdcMask, hbmMask);
297 /* copy the mask bitmap */
298 SelectObject (hdcImageList, himl->hbmMask);
299 SetBkColor (hdcImageList, RGB(255, 255, 255));
300 SetTextColor (hdcImageList, RGB(0, 0, 0));
301 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
302 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
304 /* draw the new mask */
305 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
306 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
307 hdcMask, 0, 0, 0xB8074A);
309 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
310 BitBlt (hdc, x, y, himl->cx, himl->cy,
311 hdcMask, 0, 0, 0xB8074A);
313 DeleteObject (hbmMask);
315 DeleteDC (hdcImageList);
320 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
322 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
323 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
324 BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
325 (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
326 RECT rc, rcArrow, rcBitmap;
328 if (btnPtr->fsState & TBSTATE_HIDDEN)
332 CopyRect (&rcArrow, &rc);
333 CopyRect(&rcBitmap, &rc);
335 FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
337 if (hasDropDownArrow)
339 if (dwStyle & TBSTYLE_FLAT)
340 rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
342 rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
343 rcArrow.left = rc.right;
346 /* Center the bitmap horizontally and vertically */
347 rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
349 if(TOOLBAR_HasText(infoPtr, btnPtr))
350 rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
352 rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
354 TRACE("iBitmap: %d\n", btnPtr->iBitmap);
357 if (btnPtr->fsStyle & TBSTYLE_SEP) {
358 /* with the FLAT style, iBitmap is the width and has already */
359 /* been taken into consideration in calculating the width */
360 /* so now we need to draw the vertical separator */
361 /* empirical tests show that iBitmap can/will be non-zero */
362 /* when drawing the vertical bar... */
363 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
364 TOOLBAR_DrawFlatSeparator (&rc, hdc);
369 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
370 if (!(dwStyle & TBSTYLE_FLAT))
372 DrawEdge (hdc, &rc, EDGE_RAISED,
373 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
374 if (hasDropDownArrow)
375 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
376 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
379 if (hasDropDownArrow)
381 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
382 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
385 if (infoPtr->himlDis &&
386 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
387 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
388 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
390 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
392 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
396 /* pressed TBSTYLE_BUTTON */
397 if (btnPtr->fsState & TBSTATE_PRESSED) {
398 if (dwStyle & TBSTYLE_FLAT)
400 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
401 if (hasDropDownArrow)
402 DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
406 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
407 if (hasDropDownArrow)
408 DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
411 if (hasDropDownArrow)
412 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
414 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
415 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
416 rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
418 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
422 /* checked TBSTYLE_CHECK */
423 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
424 (btnPtr->fsState & TBSTATE_CHECKED)) {
425 if (dwStyle & TBSTYLE_FLAT)
426 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
427 BF_RECT | BF_MIDDLE | BF_ADJUST);
429 DrawEdge (hdc, &rc, EDGE_SUNKEN,
430 BF_RECT | BF_MIDDLE | BF_ADJUST);
432 TOOLBAR_DrawPattern (hdc, &rc);
434 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
435 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
436 rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
437 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
442 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
443 DrawEdge (hdc, &rc, EDGE_RAISED,
444 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
446 TOOLBAR_DrawPattern (hdc, &rc);
447 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
448 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
453 if (dwStyle & TBSTYLE_FLAT)
457 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
458 if (hasDropDownArrow)
459 DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
463 FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
464 if (hasDropDownArrow)
465 FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
468 if (hasDropDownArrow)
469 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
471 if (btnPtr->bHot && infoPtr->himlHot &&
472 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
473 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
474 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
475 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
476 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
477 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
481 DrawEdge (hdc, &rc, EDGE_RAISED,
482 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
484 if (hasDropDownArrow)
486 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
487 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
488 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
491 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
492 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
493 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
496 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
501 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
503 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
504 TBUTTON_INFO *btnPtr;
508 /* redraw necessary buttons */
509 btnPtr = infoPtr->buttons;
510 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
512 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
513 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
518 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
520 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
521 TBUTTON_INFO *btnPtr;
528 hOldFont = SelectObject (hdc, infoPtr->hFont);
530 btnPtr = &infoPtr->buttons[index];
532 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
533 (btnPtr->iString > -1) &&
534 (btnPtr->iString < infoPtr->nNumStrings))
536 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
537 GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
540 SelectObject (hdc, hOldFont);
543 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
547 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
549 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
550 TBUTTON_INFO *btnPtr;
558 btnPtr = infoPtr->buttons;
559 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
560 if(TOOLBAR_HasText(infoPtr, btnPtr))
562 TOOLBAR_MeasureString(hwnd,i,&sz);
563 if (sz.cx > lpSize->cx)
565 if (sz.cy > lpSize->cy)
570 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
573 /***********************************************************************
574 * TOOLBAR_WrapToolbar
576 * This function walks through the buttons and seperators in the
577 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
578 * wrapping should occur based on the width of the toolbar window.
579 * It does *not* calculate button placement itself. That task
580 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
581 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
582 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
586 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
588 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
589 TBUTTON_INFO *btnPtr;
592 BOOL bWrap, bButtonWrap;
594 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
595 /* no layout is necessary. Applications may use this style */
596 /* to perform their own layout on the toolbar. */
597 if( !(dwStyle & TBSTYLE_WRAPABLE) )
600 btnPtr = infoPtr->buttons;
601 x = infoPtr->nIndent;
603 /* this can get the parents width, to know how far we can extend
604 * this toolbar. We cannot use its height, as there may be multiple
605 * toolbars in a rebar control
607 GetClientRect( GetParent(hwnd), &rc );
608 infoPtr->nWidth = rc.right - rc.left;
611 for (i = 0; i < infoPtr->nNumButtons; i++ )
614 btnPtr[i].fsState &= ~TBSTATE_WRAP;
616 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
619 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
620 /* it is the actual width of the separator. This is used for */
621 /* custom controls in toolbars. */
622 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
623 cx = (btnPtr[i].iBitmap > 0) ?
624 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
626 cx = infoPtr->nButtonWidth;
628 /* Two or more adjacent separators form a separator group. */
629 /* The first separator in a group should be wrapped to the */
630 /* next row if the previous wrapping is on a button. */
632 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
633 (i + 1 < infoPtr->nNumButtons ) &&
634 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
636 btnPtr[i].fsState |= TBSTATE_WRAP;
637 x = infoPtr->nIndent;
643 /* The layout makes sure the bitmap is visible, but not the button. */
644 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
649 /* If the current button is a separator and not hidden, */
650 /* go to the next until it reaches a non separator. */
651 /* Wrap the last separator if it is before a button. */
652 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
653 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
654 i < infoPtr->nNumButtons )
660 if( bFound && i < infoPtr->nNumButtons )
663 btnPtr[i].fsState |= TBSTATE_WRAP;
664 x = infoPtr->nIndent;
668 else if ( i >= infoPtr->nNumButtons)
671 /* If the current button is not a separator, find the last */
672 /* separator and wrap it. */
673 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
675 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
676 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
680 x = infoPtr->nIndent;
681 btnPtr[j].fsState |= TBSTATE_WRAP;
687 /* If no separator available for wrapping, wrap one of */
688 /* non-hidden previous button. */
692 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
694 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
699 x = infoPtr->nIndent;
700 btnPtr[j].fsState |= TBSTATE_WRAP;
706 /* If all above failed, wrap the current button. */
709 btnPtr[i].fsState |= TBSTATE_WRAP;
711 x = infoPtr->nIndent;
712 if (btnPtr[i].fsState & TBSTYLE_SEP )
724 /***********************************************************************
725 * TOOLBAR_CalcToolbar
727 * This function calculates button and separator placement. It first
728 * calculates the button sizes, gets the toolbar window width and then
729 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
730 * on. It assigns a new location to each item and sends this location to
731 * the tooltip window if appropriate. Finally, it updates the rcBound
732 * rect and calculates the new required toolbar window height.
736 TOOLBAR_CalcToolbar (HWND hwnd)
738 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
739 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
740 TBUTTON_INFO *btnPtr;
741 INT i, nRows, nSepRows;
745 BOOL usesBitmaps = FALSE;
746 BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
748 TOOLBAR_CalcStrings (hwnd, &sizeString);
750 if (dwStyle & TBSTYLE_LIST)
752 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
753 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
756 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
758 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
762 if (sizeString.cy > 0)
765 infoPtr->nButtonHeight = sizeString.cy +
766 infoPtr->nBitmapHeight + 6;
768 infoPtr->nButtonHeight = sizeString.cy + 6;
770 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
771 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
773 if (sizeString.cx > infoPtr->nBitmapWidth)
774 infoPtr->nButtonWidth = sizeString.cx + 6;
775 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
776 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
779 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
780 infoPtr->nButtonWidth = infoPtr->cxMin;
781 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
782 infoPtr->nButtonWidth = infoPtr->cxMax;
784 TOOLBAR_WrapToolbar( hwnd, dwStyle );
786 x = infoPtr->nIndent;
787 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
790 * We will set the height below, and we set the width on entry
791 * so we do not reset them here..
794 GetClientRect( hwnd, &rc );
795 /* get initial values for toolbar */
796 infoPtr->nWidth = rc.right - rc.left;
797 infoPtr->nHeight = rc.bottom - rc.top;
800 /* from above, minimum is a button, and possible text */
801 cx = infoPtr->nButtonWidth;
803 /* cannot use just ButtonHeight, we may have no buttons! */
804 if (infoPtr->nNumButtons > 0)
805 infoPtr->nHeight = infoPtr->nButtonHeight;
807 cy = infoPtr->nHeight;
809 nRows = nSepRows = 0;
811 infoPtr->rcBound.top = y;
812 infoPtr->rcBound.left = x;
813 infoPtr->rcBound.bottom = y + cy;
814 infoPtr->rcBound.right = x;
816 btnPtr = infoPtr->buttons;
818 /* do not base height/width on parent, if the parent is a */
819 /* rebar control it could have multiple rows of toolbars */
820 /* GetClientRect( GetParent(hwnd), &rc ); */
821 /* cx = rc.right - rc.left; */
822 /* cy = rc.bottom - rc.top; */
824 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
827 if (btnPtr->fsState & TBSTATE_HIDDEN)
829 SetRectEmpty (&btnPtr->rect);
833 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
834 /* it is the actual width of the separator. This is used for */
835 /* custom controls in toolbars. */
836 if (btnPtr->fsStyle & TBSTYLE_SEP)
837 cx = (btnPtr->iBitmap > 0) ?
838 btnPtr->iBitmap : SEPARATOR_WIDTH;
841 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
844 TOOLBAR_MeasureString(hwnd,i,&sz);
848 cx = infoPtr->nButtonWidth;
850 if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
853 cy = infoPtr->nHeight;
855 if (btnPtr->fsState & TBSTATE_WRAP )
858 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
860 if (infoPtr->rcBound.left > x)
861 infoPtr->rcBound.left = x;
862 if (infoPtr->rcBound.right < x + cx)
863 infoPtr->rcBound.right = x + cx;
864 if (infoPtr->rcBound.bottom < y + cy)
865 infoPtr->rcBound.bottom = y + cy;
867 /* Set the toolTip only for non-hidden, non-separator button */
868 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
872 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
873 ti.cbSize = sizeof(TTTOOLINFOA);
875 ti.uId = btnPtr->idCommand;
876 ti.rect = btnPtr->rect;
877 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
881 /* btnPtr->nRow is zero based. The space between the rows is */
882 /* also considered as a row. */
883 btnPtr->nRow = nRows + nSepRows;
886 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
890 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
891 /* it is the actual width of the separator. This is used for */
892 /* custom controls in toolbars. */
893 y += cy + ( (btnPtr->iBitmap > 0 ) ?
894 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
896 /* nSepRows is used to calculate the extra height follwoing */
900 x = infoPtr->nIndent;
907 /* infoPtr->nRows is the number of rows on the toolbar */
908 infoPtr->nRows = nRows + nSepRows + 1;
910 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
912 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
913 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
914 nSepRows * (infoPtr->nBitmapHeight + 1) +
916 TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
921 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
923 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
924 TBUTTON_INFO *btnPtr;
927 btnPtr = infoPtr->buttons;
928 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
929 if (btnPtr->fsState & TBSTATE_HIDDEN)
932 if (btnPtr->fsStyle & TBSTYLE_SEP) {
933 if (PtInRect (&btnPtr->rect, *lpPt)) {
934 TRACE(" ON SEPARATOR %d!\n", i);
939 if (PtInRect (&btnPtr->rect, *lpPt)) {
940 TRACE(" ON BUTTON %d!\n", i);
946 TRACE(" NOWHERE!\n");
952 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
954 TBUTTON_INFO *btnPtr;
957 btnPtr = infoPtr->buttons;
958 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
959 if (btnPtr->idCommand == idCommand) {
960 TRACE("command=%d index=%d\n", idCommand, i);
964 TRACE("no index found for command=%d\n", idCommand);
970 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
972 TBUTTON_INFO *btnPtr;
975 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
978 /* check index button */
979 btnPtr = &infoPtr->buttons[nIndex];
980 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
981 if (btnPtr->fsState & TBSTATE_CHECKED)
985 /* check previous buttons */
986 nRunIndex = nIndex - 1;
987 while (nRunIndex >= 0) {
988 btnPtr = &infoPtr->buttons[nRunIndex];
989 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
990 if (btnPtr->fsState & TBSTATE_CHECKED)
998 /* check next buttons */
999 nRunIndex = nIndex + 1;
1000 while (nRunIndex < infoPtr->nNumButtons) {
1001 btnPtr = &infoPtr->buttons[nRunIndex];
1002 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1003 if (btnPtr->fsState & TBSTATE_CHECKED)
1016 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
1017 WPARAM wParam, LPARAM lParam)
1023 msg.wParam = wParam;
1024 msg.lParam = lParam;
1025 msg.time = GetMessageTime ();
1026 msg.pt.x = LOWORD(GetMessagePos ());
1027 msg.pt.y = HIWORD(GetMessagePos ());
1029 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1033 /***********************************************************************
1034 * TOOLBAR_CustomizeDialogProc
1035 * This function implements the toolbar customization dialog.
1038 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1040 PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongA (hwnd, DWL_USER);
1041 PCUSTOMBUTTON btnInfo;
1047 custInfo = (PCUSTDLG_INFO)lParam;
1048 SetWindowLongA (hwnd, DWL_USER, (DWORD)custInfo);
1056 /* send TBN_QUERYINSERT notification */
1057 nmtb.hdr.hwndFrom = hwnd;
1058 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1059 nmtb.hdr.code = TBN_QUERYINSERT;
1060 nmtb.iItem = custInfo->tbInfo->nNumButtons;
1062 if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1063 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1066 /* add items to 'toolbar buttons' list and check if removable */
1067 for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
1069 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1070 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1071 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1072 btnInfo->bVirtual = FALSE;
1073 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1075 /* send TBN_QUERYDELETE notification */
1076 nmtb.hdr.hwndFrom = hwnd;
1077 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1078 nmtb.hdr.code = TBN_QUERYDELETE;
1081 btnInfo->bRemovable = SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1082 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
1084 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
1085 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1088 /* insert separator button into 'available buttons' list */
1089 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1090 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1091 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1092 btnInfo->bVirtual = FALSE;
1093 btnInfo->bRemovable = TRUE;
1094 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1095 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1096 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1098 /* insert all buttons into dsa */
1101 /* send TBN_GETBUTTONINFO notification */
1102 nmtb.hdr.hwndFrom = hwnd;
1103 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1104 nmtb.hdr.code = TBN_GETBUTTONINFOA;
1106 nmtb.pszText = Buffer;
1109 if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1110 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1113 TRACE("style: %x\n", nmtb.tbButton.fsStyle);
1115 /* insert button into the apropriate list */
1116 index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand);
1119 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1120 memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1121 btnInfo->bVirtual = FALSE;
1122 btnInfo->bRemovable = TRUE;
1123 if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1124 strcpy (btnInfo->text, nmtb.pszText);
1126 index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1127 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1131 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1132 memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1133 if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1134 strcpy (btnInfo->text, nmtb.pszText);
1136 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1140 /* select first item in the 'available' list */
1141 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);
1143 /* append 'virtual' separator button to the 'toolbar buttons' list */
1144 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1145 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1146 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1147 btnInfo->bVirtual = TRUE;
1148 btnInfo->bRemovable = FALSE;
1149 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1150 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1151 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1153 /* select last item in the 'toolbar' list */
1154 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
1155 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);
1157 /* set focus and disable buttons */
1158 PostMessageA (hwnd, WM_USER, 0, 0);
1163 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1164 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1165 EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
1166 SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
1170 EndDialog(hwnd, FALSE);
1174 switch (LOWORD(wParam))
1176 case IDC_TOOLBARBTN_LBOX:
1177 if (HIWORD(wParam) == LBN_SELCHANGE)
1179 PCUSTOMBUTTON btnInfo;
1184 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1185 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1187 /* send TBN_QUERYINSERT notification */
1188 nmtb.hdr.hwndFrom = hwnd;
1189 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1190 nmtb.hdr.code = TBN_QUERYINSERT;
1193 SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1194 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
1196 /* get list box item */
1197 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1199 if (index == (count - 1))
1201 /* last item (virtual separator) */
1202 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1203 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1205 else if (index == (count - 2))
1207 /* second last item (last non-virtual item) */
1208 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1209 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1211 else if (index == 0)
1214 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1215 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1219 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1220 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1223 EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
1227 case IDC_MOVEUP_BTN:
1229 PCUSTOMBUTTON btnInfo;
1233 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1234 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1235 TRACE("Move up: index %d\n", index);
1237 /* send TBN_QUERYINSERT notification */
1238 nmtb.hdr.hwndFrom = hwnd;
1239 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1240 nmtb.hdr.code = TBN_QUERYINSERT;
1243 if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1244 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1246 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1248 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1249 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index-1, 0);
1250 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index-1, (LPARAM)btnInfo);
1251 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1254 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1255 else if (index >= (count - 3))
1256 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1258 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1259 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index-1, (LPARAM)&(btnInfo->btn));
1264 case IDC_MOVEDN_BTN: /* move down */
1266 PCUSTOMBUTTON btnInfo;
1270 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1271 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1272 TRACE("Move up: index %d\n", index);
1274 /* send TBN_QUERYINSERT notification */
1275 nmtb.hdr.hwndFrom = hwnd;
1276 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1277 nmtb.hdr.code = TBN_QUERYINSERT;
1280 if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1281 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1283 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1285 /* move button down */
1286 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1287 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index+1, 0);
1288 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index+1, (LPARAM)btnInfo);
1289 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index+1 , 0);
1292 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1293 else if (index >= (count - 3))
1294 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1296 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1297 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index+1, (LPARAM)&(btnInfo->btn));
1302 case IDC_REMOVE_BTN: /* remove button */
1304 PCUSTOMBUTTON btnInfo;
1307 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1308 TRACE("Remove: index %d\n", index);
1310 /* send TBN_QUERYDELETE notification */
1311 nmtb.hdr.hwndFrom = hwnd;
1312 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1313 nmtb.hdr.code = TBN_QUERYDELETE;
1316 if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1317 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1319 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1320 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1321 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index , 0);
1323 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1325 /* insert into 'available button' list */
1326 if (!(btnInfo->btn.fsStyle & TBSTYLE_SEP))
1328 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1329 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1332 COMCTL32_Free (btnInfo);
1337 case IDOK: /* Add button */
1342 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1343 index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
1344 TRACE("Add: index %d\n", index);
1346 /* send TBN_QUERYINSERT notification */
1347 nmtb.hdr.hwndFrom = hwnd;
1348 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1349 nmtb.hdr.code = TBN_QUERYINSERT;
1352 if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1353 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1355 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, index, 0);
1359 /* remove from 'available buttons' list */
1360 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_DELETESTRING, index, 0);
1361 if (index == count-1)
1362 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1364 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index , 0);
1368 PCUSTOMBUTTON btnNew;
1370 /* duplicate 'separator' button */
1371 btnNew = (PCUSTOMBUTTON)COMCTL32_Alloc (sizeof(CUSTOMBUTTON));
1372 memcpy (btnNew, btnInfo, sizeof(CUSTOMBUTTON));
1376 /* insert into 'toolbar button' list */
1377 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1378 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index, 0);
1379 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1381 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index, (LPARAM)&(btnInfo->btn));
1387 EndDialog(hwnd, FALSE);
1397 /* delete items from 'toolbar buttons' listbox*/
1398 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1399 for (i = 0; i < count; i++)
1401 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
1402 COMCTL32_Free(btnInfo);
1403 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
1405 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);
1408 /* delete items from 'available buttons' listbox*/
1409 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1410 for (i = 0; i < count; i++)
1412 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
1413 COMCTL32_Free(btnInfo);
1414 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
1416 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
1421 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1423 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1428 COLORREF oldText = 0;
1432 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0);
1433 if (btnInfo == NULL)
1435 FIXME("btnInfo invalid!\n");
1439 /* set colors and select objects */
1440 oldBk = SetBkColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1441 if (btnInfo->bVirtual)
1442 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
1444 oldText = SetTextColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHTTEXT:COLOR_WINDOWTEXT));
1445 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1446 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1448 /* fill background rectangle */
1449 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1450 lpdis->rcItem.right, lpdis->rcItem.bottom);
1452 /* calculate button and text rectangles */
1453 CopyRect (&rcButton, &lpdis->rcItem);
1454 InflateRect (&rcButton, -1, -1);
1455 CopyRect (&rcText, &rcButton);
1456 rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
1457 rcText.left = rcButton.right + 2;
1459 /* draw focus rectangle */
1460 if (lpdis->itemState & ODS_FOCUS)
1461 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1464 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1466 /* draw image and text */
1467 if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
1468 ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
1469 rcButton.left+3, rcButton.top+3, ILD_NORMAL);
1470 DrawTextA (lpdis->hDC, btnInfo->text, -1, &rcText,
1471 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1473 /* delete objects and reset colors */
1474 SelectObject (lpdis->hDC, hOldBrush);
1475 SelectObject (lpdis->hDC, hOldPen);
1476 SetBkColor (lpdis->hDC, oldBk);
1477 SetTextColor (lpdis->hDC, oldText);
1483 case WM_MEASUREITEM:
1484 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1486 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1488 if (custInfo && custInfo->tbInfo)
1489 lpmis->itemHeight = custInfo->tbInfo->nBitmapHeight + 8;
1491 lpmis->itemHeight = 15 + 8; /* default height */
1503 /***********************************************************************
1504 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1508 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1510 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1511 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1512 INT nIndex = 0, nButtons, nCount;
1515 TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1519 if (lpAddBmp->hInst == HINST_COMMCTRL)
1521 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1523 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1525 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1530 TRACE ("adding %d internal bitmaps!\n", nButtons);
1532 /* Windows resize all the buttons to the size of a newly added standard image */
1533 if (lpAddBmp->nID & 1)
1536 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
1537 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
1539 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1540 MAKELPARAM((WORD)24, (WORD)24));
1541 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1542 MAKELPARAM((WORD)31, (WORD)30));
1547 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1548 MAKELPARAM((WORD)16, (WORD)16));
1549 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1550 MAKELPARAM((WORD)22, (WORD)22));
1553 TOOLBAR_CalcToolbar (hwnd);
1557 nButtons = (INT)wParam;
1561 TRACE ("adding %d bitmaps!\n", nButtons);
1564 if (!(infoPtr->himlDef)) {
1565 /* create new default image list */
1566 TRACE ("creating default image list!\n");
1569 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1570 ILC_COLOR | ILC_MASK, nButtons, 2);
1571 infoPtr->himlInt = infoPtr->himlDef;
1574 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1576 /* Add bitmaps to the default image list */
1577 if (lpAddBmp->hInst == (HINSTANCE)0)
1580 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1583 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1585 /* Add system bitmaps */
1586 switch (lpAddBmp->nID)
1588 case IDB_STD_SMALL_COLOR:
1589 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1590 MAKEINTRESOURCEA(IDB_STD_SMALL));
1591 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1592 hbmLoad, CLR_DEFAULT);
1593 DeleteObject (hbmLoad);
1596 case IDB_STD_LARGE_COLOR:
1597 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1598 MAKEINTRESOURCEA(IDB_STD_LARGE));
1599 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1600 hbmLoad, CLR_DEFAULT);
1601 DeleteObject (hbmLoad);
1604 case IDB_VIEW_SMALL_COLOR:
1605 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1606 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1607 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1608 hbmLoad, CLR_DEFAULT);
1609 DeleteObject (hbmLoad);
1612 case IDB_VIEW_LARGE_COLOR:
1613 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1614 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1615 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1616 hbmLoad, CLR_DEFAULT);
1617 DeleteObject (hbmLoad);
1620 case IDB_HIST_SMALL_COLOR:
1621 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1622 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1623 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1624 hbmLoad, CLR_DEFAULT);
1625 DeleteObject (hbmLoad);
1628 case IDB_HIST_LARGE_COLOR:
1629 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1630 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1631 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1632 hbmLoad, CLR_DEFAULT);
1633 DeleteObject (hbmLoad);
1637 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1638 ERR ("invalid imagelist!\n");
1644 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1645 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1646 DeleteObject (hbmLoad);
1651 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1653 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1655 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",
1656 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1657 infoPtr->nNumBitmaps+nButtons,imagecount);
1659 infoPtr->nNumBitmaps = imagecount;
1662 infoPtr->nNumBitmaps += nButtons;
1665 InvalidateRect(hwnd, NULL, FALSE);
1672 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1674 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1675 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1676 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1678 TRACE("adding %d buttons!\n", wParam);
1680 nAddButtons = (UINT)wParam;
1681 nOldButtons = infoPtr->nNumButtons;
1682 nNewButtons = nOldButtons + nAddButtons;
1684 if (infoPtr->nNumButtons == 0) {
1686 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1689 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1691 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1692 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1693 nOldButtons * sizeof(TBUTTON_INFO));
1694 COMCTL32_Free (oldButtons);
1697 infoPtr->nNumButtons = nNewButtons;
1699 /* insert new button data */
1700 for (nCount = 0; nCount < nAddButtons; nCount++) {
1701 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1702 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1703 btnPtr->idCommand = lpTbb[nCount].idCommand;
1704 btnPtr->fsState = lpTbb[nCount].fsState;
1705 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1706 btnPtr->dwData = lpTbb[nCount].dwData;
1707 btnPtr->iString = lpTbb[nCount].iString;
1708 btnPtr->bHot = FALSE;
1710 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1713 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1714 ti.cbSize = sizeof (TTTOOLINFOA);
1716 ti.uId = btnPtr->idCommand;
1718 ti.lpszText = LPSTR_TEXTCALLBACKA;
1720 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1725 TOOLBAR_CalcToolbar (hwnd);
1727 InvalidateRect(hwnd, NULL, FALSE);
1734 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1736 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1737 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1738 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1740 TRACE("adding %d buttons!\n", wParam);
1742 nAddButtons = (UINT)wParam;
1743 nOldButtons = infoPtr->nNumButtons;
1744 nNewButtons = nOldButtons + nAddButtons;
1746 if (infoPtr->nNumButtons == 0) {
1748 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1751 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1753 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1754 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1755 nOldButtons * sizeof(TBUTTON_INFO));
1756 COMCTL32_Free (oldButtons);
1759 infoPtr->nNumButtons = nNewButtons;
1761 /* insert new button data */
1762 for (nCount = 0; nCount < nAddButtons; nCount++) {
1763 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1764 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1765 btnPtr->idCommand = lpTbb[nCount].idCommand;
1766 btnPtr->fsState = lpTbb[nCount].fsState;
1767 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1768 btnPtr->dwData = lpTbb[nCount].dwData;
1769 btnPtr->iString = lpTbb[nCount].iString;
1770 btnPtr->bHot = FALSE;
1772 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1775 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1776 ti.cbSize = sizeof (TTTOOLINFOW);
1778 ti.uId = btnPtr->idCommand;
1780 ti.lpszText = LPSTR_TEXTCALLBACKW;
1782 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1787 TOOLBAR_CalcToolbar (hwnd);
1789 InvalidateRect(hwnd, NULL, FALSE);
1796 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1798 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1801 if ((wParam) && (HIWORD(lParam) == 0)) {
1804 TRACE("adding string from resource!\n");
1806 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1809 TRACE("len=%d \"%s\"\n", len, szString);
1810 nIndex = infoPtr->nNumStrings;
1811 if (infoPtr->nNumStrings == 0) {
1813 COMCTL32_Alloc (sizeof(LPWSTR));
1816 LPWSTR *oldStrings = infoPtr->strings;
1818 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1819 memcpy (&infoPtr->strings[0], &oldStrings[0],
1820 sizeof(LPWSTR) * infoPtr->nNumStrings);
1821 COMCTL32_Free (oldStrings);
1824 lenW = MultiByteToWideChar( CP_ACP, 0, szString, -1, NULL, 0 );
1825 infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
1826 MultiByteToWideChar( CP_ACP, 0, szString, -1,
1827 infoPtr->strings[infoPtr->nNumStrings], lenW );
1828 infoPtr->nNumStrings++;
1831 LPSTR p = (LPSTR)lParam;
1836 TRACE("adding string(s) from array!\n");
1838 nIndex = infoPtr->nNumStrings;
1841 TRACE("len=%d \"%s\"\n", len, p);
1843 if (infoPtr->nNumStrings == 0) {
1845 COMCTL32_Alloc (sizeof(LPWSTR));
1848 LPWSTR *oldStrings = infoPtr->strings;
1850 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1851 memcpy (&infoPtr->strings[0], &oldStrings[0],
1852 sizeof(LPWSTR) * infoPtr->nNumStrings);
1853 COMCTL32_Free (oldStrings);
1856 lenW = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
1857 infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
1858 MultiByteToWideChar( CP_ACP, 0, p, -1,
1859 infoPtr->strings[infoPtr->nNumStrings], lenW );
1860 infoPtr->nNumStrings++;
1871 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1873 #define MAX_RESOURCE_STRING_LENGTH 512
1874 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1877 if ((wParam) && (HIWORD(lParam) == 0)) {
1878 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1880 TRACE("adding string from resource!\n");
1882 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1883 szString, MAX_RESOURCE_STRING_LENGTH);
1885 TRACE("len=%d %s\n", len, debugstr_w(szString));
1886 TRACE("First char: 0x%x\n", *szString);
1887 if (szString[0] == L'|')
1889 PWSTR p = szString + 1;
1891 nIndex = infoPtr->nNumStrings;
1892 while (*p != L'|') {
1894 if (infoPtr->nNumStrings == 0) {
1896 COMCTL32_Alloc (sizeof(LPWSTR));
1899 LPWSTR *oldStrings = infoPtr->strings;
1901 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1902 memcpy (&infoPtr->strings[0], &oldStrings[0],
1903 sizeof(LPWSTR) * infoPtr->nNumStrings);
1904 COMCTL32_Free (oldStrings);
1907 len = COMCTL32_StrChrW (p, L'|') - p;
1908 TRACE("len=%d %s\n", len, debugstr_w(p));
1909 infoPtr->strings[infoPtr->nNumStrings] =
1910 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1911 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1912 infoPtr->nNumStrings++;
1919 nIndex = infoPtr->nNumStrings;
1920 if (infoPtr->nNumStrings == 0) {
1922 COMCTL32_Alloc (sizeof(LPWSTR));
1925 LPWSTR *oldStrings = infoPtr->strings;
1927 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1928 memcpy (&infoPtr->strings[0], &oldStrings[0],
1929 sizeof(LPWSTR) * infoPtr->nNumStrings);
1930 COMCTL32_Free (oldStrings);
1933 infoPtr->strings[infoPtr->nNumStrings] =
1934 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1935 strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1936 infoPtr->nNumStrings++;
1940 LPWSTR p = (LPWSTR)lParam;
1945 TRACE("adding string(s) from array!\n");
1946 nIndex = infoPtr->nNumStrings;
1950 TRACE("len=%d %s\n", len, debugstr_w(p));
1951 if (infoPtr->nNumStrings == 0) {
1953 COMCTL32_Alloc (sizeof(LPWSTR));
1956 LPWSTR *oldStrings = infoPtr->strings;
1958 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1959 memcpy (&infoPtr->strings[0], &oldStrings[0],
1960 sizeof(LPWSTR) * infoPtr->nNumStrings);
1961 COMCTL32_Free (oldStrings);
1964 infoPtr->strings[infoPtr->nNumStrings] =
1965 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1966 strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1967 infoPtr->nNumStrings++;
1978 TOOLBAR_AutoSize (HWND hwnd)
1980 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1981 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1987 UINT uPosFlags = SWP_NOZORDER;
1989 TRACE("resize forced, style=%lx!\n", dwStyle);
1991 parent = GetParent (hwnd);
1992 GetClientRect(parent, &parent_rect);
1994 x = parent_rect.left;
1995 y = parent_rect.top;
1997 /* FIXME: we should be able to early out if nothing */
1998 /* has changed with nWidth != parent_rect width */
2000 if (dwStyle & CCS_NORESIZE) {
2001 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
2006 infoPtr->nWidth = parent_rect.right - parent_rect.left;
2007 TOOLBAR_CalcToolbar (hwnd);
2008 InvalidateRect( hwnd, NULL, TRUE );
2009 cy = infoPtr->nHeight;
2010 cx = infoPtr->nWidth;
2012 if (dwStyle & CCS_NOMOVEY) {
2013 GetWindowRect(hwnd, &window_rect);
2014 ScreenToClient(parent, (LPPOINT)&window_rect.left);
2015 y = window_rect.top;
2019 if (dwStyle & CCS_NOPARENTALIGN)
2020 uPosFlags |= SWP_NOMOVE;
2022 if (!(dwStyle & CCS_NODIVIDER))
2023 cy += GetSystemMetrics(SM_CYEDGE);
2025 if (dwStyle & WS_BORDER)
2028 cy += GetSystemMetrics(SM_CYEDGE);
2029 cx += GetSystemMetrics(SM_CYEDGE);
2032 infoPtr->bAutoSize = TRUE;
2033 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
2035 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2036 * the setwindowpos calls */
2037 infoPtr->bAutoSize = FALSE;
2044 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
2046 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2048 return infoPtr->nNumButtons;
2053 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2055 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2057 if (infoPtr == NULL) {
2058 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
2059 ERR("infoPtr == NULL!\n");
2063 infoPtr->dwStructSize = (DWORD)wParam;
2070 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2072 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2073 TBUTTON_INFO *btnPtr;
2076 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2080 btnPtr = &infoPtr->buttons[nIndex];
2081 btnPtr->iBitmap = LOWORD(lParam);
2083 /* we HAVE to erase the background, the new bitmap could be */
2085 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2092 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2094 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2095 TBUTTON_INFO *btnPtr;
2098 BOOL bChecked = FALSE;
2100 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2104 btnPtr = &infoPtr->buttons[nIndex];
2106 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
2109 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
2111 if (LOWORD(lParam) == FALSE)
2112 btnPtr->fsState &= ~TBSTATE_CHECKED;
2114 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2116 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
2117 if (nOldIndex == nIndex)
2119 if (nOldIndex != -1)
2120 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2122 btnPtr->fsState |= TBSTATE_CHECKED;
2125 if( bChecked != LOWORD(lParam) )
2127 if (nOldIndex != -1)
2129 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
2130 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
2132 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2135 /* FIXME: Send a WM_NOTIFY?? */
2142 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2144 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2146 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2151 TOOLBAR_Customize (HWND hwnd)
2153 CUSTDLG_INFO custInfo;
2159 custInfo.tbInfo = TOOLBAR_GetInfoPtr (hwnd);
2160 custInfo.tbHwnd = hwnd;
2162 /* send TBN_BEGINADJUST notification */
2163 nmhdr.hwndFrom = hwnd;
2164 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
2165 nmhdr.code = TBN_BEGINADJUST;
2167 SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2168 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2170 if (!(hRes = FindResourceA (COMCTL32_hModule,
2171 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
2175 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
2178 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
2179 (LPDLGTEMPLATEA)template,
2181 (DLGPROC)TOOLBAR_CustomizeDialogProc,
2184 /* send TBN_ENDADJUST notification */
2185 nmhdr.code = TBN_ENDADJUST;
2186 SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2187 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2194 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2196 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2197 INT nIndex = (INT)wParam;
2199 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2202 if ((infoPtr->hwndToolTip) &&
2203 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2206 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2207 ti.cbSize = sizeof (TTTOOLINFOA);
2209 ti.uId = infoPtr->buttons[nIndex].idCommand;
2211 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
2214 if (infoPtr->nNumButtons == 1) {
2215 TRACE(" simple delete!\n");
2216 COMCTL32_Free (infoPtr->buttons);
2217 infoPtr->buttons = NULL;
2218 infoPtr->nNumButtons = 0;
2221 TBUTTON_INFO *oldButtons = infoPtr->buttons;
2222 TRACE("complex delete! [nIndex=%d]\n", nIndex);
2224 infoPtr->nNumButtons--;
2225 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2227 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2228 nIndex * sizeof(TBUTTON_INFO));
2231 if (nIndex < infoPtr->nNumButtons) {
2232 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
2233 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
2236 COMCTL32_Free (oldButtons);
2239 TOOLBAR_CalcToolbar (hwnd);
2241 InvalidateRect (hwnd, NULL, TRUE);
2248 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2250 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2251 TBUTTON_INFO *btnPtr;
2255 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2259 btnPtr = &infoPtr->buttons[nIndex];
2261 bState = btnPtr->fsState & TBSTATE_ENABLED;
2263 /* update the toolbar button state */
2264 if(LOWORD(lParam) == FALSE) {
2265 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
2267 btnPtr->fsState |= TBSTATE_ENABLED;
2270 /* redraw the button only if the state of the button changed */
2271 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2273 InvalidateRect(hwnd, &btnPtr->rect,
2274 TOOLBAR_HasText(infoPtr, btnPtr));
2281 static inline LRESULT
2282 TOOLBAR_GetAnchorHighlight (HWND hwnd)
2284 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2286 return infoPtr->bAnchor;
2291 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2293 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2296 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2300 return infoPtr->buttons[nIndex].iBitmap;
2304 static inline LRESULT
2305 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2307 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
2312 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2314 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2315 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2316 INT nIndex = (INT)wParam;
2317 TBUTTON_INFO *btnPtr;
2319 if (infoPtr == NULL)
2325 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2328 btnPtr = &infoPtr->buttons[nIndex];
2329 lpTbb->iBitmap = btnPtr->iBitmap;
2330 lpTbb->idCommand = btnPtr->idCommand;
2331 lpTbb->fsState = btnPtr->fsState;
2332 lpTbb->fsStyle = btnPtr->fsStyle;
2333 lpTbb->dwData = btnPtr->dwData;
2334 lpTbb->iString = btnPtr->iString;
2341 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2343 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2344 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2345 TBUTTON_INFO *btnPtr;
2348 if (infoPtr == NULL)
2350 if (lpTbInfo == NULL)
2352 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2355 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2359 btnPtr = &infoPtr->buttons[nIndex];
2361 if (lpTbInfo->dwMask & TBIF_COMMAND)
2362 lpTbInfo->idCommand = btnPtr->idCommand;
2363 if (lpTbInfo->dwMask & TBIF_IMAGE)
2364 lpTbInfo->iImage = btnPtr->iBitmap;
2365 if (lpTbInfo->dwMask & TBIF_LPARAM)
2366 lpTbInfo->lParam = btnPtr->dwData;
2367 if (lpTbInfo->dwMask & TBIF_SIZE)
2368 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2369 if (lpTbInfo->dwMask & TBIF_STATE)
2370 lpTbInfo->fsState = btnPtr->fsState;
2371 if (lpTbInfo->dwMask & TBIF_STYLE)
2372 lpTbInfo->fsStyle = btnPtr->fsStyle;
2373 if (lpTbInfo->dwMask & TBIF_TEXT) {
2374 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2376 if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[btnPtr->iString], -1,
2377 lpTbInfo->pszText, lpTbInfo->cchText, NULL, NULL ))
2378 lpTbInfo->pszText[lpTbInfo->cchText-1] = 0;
2380 else lpTbInfo->pszText[0]=0;
2387 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2389 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2390 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2391 TBUTTON_INFO *btnPtr;
2394 if (infoPtr == NULL)
2396 if (lpTbInfo == NULL)
2398 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2401 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2405 btnPtr = &infoPtr->buttons[nIndex];
2407 if (lpTbInfo->dwMask & TBIF_COMMAND)
2408 lpTbInfo->idCommand = btnPtr->idCommand;
2409 if (lpTbInfo->dwMask & TBIF_IMAGE)
2410 lpTbInfo->iImage = btnPtr->iBitmap;
2411 if (lpTbInfo->dwMask & TBIF_LPARAM)
2412 lpTbInfo->lParam = btnPtr->dwData;
2413 if (lpTbInfo->dwMask & TBIF_SIZE)
2414 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2415 if (lpTbInfo->dwMask & TBIF_STATE)
2416 lpTbInfo->fsState = btnPtr->fsState;
2417 if (lpTbInfo->dwMask & TBIF_STYLE)
2418 lpTbInfo->fsStyle = btnPtr->fsStyle;
2419 if (lpTbInfo->dwMask & TBIF_TEXT) {
2420 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2421 lstrcpynW (lpTbInfo->pszText,
2422 (LPWSTR)infoPtr->strings[btnPtr->iString],
2431 TOOLBAR_GetButtonSize (HWND hwnd)
2433 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2435 return MAKELONG((WORD)infoPtr->nButtonWidth,
2436 (WORD)infoPtr->nButtonHeight);
2441 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2443 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2444 INT nIndex, nStringIndex;
2446 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2450 nStringIndex = infoPtr->buttons[nIndex].iString;
2452 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2454 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2460 return WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[nStringIndex], -1,
2461 (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1;
2466 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2468 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2469 INT nIndex, nStringIndex;
2471 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2475 nStringIndex = infoPtr->buttons[nIndex].iString;
2477 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2479 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2485 strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2487 return strlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2491 /* << TOOLBAR_GetColorScheme >> */
2495 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2497 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2499 return (LRESULT)infoPtr->himlDis;
2503 inline static LRESULT
2504 TOOLBAR_GetExtendedStyle (HWND hwnd)
2506 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2508 return infoPtr->dwExStyle;
2513 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2515 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2517 return (LRESULT)infoPtr->himlHot;
2522 TOOLBAR_GetHotItem (HWND hwnd)
2524 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2526 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2529 if (infoPtr->nHotItem < 0)
2532 return (LRESULT)infoPtr->nHotItem;
2537 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2539 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2541 return (LRESULT)infoPtr->himlDef;
2545 /* << TOOLBAR_GetInsertMark >> */
2546 /* << TOOLBAR_GetInsertMarkColor >> */
2550 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2552 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2553 TBUTTON_INFO *btnPtr;
2557 if (infoPtr == NULL)
2559 nIndex = (INT)wParam;
2560 btnPtr = &infoPtr->buttons[nIndex];
2561 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2563 lpRect = (LPRECT)lParam;
2566 if (btnPtr->fsState & TBSTATE_HIDDEN)
2569 lpRect->left = btnPtr->rect.left;
2570 lpRect->right = btnPtr->rect.right;
2571 lpRect->bottom = btnPtr->rect.bottom;
2572 lpRect->top = btnPtr->rect.top;
2579 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2581 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2582 LPSIZE lpSize = (LPSIZE)lParam;
2587 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2588 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2590 TRACE("maximum size %d x %d\n",
2591 infoPtr->rcBound.right - infoPtr->rcBound.left,
2592 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2598 /* << TOOLBAR_GetObject >> */
2599 /* << TOOLBAR_GetPadding >> */
2603 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2605 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2606 TBUTTON_INFO *btnPtr;
2610 if (infoPtr == NULL)
2612 nIndex = (INT)wParam;
2613 btnPtr = &infoPtr->buttons[nIndex];
2614 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2616 lpRect = (LPRECT)lParam;
2620 lpRect->left = btnPtr->rect.left;
2621 lpRect->right = btnPtr->rect.right;
2622 lpRect->bottom = btnPtr->rect.bottom;
2623 lpRect->top = btnPtr->rect.top;
2630 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2632 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2634 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2635 return infoPtr->nRows;
2642 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2644 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2647 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2651 return infoPtr->buttons[nIndex].fsState;
2656 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2658 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2661 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2665 return infoPtr->buttons[nIndex].fsStyle;
2670 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2674 if (infoPtr == NULL)
2677 return infoPtr->nMaxTextRows;
2682 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2684 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2686 if (infoPtr == NULL)
2688 return infoPtr->hwndToolTip;
2693 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2695 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2697 TRACE("%s hwnd=0x%x stub!\n",
2698 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2700 return infoPtr->bUnicode;
2704 inline static LRESULT
2705 TOOLBAR_GetVersion (HWND hwnd)
2707 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2708 return infoPtr->iVersion;
2713 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2715 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2716 TBUTTON_INFO *btnPtr;
2721 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2725 btnPtr = &infoPtr->buttons[nIndex];
2726 if (LOWORD(lParam) == FALSE)
2727 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2729 btnPtr->fsState |= TBSTATE_HIDDEN;
2731 TOOLBAR_CalcToolbar (hwnd);
2733 InvalidateRect (hwnd, NULL, TRUE);
2739 inline static LRESULT
2740 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2742 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2747 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2749 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2750 TBUTTON_INFO *btnPtr;
2753 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2757 btnPtr = &infoPtr->buttons[nIndex];
2758 if (LOWORD(lParam) == FALSE)
2759 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2761 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2763 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2770 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2772 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2773 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2774 INT nIndex = (INT)wParam;
2775 TBUTTON_INFO *oldButtons;
2781 /* EPP: this seems to be an undocumented call (from my IE4)
2782 * I assume in that case that:
2783 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2784 * - index of insertion is at the end of existing buttons
2785 * I only see this happen with nIndex == -1, but it could have a special
2786 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2791 /* FIXME: iString == -1 is undocumented */
2792 if(lpTbb->iString && lpTbb->iString!=-1) {
2793 len = strlen((char*)lpTbb->iString) + 2;
2794 ptr = COMCTL32_Alloc(len);
2795 nIndex = infoPtr->nNumButtons;
2796 strcpy(ptr, (char*)lpTbb->iString);
2797 ptr[len - 1] = 0; /* ended by two '\0' */
2798 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2802 ERR("lpTbb->iString is NULL\n");
2806 } else if (nIndex < 0)
2809 TRACE("inserting button index=%d\n", nIndex);
2810 if (nIndex > infoPtr->nNumButtons) {
2811 nIndex = infoPtr->nNumButtons;
2812 TRACE("adjust index=%d\n", nIndex);
2815 oldButtons = infoPtr->buttons;
2816 infoPtr->nNumButtons++;
2817 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2818 /* pre insert copy */
2820 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2821 nIndex * sizeof(TBUTTON_INFO));
2824 /* insert new button */
2825 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2826 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2827 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2828 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2829 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2830 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2832 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2835 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2836 ti.cbSize = sizeof (TTTOOLINFOA);
2838 ti.uId = lpTbb->idCommand;
2840 ti.lpszText = LPSTR_TEXTCALLBACKA;
2842 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2846 /* post insert copy */
2847 if (nIndex < infoPtr->nNumButtons - 1) {
2848 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2849 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2852 COMCTL32_Free (oldButtons);
2854 TOOLBAR_CalcToolbar (hwnd);
2856 InvalidateRect (hwnd, NULL, FALSE);
2863 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2865 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2866 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2867 INT nIndex = (INT)wParam;
2868 TBUTTON_INFO *oldButtons;
2875 TRACE("inserting button index=%d\n", nIndex);
2876 if (nIndex > infoPtr->nNumButtons) {
2877 nIndex = infoPtr->nNumButtons;
2878 TRACE("adjust index=%d\n", nIndex);
2881 oldButtons = infoPtr->buttons;
2882 infoPtr->nNumButtons++;
2883 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2884 /* pre insert copy */
2886 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2887 nIndex * sizeof(TBUTTON_INFO));
2890 /* insert new button */
2891 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2892 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2893 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2894 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2895 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2896 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2898 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2901 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2902 ti.cbSize = sizeof (TTTOOLINFOW);
2904 ti.uId = lpTbb->idCommand;
2906 ti.lpszText = LPSTR_TEXTCALLBACKW;
2908 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2912 /* post insert copy */
2913 if (nIndex < infoPtr->nNumButtons - 1) {
2914 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2915 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2918 COMCTL32_Free (oldButtons);
2920 InvalidateRect (hwnd, NULL, FALSE);
2926 /* << TOOLBAR_InsertMarkHitTest >> */
2930 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2932 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2935 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2939 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2944 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2946 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2949 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2953 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2958 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2960 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2963 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2967 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2972 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2974 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2977 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2981 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2986 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2988 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2991 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2995 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
3000 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
3002 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3005 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3009 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
3013 /* << TOOLBAR_LoadImages >> */
3014 /* << TOOLBAR_MapAccelerator >> */
3015 /* << TOOLBAR_MarkButton >> */
3016 /* << TOOLBAR_MoveButton >> */
3020 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3022 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3023 TBUTTON_INFO *btnPtr;
3026 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3030 btnPtr = &infoPtr->buttons[nIndex];
3031 if (LOWORD(lParam) == FALSE)
3032 btnPtr->fsState &= ~TBSTATE_PRESSED;
3034 btnPtr->fsState |= TBSTATE_PRESSED;
3036 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3042 /* << TOOLBAR_ReplaceBitmap >> */
3046 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3049 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3050 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
3052 if (lpSave == NULL) return 0;
3055 /* save toolbar information */
3056 FIXME("save to \"%s\" \"%s\"\n",
3057 lpSave->pszSubKey, lpSave->pszValueName);
3062 /* restore toolbar information */
3064 FIXME("restore from \"%s\" \"%s\"\n",
3065 lpSave->pszSubKey, lpSave->pszValueName);
3076 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3079 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3080 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
3086 /* save toolbar information */
3087 FIXME("save to \"%s\" \"%s\"\n",
3088 lpSave->pszSubKey, lpSave->pszValueName);
3093 /* restore toolbar information */
3095 FIXME("restore from \"%s\" \"%s\"\n",
3096 lpSave->pszSubKey, lpSave->pszValueName);
3107 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
3109 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3110 BOOL bOldAnchor = infoPtr->bAnchor;
3112 infoPtr->bAnchor = (BOOL)wParam;
3114 return (LRESULT)bOldAnchor;
3119 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3121 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3123 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3126 if (infoPtr->nNumButtons > 0)
3127 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
3128 infoPtr->nNumButtons,
3129 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
3130 LOWORD(lParam), HIWORD(lParam));
3132 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
3133 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
3135 /* uses image list internals directly */
3136 if (infoPtr->himlDef) {
3137 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
3138 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
3146 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3148 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3149 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
3150 TBUTTON_INFO *btnPtr;
3155 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
3158 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3162 btnPtr = &infoPtr->buttons[nIndex];
3163 if (lptbbi->dwMask & TBIF_COMMAND)
3164 btnPtr->idCommand = lptbbi->idCommand;
3165 if (lptbbi->dwMask & TBIF_IMAGE)
3166 btnPtr->iBitmap = lptbbi->iImage;
3167 if (lptbbi->dwMask & TBIF_LPARAM)
3168 btnPtr->dwData = lptbbi->lParam;
3169 /* if (lptbbi->dwMask & TBIF_SIZE) */
3170 /* btnPtr->cx = lptbbi->cx; */
3171 if (lptbbi->dwMask & TBIF_STATE)
3172 btnPtr->fsState = lptbbi->fsState;
3173 if (lptbbi->dwMask & TBIF_STYLE)
3174 btnPtr->fsStyle = lptbbi->fsStyle;
3176 if (lptbbi->dwMask & TBIF_TEXT) {
3177 if ((btnPtr->iString >= 0) ||
3178 (btnPtr->iString < infoPtr->nNumStrings)) {
3179 TRACE("Ooooooch\n");
3181 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3182 INT len = lstrlenA (lptbbi->pszText);
3183 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3186 /* this is the ultimate sollution */
3187 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3196 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3198 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3199 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
3200 TBUTTON_INFO *btnPtr;
3205 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
3208 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3212 btnPtr = &infoPtr->buttons[nIndex];
3213 if (lptbbi->dwMask & TBIF_COMMAND)
3214 btnPtr->idCommand = lptbbi->idCommand;
3215 if (lptbbi->dwMask & TBIF_IMAGE)
3216 btnPtr->iBitmap = lptbbi->iImage;
3217 if (lptbbi->dwMask & TBIF_LPARAM)
3218 btnPtr->dwData = lptbbi->lParam;
3219 /* if (lptbbi->dwMask & TBIF_SIZE) */
3220 /* btnPtr->cx = lptbbi->cx; */
3221 if (lptbbi->dwMask & TBIF_STATE)
3222 btnPtr->fsState = lptbbi->fsState;
3223 if (lptbbi->dwMask & TBIF_STYLE)
3224 btnPtr->fsStyle = lptbbi->fsStyle;
3226 if (lptbbi->dwMask & TBIF_TEXT) {
3227 if ((btnPtr->iString >= 0) ||
3228 (btnPtr->iString < infoPtr->nNumStrings)) {
3230 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3231 INT len = lstrlenW (lptbbi->pszText);
3232 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3235 /* this is the ultimate solution */
3236 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3245 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3247 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3249 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3251 ERR("invalid parameter\n");
3255 /* The documentation claims you can only change the button size before
3256 * any button has been added. But this is wrong.
3257 * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding
3258 * it to the toolbar, and it checks that the return value is nonzero - mjm
3259 * Further testing shows that we must actually perform the change too.
3261 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
3262 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
3268 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
3270 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3272 if (infoPtr == NULL)
3275 infoPtr->cxMin = (INT)LOWORD(lParam);
3276 infoPtr->cxMax = (INT)HIWORD(lParam);
3283 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
3285 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3286 INT nIndex = (INT)wParam;
3288 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3291 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
3293 if (infoPtr->hwndToolTip) {
3295 FIXME("change tool tip!\n");
3303 /* << TOOLBAR_SetColorScheme >> */
3307 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3309 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3310 HIMAGELIST himlTemp;
3313 himlTemp = infoPtr->himlDis;
3314 infoPtr->himlDis = (HIMAGELIST)lParam;
3316 /* FIXME: redraw ? */
3318 return (LRESULT)himlTemp;
3323 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
3325 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3328 dwTemp = infoPtr->dwDTFlags;
3329 infoPtr->dwDTFlags =
3330 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
3332 return (LRESULT)dwTemp;
3337 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3339 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3342 dwTemp = infoPtr->dwExStyle;
3343 infoPtr->dwExStyle = (DWORD)lParam;
3345 return (LRESULT)dwTemp;
3350 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3352 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3353 HIMAGELIST himlTemp;
3355 himlTemp = infoPtr->himlHot;
3356 infoPtr->himlHot = (HIMAGELIST)lParam;
3358 /* FIXME: redraw ? */
3360 return (LRESULT)himlTemp;
3365 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3367 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3368 INT nOldHotItem = infoPtr->nHotItem;
3369 TBUTTON_INFO *btnPtr;
3371 if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons)
3374 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3377 infoPtr->nHotItem = (INT)wParam;
3378 if ((INT)wParam >=0)
3380 btnPtr = &infoPtr->buttons[(INT)wParam];
3381 btnPtr->bHot = TRUE;
3382 InvalidateRect (hwnd, &btnPtr->rect,
3383 TOOLBAR_HasText(infoPtr, btnPtr));
3387 btnPtr = &infoPtr->buttons[nOldHotItem];
3388 btnPtr->bHot = FALSE;
3389 InvalidateRect (hwnd, &btnPtr->rect,
3390 TOOLBAR_HasText(infoPtr, btnPtr));
3394 if (nOldHotItem < 0)
3397 return (LRESULT)nOldHotItem;
3402 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3404 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3405 HIMAGELIST himlTemp;
3407 himlTemp = infoPtr->himlDef;
3408 infoPtr->himlDef = (HIMAGELIST)lParam;
3410 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3411 /* FIXME: redraw ? */
3413 return (LRESULT)himlTemp;
3418 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3420 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3422 infoPtr->nIndent = (INT)wParam;
3426 /* process only on indent changing */
3427 if(infoPtr->nIndent != (INT)wParam)
3429 infoPtr->nIndent = (INT)wParam;
3430 TOOLBAR_CalcToolbar (hwnd);
3431 InvalidateRect(hwnd, NULL, FALSE);
3438 /* << TOOLBAR_SetInsertMark >> */
3442 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3444 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3446 infoPtr->clrInsertMark = (COLORREF)lParam;
3448 /* FIXME : redraw ??*/
3455 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3457 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3459 if (infoPtr == NULL)
3462 infoPtr->nMaxTextRows = (INT)wParam;
3468 /* << TOOLBAR_SetPadding >> */
3472 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3474 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3479 if (infoPtr == NULL)
3481 hwndOldNotify = infoPtr->hwndNotify;
3482 infoPtr->hwndNotify = (HWND)wParam;
3484 return hwndOldNotify;
3489 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3491 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3492 LPRECT lprc = (LPRECT)lParam;
3496 if (LOWORD(wParam) > 1) {
3497 FIXME("multiple rows not supported!\n");
3500 if(infoPtr->nRows != LOWORD(wParam))
3502 infoPtr->nRows = LOWORD(wParam);
3504 /* recalculate toolbar */
3505 TOOLBAR_CalcToolbar (hwnd);
3507 /* repaint toolbar */
3508 InvalidateRect(hwnd, NULL, FALSE);
3511 /* return bounding rectangle */
3513 lprc->left = infoPtr->rcBound.left;
3514 lprc->right = infoPtr->rcBound.right;
3515 lprc->top = infoPtr->rcBound.top;
3516 lprc->bottom = infoPtr->rcBound.bottom;
3524 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3526 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3527 TBUTTON_INFO *btnPtr;
3530 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3534 btnPtr = &infoPtr->buttons[nIndex];
3536 /* process state changing if current state doesn't match new state */
3537 if(btnPtr->fsState != LOWORD(lParam))
3539 btnPtr->fsState = LOWORD(lParam);
3540 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3549 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3551 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3552 TBUTTON_INFO *btnPtr;
3555 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3559 btnPtr = &infoPtr->buttons[nIndex];
3561 /* process style change if current style doesn't match new style */
3562 if(btnPtr->fsStyle != LOWORD(lParam))
3564 btnPtr->fsStyle = LOWORD(lParam);
3565 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3568 if (infoPtr->hwndToolTip) {
3569 FIXME("change tool tip!\n");
3577 inline static LRESULT
3578 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3580 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3582 if (infoPtr == NULL)
3584 infoPtr->hwndToolTip = (HWND)wParam;
3590 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3592 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3595 TRACE("%s hwnd=0x%04x stub!\n",
3596 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3598 bTemp = infoPtr->bUnicode;
3599 infoPtr->bUnicode = (BOOL)wParam;
3606 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3608 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3609 INT iOldVersion = infoPtr->iVersion;
3611 infoPtr->iVersion = iVersion;
3618 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3620 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3621 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3624 /* initialize info structure */
3625 infoPtr->nButtonHeight = 22;
3626 infoPtr->nButtonWidth = 24;
3627 infoPtr->nBitmapHeight = 15;
3628 infoPtr->nBitmapWidth = 16;
3630 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3632 infoPtr->nMaxTextRows = 1;
3633 infoPtr->cxMin = -1;
3634 infoPtr->cxMax = -1;
3635 infoPtr->nNumBitmaps = 0;
3636 infoPtr->nNumStrings = 0;
3638 infoPtr->bCaptured = FALSE;
3639 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3640 infoPtr->nButtonDown = -1;
3641 infoPtr->nOldHit = -1;
3642 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3643 infoPtr->hwndNotify = GetParent (hwnd);
3644 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3645 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3646 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3647 infoPtr->iVersion = 0;
3649 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3650 infoPtr->hFont = CreateFontIndirectA (&logFont);
3652 if (dwStyle & TBSTYLE_TOOLTIPS) {
3653 /* Create tooltip control */
3654 infoPtr->hwndToolTip =
3655 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3656 CW_USEDEFAULT, CW_USEDEFAULT,
3657 CW_USEDEFAULT, CW_USEDEFAULT,
3660 /* Send NM_TOOLTIPSCREATED notification */
3661 if (infoPtr->hwndToolTip) {
3662 NMTOOLTIPSCREATED nmttc;
3664 nmttc.hdr.hwndFrom = hwnd;
3665 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3666 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3667 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3669 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3670 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3674 TOOLBAR_CalcToolbar(hwnd);
3681 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3683 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3685 /* delete tooltip control */
3686 if (infoPtr->hwndToolTip)
3687 DestroyWindow (infoPtr->hwndToolTip);
3689 /* delete button data */
3690 if (infoPtr->buttons)
3691 COMCTL32_Free (infoPtr->buttons);
3693 /* delete strings */
3694 if (infoPtr->strings) {
3696 for (i = 0; i < infoPtr->nNumStrings; i++)
3697 if (infoPtr->strings[i])
3698 COMCTL32_Free (infoPtr->strings[i]);
3700 COMCTL32_Free (infoPtr->strings);
3703 /* destroy internal image list */
3704 if (infoPtr->himlInt)
3705 ImageList_Destroy (infoPtr->himlInt);
3707 /* delete default font */
3709 DeleteObject (infoPtr->hFont);
3711 /* free toolbar info data */
3712 COMCTL32_Free (infoPtr);
3713 SetWindowLongA (hwnd, 0, 0);
3720 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3722 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3724 if (infoPtr->bTransparent)
3725 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3727 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3732 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3734 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3736 return infoPtr->hFont;
3741 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3743 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3744 TBUTTON_INFO *btnPtr;
3748 pt.x = (INT)LOWORD(lParam);
3749 pt.y = (INT)HIWORD(lParam);
3750 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3753 btnPtr = &infoPtr->buttons[nHit];
3754 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3757 infoPtr->bCaptured = TRUE;
3758 infoPtr->nButtonDown = nHit;
3760 btnPtr->fsState |= TBSTATE_PRESSED;
3762 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3765 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3766 TOOLBAR_Customize (hwnd);
3773 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3775 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3776 TBUTTON_INFO *btnPtr;
3780 if (infoPtr->hwndToolTip)
3781 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3782 WM_LBUTTONDOWN, wParam, lParam);
3784 pt.x = (INT)LOWORD(lParam);
3785 pt.y = (INT)HIWORD(lParam);
3786 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3790 btnPtr = &infoPtr->buttons[nHit];
3791 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3794 infoPtr->nOldHit = nHit;
3796 CopyRect(&arrowRect, &btnPtr->rect);
3797 arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
3799 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
3800 if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
3801 ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
3802 (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))
3806 * this time we must force a Redraw, so the btn is
3807 * painted down before CaptureChanged repaints it up
3809 RedrawWindow(hwnd,&btnPtr->rect,0,
3810 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3812 nmtb.hdr.hwndFrom = hwnd;
3813 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3814 nmtb.hdr.code = TBN_DROPDOWN;
3815 nmtb.iItem = btnPtr->idCommand;
3817 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3818 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3823 infoPtr->bCaptured = TRUE;
3824 infoPtr->nButtonDown = nHit;
3826 btnPtr->fsState |= TBSTATE_PRESSED;
3827 btnPtr->bHot = FALSE;
3829 InvalidateRect(hwnd, &btnPtr->rect,
3830 TOOLBAR_HasText(infoPtr, btnPtr));
3838 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3840 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3841 TBUTTON_INFO *btnPtr;
3845 BOOL bSendMessage = TRUE;
3847 if (infoPtr->hwndToolTip)
3848 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3849 WM_LBUTTONUP, wParam, lParam);
3851 pt.x = (INT)LOWORD(lParam);
3852 pt.y = (INT)HIWORD(lParam);
3853 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3855 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3856 /* if the cursor is still inside of the toolbar */
3857 if((infoPtr->nHotItem >= 0) && (nHit != -1))
3858 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3860 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3861 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3862 btnPtr->fsState &= ~TBSTATE_PRESSED;
3864 if (nHit == infoPtr->nButtonDown) {
3865 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3866 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3867 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3868 infoPtr->nButtonDown);
3869 if (nOldIndex == infoPtr->nButtonDown)
3870 bSendMessage = FALSE;
3871 if ((nOldIndex != infoPtr->nButtonDown) &&
3873 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3874 btnPtr->fsState |= TBSTATE_CHECKED;
3877 if (btnPtr->fsState & TBSTATE_CHECKED)
3878 btnPtr->fsState &= ~TBSTATE_CHECKED;
3880 btnPtr->fsState |= TBSTATE_CHECKED;
3885 bSendMessage = FALSE;
3887 if (nOldIndex != -1)
3889 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
3890 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
3894 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
3895 * that resets bCaptured and btn TBSTATE_PRESSED flags,
3896 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
3901 SendMessageA (GetParent(hwnd), WM_COMMAND,
3902 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3909 TOOLBAR_CaptureChanged(HWND hwnd)
3911 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3912 TBUTTON_INFO *btnPtr;
3914 infoPtr->bCaptured = FALSE;
3916 if (infoPtr->nButtonDown >= 0)
3918 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3919 btnPtr->fsState &= ~TBSTATE_PRESSED;
3921 infoPtr->nButtonDown = -1;
3922 infoPtr->nOldHit = -1;
3924 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3931 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3933 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3934 TBUTTON_INFO *hotBtnPtr, *btnPtr;
3936 if (infoPtr->nOldHit < 0)
3939 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3941 /* Redraw the button if the last button we were over is the hot button and it
3943 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3945 hotBtnPtr->bHot = FALSE;
3947 InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
3951 /* If the last button we were over is depressed then make it not */
3952 /* depressed and redraw it */
3953 if(infoPtr->nOldHit == infoPtr->nButtonDown)
3955 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3957 btnPtr->fsState &= ~TBSTATE_PRESSED;
3959 InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
3962 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3963 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3969 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3971 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3972 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3975 TRACKMOUSEEVENT trackinfo;
3977 /* fill in the TRACKMOUSEEVENT struct */
3978 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3979 trackinfo.dwFlags = TME_QUERY;
3980 trackinfo.hwndTrack = hwnd;
3981 trackinfo.dwHoverTime = HOVER_DEFAULT;
3983 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3984 _TrackMouseEvent(&trackinfo);
3986 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
3987 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3988 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3990 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
3991 /* and can properly deactivate the hot toolbar button */
3992 _TrackMouseEvent(&trackinfo);
3995 if (infoPtr->hwndToolTip)
3996 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3997 WM_MOUSEMOVE, wParam, lParam);
3999 pt.x = (INT)LOWORD(lParam);
4000 pt.y = (INT)HIWORD(lParam);
4002 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4004 if (infoPtr->nOldHit != nHit)
4006 /* Remove the effect of an old hot button if the button was enabled and was
4007 drawn with the hot button effect */
4008 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
4009 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
4011 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
4012 oldBtnPtr->bHot = FALSE;
4014 InvalidateRect (hwnd, &oldBtnPtr->rect,
4015 TOOLBAR_HasText(infoPtr, oldBtnPtr));
4018 /* It's not a separator or in nowhere. It's a hot button. */
4021 btnPtr = &infoPtr->buttons[nHit];
4022 btnPtr->bHot = TRUE;
4024 infoPtr->nHotItem = nHit;
4026 /* only enabled buttons show hot effect */
4027 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
4029 InvalidateRect(hwnd, &btnPtr->rect,
4030 TOOLBAR_HasText(infoPtr, btnPtr));
4035 if (infoPtr->bCaptured) {
4036 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4037 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
4038 btnPtr->fsState &= ~TBSTATE_PRESSED;
4039 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4041 else if (nHit == infoPtr->nButtonDown) {
4042 btnPtr->fsState |= TBSTATE_PRESSED;
4043 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4046 infoPtr->nOldHit = nHit;
4052 inline static LRESULT
4053 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4055 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
4056 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
4058 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
4062 inline static LRESULT
4063 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
4065 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
4066 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
4068 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
4073 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4075 TOOLBAR_INFO *infoPtr;
4077 /* allocate memory for info structure */
4078 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
4079 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
4082 infoPtr->dwStructSize = sizeof(TBBUTTON);
4084 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
4085 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
4086 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
4087 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
4090 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
4095 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
4097 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4101 if (dwStyle & WS_MINIMIZE)
4102 return 0; /* Nothing to do */
4104 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
4106 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
4109 if (!(dwStyle & CCS_NODIVIDER))
4111 GetWindowRect (hwnd, &rcWindow);
4112 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4113 if( dwStyle & WS_BORDER )
4114 OffsetRect (&rcWindow, 1, 1);
4115 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
4118 ReleaseDC( hwnd, hdc );
4124 inline static LRESULT
4125 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
4127 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4128 LPNMHDR lpnmh = (LPNMHDR)lParam;
4130 TRACE("passing WM_NOTIFY!\n");
4132 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
4133 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
4136 if (lpnmh->code == TTN_GETDISPINFOA) {
4137 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
4139 FIXME("retrieving ASCII string\n");
4142 else if (lpnmh->code == TTN_GETDISPINFOW) {
4143 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
4145 FIXME("retrieving UNICODE string\n");
4156 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
4158 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4164 /* fill ps.rcPaint with a default rect */
4165 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
4167 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
4168 TOOLBAR_Refresh (hwnd, hdc, &ps);
4169 if (!wParam) EndPaint (hwnd, &ps);
4176 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
4178 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4179 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4188 /* Resize deadlock check */
4189 if (infoPtr->bAutoSize) {
4190 infoPtr->bAutoSize = FALSE;
4194 /* FIXME: optimize to only update size if the new size doesn't */
4195 /* match the current size */
4197 flags = (INT) wParam;
4199 /* FIXME for flags =
4200 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
4203 TRACE("sizing toolbar!\n");
4205 if (flags == SIZE_RESTORED) {
4206 /* width and height don't apply */
4207 parent = GetParent (hwnd);
4208 GetClientRect(parent, &parent_rect);
4209 x = parent_rect.left;
4210 y = parent_rect.top;
4212 if (dwStyle & CCS_NORESIZE) {
4213 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
4216 * this sets the working width of the toolbar, and
4217 * Calc Toolbar will not adjust it, only the height
4219 infoPtr->nWidth = parent_rect.right - parent_rect.left;
4220 cy = infoPtr->nHeight;
4221 cx = infoPtr->nWidth;
4222 TOOLBAR_CalcToolbar (hwnd);
4223 infoPtr->nWidth = cx;
4224 infoPtr->nHeight = cy;
4227 infoPtr->nWidth = parent_rect.right - parent_rect.left;
4228 TOOLBAR_CalcToolbar (hwnd);
4229 cy = infoPtr->nHeight;
4230 cx = infoPtr->nWidth;
4232 if (dwStyle & CCS_NOMOVEY) {
4233 GetWindowRect(hwnd, &window_rect);
4234 ScreenToClient(parent, (LPPOINT)&window_rect.left);
4235 y = window_rect.top;
4239 if (dwStyle & CCS_NOPARENTALIGN) {
4240 uPosFlags |= SWP_NOMOVE;
4241 cy = infoPtr->nHeight;
4242 cx = infoPtr->nWidth;
4245 if (!(dwStyle & CCS_NODIVIDER))
4246 cy += GetSystemMetrics(SM_CYEDGE);
4248 if (dwStyle & WS_BORDER)
4251 cy += GetSystemMetrics(SM_CYEDGE);
4252 cx += GetSystemMetrics(SM_CYEDGE);
4255 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
4256 cx, cy, uPosFlags | SWP_NOZORDER);
4263 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
4265 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4267 if (nType == GWL_STYLE) {
4268 if (lpStyle->styleNew & TBSTYLE_LIST) {
4269 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
4272 infoPtr->dwDTFlags = DT_CENTER;
4276 TOOLBAR_AutoSize (hwnd);
4278 InvalidateRect(hwnd, NULL, FALSE);
4285 static LRESULT WINAPI
4286 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4288 if (!TOOLBAR_GetInfoPtr(hwnd) && (uMsg != WM_NCCREATE))
4289 return DefWindowProcA( hwnd, uMsg, wParam, lParam );
4294 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
4296 case TB_ADDBUTTONSA:
4297 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
4299 case TB_ADDBUTTONSW:
4300 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
4303 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
4306 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
4309 return TOOLBAR_AutoSize (hwnd);
4311 case TB_BUTTONCOUNT:
4312 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
4314 case TB_BUTTONSTRUCTSIZE:
4315 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
4317 case TB_CHANGEBITMAP:
4318 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
4320 case TB_CHECKBUTTON:
4321 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
4323 case TB_COMMANDTOINDEX:
4324 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
4327 return TOOLBAR_Customize (hwnd);
4329 case TB_DELETEBUTTON:
4330 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
4332 case TB_ENABLEBUTTON:
4333 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
4335 case TB_GETANCHORHIGHLIGHT:
4336 return TOOLBAR_GetAnchorHighlight (hwnd);
4339 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
4341 case TB_GETBITMAPFLAGS:
4342 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
4345 return TOOLBAR_GetButton (hwnd, wParam, lParam);
4347 case TB_GETBUTTONINFOA:
4348 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
4350 case TB_GETBUTTONINFOW:
4351 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
4353 case TB_GETBUTTONSIZE:
4354 return TOOLBAR_GetButtonSize (hwnd);
4356 case TB_GETBUTTONTEXTA:
4357 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
4359 case TB_GETBUTTONTEXTW:
4360 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
4362 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
4364 case TB_GETDISABLEDIMAGELIST:
4365 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
4367 case TB_GETEXTENDEDSTYLE:
4368 return TOOLBAR_GetExtendedStyle (hwnd);
4370 case TB_GETHOTIMAGELIST:
4371 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
4374 return TOOLBAR_GetHotItem (hwnd);
4376 case TB_GETIMAGELIST:
4377 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
4379 /* case TB_GETINSERTMARK: */ /* 4.71 */
4380 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
4382 case TB_GETITEMRECT:
4383 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
4386 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
4388 /* case TB_GETOBJECT: */ /* 4.71 */
4389 /* case TB_GETPADDING: */ /* 4.71 */
4392 return TOOLBAR_GetRect (hwnd, wParam, lParam);
4395 return TOOLBAR_GetRows (hwnd, wParam, lParam);
4398 return TOOLBAR_GetState (hwnd, wParam, lParam);
4401 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
4403 case TB_GETTEXTROWS:
4404 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
4406 case TB_GETTOOLTIPS:
4407 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
4409 case TB_GETUNICODEFORMAT:
4410 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
4412 case CCM_GETVERSION:
4413 return TOOLBAR_GetVersion (hwnd);
4416 return TOOLBAR_HideButton (hwnd, wParam, lParam);
4419 return TOOLBAR_HitTest (hwnd, wParam, lParam);
4421 case TB_INDETERMINATE:
4422 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
4424 case TB_INSERTBUTTONA:
4425 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
4427 case TB_INSERTBUTTONW:
4428 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
4430 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
4432 case TB_ISBUTTONCHECKED:
4433 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
4435 case TB_ISBUTTONENABLED:
4436 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
4438 case TB_ISBUTTONHIDDEN:
4439 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
4441 case TB_ISBUTTONHIGHLIGHTED:
4442 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
4444 case TB_ISBUTTONINDETERMINATE:
4445 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
4447 case TB_ISBUTTONPRESSED:
4448 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
4450 case TB_LOADIMAGES: /* 4.70 */
4451 FIXME("missing standard imagelists\n");
4454 /* case TB_MAPACCELERATORA: */ /* 4.71 */
4455 /* case TB_MAPACCELERATORW: */ /* 4.71 */
4456 /* case TB_MARKBUTTON: */ /* 4.71 */
4457 /* case TB_MOVEBUTTON: */ /* 4.71 */
4459 case TB_PRESSBUTTON:
4460 return TOOLBAR_PressButton (hwnd, wParam, lParam);
4462 /* case TB_REPLACEBITMAP: */
4464 case TB_SAVERESTOREA:
4465 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
4467 case TB_SAVERESTOREW:
4468 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
4470 case TB_SETANCHORHIGHLIGHT:
4471 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
4473 case TB_SETBITMAPSIZE:
4474 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
4476 case TB_SETBUTTONINFOA:
4477 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
4479 case TB_SETBUTTONINFOW:
4480 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
4482 case TB_SETBUTTONSIZE:
4483 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
4485 case TB_SETBUTTONWIDTH:
4486 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
4489 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
4491 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
4493 case TB_SETDISABLEDIMAGELIST:
4494 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
4496 case TB_SETDRAWTEXTFLAGS:
4497 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
4499 case TB_SETEXTENDEDSTYLE:
4500 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
4502 case TB_SETHOTIMAGELIST:
4503 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
4506 return TOOLBAR_SetHotItem (hwnd, wParam);
4508 case TB_SETIMAGELIST:
4509 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
4512 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
4514 /* case TB_SETINSERTMARK: */ /* 4.71 */
4516 case TB_SETINSERTMARKCOLOR:
4517 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
4519 case TB_SETMAXTEXTROWS:
4520 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
4522 /* case TB_SETPADDING: */ /* 4.71 */
4525 return TOOLBAR_SetParent (hwnd, wParam, lParam);
4528 return TOOLBAR_SetRows (hwnd, wParam, lParam);
4531 return TOOLBAR_SetState (hwnd, wParam, lParam);
4534 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
4536 case TB_SETTOOLTIPS:
4537 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
4539 case TB_SETUNICODEFORMAT:
4540 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
4542 case CCM_SETVERSION:
4543 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
4549 return TOOLBAR_Create (hwnd, wParam, lParam);
4552 return TOOLBAR_Destroy (hwnd, wParam, lParam);
4555 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
4558 return TOOLBAR_GetFont (hwnd, wParam, lParam);
4560 /* case WM_KEYDOWN: */
4561 /* case WM_KILLFOCUS: */
4563 case WM_LBUTTONDBLCLK:
4564 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
4566 case WM_LBUTTONDOWN:
4567 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
4570 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4573 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4576 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
4578 case WM_CAPTURECHANGED:
4579 return TOOLBAR_CaptureChanged(hwnd);
4582 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4585 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4588 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
4591 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4594 return TOOLBAR_Notify (hwnd, wParam, lParam);
4596 /* case WM_NOTIFYFORMAT: */
4599 return TOOLBAR_Paint (hwnd, wParam);
4602 return TOOLBAR_Size (hwnd, wParam, lParam);
4604 case WM_STYLECHANGED:
4605 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4607 /* case WM_SYSCOLORCHANGE: */
4609 /* case WM_WININICHANGE: */
4614 case WM_MEASUREITEM:
4616 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4619 if (uMsg >= WM_USER)
4620 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4621 uMsg, wParam, lParam);
4622 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4629 TOOLBAR_Register (void)
4633 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4634 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4635 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4636 wndClass.cbClsExtra = 0;
4637 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4638 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4639 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4640 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4642 RegisterClassA (&wndClass);
4647 TOOLBAR_Unregister (void)
4649 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);