4 * Copyright 1998,1999 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Differences between MSDN and actual native control operation:
22 * 1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
23 * to the right of the bitmap. Otherwise, this style is
24 * identical to TBSTYLE_FLAT."
25 * As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
26 * you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
27 * is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
28 * *not* imply TBSTYLE_FLAT as documented. (GA 8/2001)
32 * - A little bug in TOOLBAR_DrawMasked()
33 * - Button wrapping (under construction).
35 * - Notifications (under construction).
37 * - Tooltip support (almost complete).
38 * - Unicode suppport (under construction).
39 * - Fix TOOLBAR_SetButtonInfo32A/W.
40 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
41 * - I_IMAGECALLBACK support.
42 * - iString of -1 is undocumented
43 * - Customization dialog:
45 * - Minor buglet in 'available buttons' list:
46 * Buttons are not listed in M$-like order. M$ seems to use a single
47 * internal list to store the button information of both listboxes.
48 * - Drag list support.
49 * - Help and Reset button support.
52 * - Run tests using Waite Group Windows95 API Bible Volume 2.
53 * The second cdrom contains executables addstr.exe, btncount.exe,
54 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
55 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
56 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
57 * setparnt.exe, setrows.exe, toolwnd.exe.
58 * - Microsofts controlspy examples.
59 * - Charles Petzold's 'Programming Windows': gadgets.exe
68 #include "wine/unicode.h"
70 #include "imagelist.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(toolbar);
92 DWORD dwStructSize; /* size of TBBUTTON struct */
93 INT nHeight; /* height of the toolbar */
94 INT nWidth; /* width of the toolbar */
100 INT nRows; /* number of button rows */
101 INT nMaxTextRows; /* maximum number of text rows */
102 INT cxMin; /* minimum button width */
103 INT cxMax; /* maximum button width */
104 INT nNumButtons; /* number of buttons */
105 INT nNumBitmaps; /* number of bitmaps */
106 INT nNumStrings; /* number of strings */
107 BOOL bUnicode; /* ASCII (FALSE) or Unicode (TRUE)? */
108 BOOL bCaptured; /* mouse captured? */
111 INT nHotItem; /* index of the "hot" item */
113 HFONT hFont; /* text font */
114 HIMAGELIST himlInt; /* image list created internally */
115 HIMAGELIST himlDef; /* default image list */
116 HIMAGELIST himlHot; /* hot image list */
117 HIMAGELIST himlDis; /* disabled image list */
118 HWND hwndToolTip; /* handle to tool tip control */
119 HWND hwndNotify; /* handle to the window that gets notifications */
120 HWND hwndSelf; /* my own handle */
121 BOOL bTransparent; /* background transparency flag */
122 BOOL bBtnTranspnt; /* button transparency flag */
123 BOOL bAutoSize; /* auto size deadlock indicator */
124 BOOL bAnchor; /* anchor highlight enabled */
125 BOOL bNtfUnicode; /* TRUE if NOTIFYs use {W} */
126 BOOL bDoRedraw; /* Redraw status */
127 DWORD dwExStyle; /* extended toolbar style */
128 DWORD dwDTFlags; /* DrawText flags */
130 COLORREF clrInsertMark; /* insert mark color */
131 RECT rcBound; /* bounding rectangle */
134 TBUTTON_INFO *buttons; /* pointer to button array */
135 LPWSTR *strings; /* pointer to string array */
136 } TOOLBAR_INFO, *PTOOLBAR_INFO;
139 /* used by customization dialog */
142 PTOOLBAR_INFO tbInfo;
144 } CUSTDLG_INFO, *PCUSTDLG_INFO;
152 } CUSTOMBUTTON, *PCUSTOMBUTTON;
155 #define SEPARATOR_WIDTH 8
157 #define BOTTOM_BORDER 2
158 #define DDARROW_WIDTH 11
160 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
161 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
162 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
166 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
168 LPWSTR lpText = NULL;
170 /* FIXME: iString == -1 is undocumented */
171 if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
172 lpText = (LPWSTR)btnPtr->iString;
173 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
174 lpText = infoPtr->strings[btnPtr->iString];
180 TOOLBAR_DumpButton(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *bP, INT btn_num, BOOL internal)
182 if (TRACE_ON(toolbar)){
183 TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08x\n",
184 btn_num, bP->idCommand,
185 bP->iBitmap, bP->fsState, bP->fsStyle, bP->dwData, bP->iString);
186 TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr,bP)));
188 TRACE("button %d id %d, hot=%s, row=%d, rect=(%d,%d)-(%d,%d)\n",
189 btn_num, bP->idCommand,
190 (bP->bHot) ? "TRUE":"FALSE", bP->nRow,
191 bP->rect.left, bP->rect.top,
192 bP->rect.right, bP->rect.bottom);
198 TOOLBAR_DumpToolbar(TOOLBAR_INFO *iP, INT line)
200 if (TRACE_ON(toolbar)) {
204 dwStyle = GetWindowLongA (iP->hwndSelf, GWL_STYLE);
205 TRACE("toolbar %08x at line %d, exStyle=%08lx, buttons=%d, bitmaps=%d, strings=%d, style=%08lx\n",
207 iP->dwExStyle, iP->nNumButtons, iP->nNumBitmaps,
208 iP->nNumStrings, dwStyle);
209 TRACE("toolbar %08x at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p, redrawable=%s\n",
211 iP->himlInt, iP->himlDef, iP->himlHot, iP->himlDis,
212 (iP->bDoRedraw) ? "TRUE" : "FALSE");
213 for(i=0; i<iP->nNumButtons; i++) {
214 TOOLBAR_DumpButton(iP, &iP->buttons[i], i, TRUE);
220 /***********************************************************************
223 * This function validates that the styles set are implemented and
224 * issues FIXME's warning of possible problems. In a perfect world this
225 * function should be null.
228 TOOLBAR_CheckStyle (HWND hwnd, DWORD dwStyle)
230 if (dwStyle & TBSTYLE_ALTDRAG)
231 FIXME("[%04x] TBSTYLE_ALTDRAG not implemented\n", hwnd);
232 if (dwStyle & TBSTYLE_REGISTERDROP)
233 FIXME("[%04x] TBSTYLE_REGISTERDROP not implemented\n", hwnd);
238 TOOLBAR_SendNotify (NMHDR *nmhdr, TOOLBAR_INFO *infoPtr, UINT code)
240 if(!IsWindow(infoPtr->hwndSelf))
241 return 0; /* we have just been destroyed */
243 nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
244 nmhdr->hwndFrom = infoPtr->hwndSelf;
247 TRACE("to window %04x, code=%08x, %s\n", infoPtr->hwndNotify, code,
248 (infoPtr->bNtfUnicode) ? "via Unicode" : "via ANSI");
250 if (infoPtr->bNtfUnicode)
251 return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
252 (WPARAM) nmhdr->idFrom, (LPARAM)nmhdr);
254 return SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
255 (WPARAM) nmhdr->idFrom, (LPARAM)nmhdr);
258 /***********************************************************************
259 * TOOLBAR_GetBitmapIndex
261 * This function returns the bitmap index associated with a button.
262 * If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO
263 * is issued to retrieve the index.
266 TOOLBAR_GetBitmapIndex(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
268 INT ret = btnPtr->iBitmap;
270 if (ret == I_IMAGECALLBACK) {
271 /* issue TBN_GETDISPINFO */
274 nmgd.idCommand = btnPtr->idCommand;
275 nmgd.lParam = btnPtr->dwData;
276 nmgd.dwMask = TBNF_IMAGE;
277 TOOLBAR_SendNotify ((NMHDR *) &nmgd, infoPtr,
278 (infoPtr->bNtfUnicode) ? TBN_GETDISPINFOW :
280 if (nmgd.dwMask & TBNF_DI_SETITEM) {
281 btnPtr->iBitmap = nmgd.iImage;
284 TRACE("TBN_GETDISPINFOA returned bitmap id %d, mask=%08lx, nNumBitmaps=%d\n",
285 ret, nmgd.dwMask, infoPtr->nNumBitmaps);
292 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
294 if (((index>=0) && (index <= infoPtr->nNumBitmaps)) ||
295 (index == I_IMAGECALLBACK))
302 /***********************************************************************
303 * TOOLBAR_DrawImageList
305 * This function validates the bitmap index (including I_IMAGECALLBACK
306 * functionality). It then draws the image via the ImageList_Draw
307 * function. It returns TRUE if the image was drawn, FALSE otherwise.
310 TOOLBAR_DrawImageList (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl,
311 HDC hdc, UINT left, UINT top, UINT draw_flags)
315 if (!himl) return FALSE;
317 if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
318 ERR("index %d is not valid, max %d\n",
319 btnPtr->iBitmap, infoPtr->nNumBitmaps);
323 if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {
324 if (index == -1) return FALSE;
325 ERR("TBN_GETDISPINFO returned invalid index %d\n",
329 TRACE("drawing index=%d, himl=%p, left=%d, top=%d, flags=%08x\n",
330 index, himl, left, top, draw_flags);
332 ImageList_Draw (himl, index, hdc, left, top, draw_flags);
337 /***********************************************************************
338 * TOOLBAR_TestImageExist
340 * This function is similar to TOOLBAR_DrawImageList, except it does not
341 * draw the image. The I_IMAGECALLBACK functionality is implemented.
344 TOOLBAR_TestImageExist (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl)
348 if (!himl) return FALSE;
350 if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
351 ERR("index %d is not valid, max %d\n",
352 btnPtr->iBitmap, infoPtr->nNumBitmaps);
356 if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {
357 if (index == -1) return FALSE;
358 ERR("TBN_GETDISPINFO returned invalid index %d\n",
367 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
369 INT x = (lpRect->left + lpRect->right) / 2 - 1;
370 INT yBottom = lpRect->bottom - 3;
371 INT yTop = lpRect->top + 1;
373 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
374 MoveToEx (hdc, x, yBottom, NULL);
375 LineTo (hdc, x, yTop);
377 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
378 MoveToEx (hdc, x, yBottom, NULL);
379 LineTo (hdc, x, yTop);
383 /***********************************************************************
384 * TOOLBAR_DrawDDFlatSeparator
386 * This function draws the separator that was flaged as TBSTYLE_DROPDOWN.
387 * In this case, the separator is a pixel high line of COLOR_BTNSHADOW,
388 * followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators
389 * are horizontal as opposed to the vertical separators for not dropdown
392 * FIXME: It is possible that the height of each line is really SM_CYBORDER.
395 TOOLBAR_DrawDDFlatSeparator (LPRECT lpRect, HDC hdc, TBUTTON_INFO *btnPtr)
398 COLORREF oldcolor, newcolor;
400 myrect.left = lpRect->left;
401 myrect.right = lpRect->right;
402 myrect.top = lpRect->top + (lpRect->bottom - lpRect->top - 2)/2;
403 myrect.bottom = myrect.top + 1;
405 InflateRect (&myrect, -2, 0);
407 TRACE("rect=(%d,%d)-(%d,%d)\n",
408 myrect.left, myrect.top, myrect.right, myrect.bottom);
410 newcolor = GetSysColor (COLOR_BTNSHADOW);
411 oldcolor = SetBkColor (hdc, newcolor);
412 ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
414 myrect.top = myrect.bottom;
415 myrect.bottom = myrect.top + 1;
417 newcolor = GetSysColor (COLOR_BTNHIGHLIGHT);
418 SetBkColor (hdc, newcolor);
419 ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
421 SetBkColor (hdc, oldcolor);
426 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
429 SelectObject ( hdc, GetSysColorPen (colorRef));
432 MoveToEx (hdc, x, y, NULL);
433 LineTo (hdc, x+5, y++); x++;
434 MoveToEx (hdc, x, y, NULL);
435 LineTo (hdc, x+3, y++); x++;
436 MoveToEx (hdc, x, y, NULL);
437 LineTo (hdc, x+1, y++);
441 * Draw the text string for this button.
442 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
443 * is non-zero, so we can simply check himlDef to see if we have
447 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
448 HDC hdc, INT nState, DWORD dwStyle)
450 RECT rcText = btnPtr->rect;
453 LPWSTR lpText = NULL;
454 HIMAGELIST himl = infoPtr->himlDef;
456 TRACE ("iString: %x\n", btnPtr->iString);
458 /* get a pointer to the text */
459 lpText = TOOLBAR_GetText(infoPtr, btnPtr);
461 TRACE ("Stringtext: %s\n", debugstr_w(lpText));
466 InflateRect (&rcText, -3, -3);
468 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
469 /* The following test looked like this before
470 * I changed it. IE4 "Links" toolbar would not
471 * draw correctly with the original code. - GA 8/01
472 * ((dwStyle & TBSTYLE_LIST) &&
473 * ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
474 * (btnPtr->iBitmap != I_IMAGENONE))
476 if (dwStyle & TBSTYLE_LIST) {
477 /* LIST style w/ ICON offset is by matching native. */
478 /* Matches IE4 "Links" bar. - GA 8/01 */
479 rcText.left += (infoPtr->nBitmapWidth + 2);
482 rcText.top += infoPtr->nBitmapHeight + 1;
486 if (dwStyle & TBSTYLE_LIST) {
487 /* LIST style w/o ICON offset is by matching native. */
488 /* Matches IE4 "menu" bar. - GA 8/01 */
493 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
494 OffsetRect (&rcText, 1, 1);
496 TRACE("string rect=(%d,%d)-(%d,%d)\n",
497 rcText.left, rcText.top, rcText.right, rcText.bottom);
499 hOldFont = SelectObject (hdc, infoPtr->hFont);
500 if (!(nState & TBSTATE_ENABLED)) {
501 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
502 OffsetRect (&rcText, 1, 1);
503 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
504 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
505 OffsetRect (&rcText, -1, -1);
506 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
508 else if (nState & TBSTATE_INDETERMINATE) {
509 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
510 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
513 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
514 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
517 SetTextColor (hdc, clrOld);
518 SelectObject (hdc, hOldFont);
524 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
526 HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush);
527 INT cx = lpRect->right - lpRect->left;
528 INT cy = lpRect->bottom - lpRect->top;
529 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
530 SelectObject (hdc, hbr);
535 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
536 HDC hdc, INT x, INT y)
538 /* FIXME: this function is a hack since it uses image list
539 internals directly */
541 HIMAGELIST himl = infoPtr->himlDef;
549 /* create new dc's */
550 hdcImageList = CreateCompatibleDC (0);
551 hdcMask = CreateCompatibleDC (0);
553 /* create new bitmap */
554 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
555 SelectObject (hdcMask, hbmMask);
557 /* copy the mask bitmap */
558 SelectObject (hdcImageList, himl->hbmMask);
559 SetBkColor (hdcImageList, RGB(255, 255, 255));
560 SetTextColor (hdcImageList, RGB(0, 0, 0));
561 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
562 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
564 /* draw the new mask */
565 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
566 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
567 hdcMask, 0, 0, 0xB8074A);
569 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
570 BitBlt (hdc, x, y, himl->cx, himl->cy,
571 hdcMask, 0, 0, 0xB8074A);
573 DeleteObject (hbmMask);
575 DeleteDC (hdcImageList);
580 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
582 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
583 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
584 BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
585 (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
586 RECT rc, rcArrow, rcBitmap;
588 if (btnPtr->fsState & TBSTATE_HIDDEN)
592 CopyRect (&rcArrow, &rc);
593 CopyRect(&rcBitmap, &rc);
595 if (!infoPtr->bBtnTranspnt)
596 FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
598 if (hasDropDownArrow)
600 if (dwStyle & TBSTYLE_FLAT)
601 rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
603 rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
604 rcArrow.left = rc.right;
607 /* Center the bitmap horizontally and vertically */
608 if (dwStyle & TBSTYLE_LIST)
611 rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
613 if(TOOLBAR_HasText(infoPtr, btnPtr))
614 rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
616 rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
618 TRACE("iBitmap: %d, start=(%d,%d) w=%d, h=%d\n",
619 btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,
620 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
623 if (btnPtr->fsStyle & TBSTYLE_SEP) {
624 /* with the FLAT style, iBitmap is the width and has already */
625 /* been taken into consideration in calculating the width */
626 /* so now we need to draw the vertical separator */
627 /* empirical tests show that iBitmap can/will be non-zero */
628 /* when drawing the vertical bar... */
629 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */) {
630 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
631 TOOLBAR_DrawDDFlatSeparator (&rc, hdc, btnPtr);
633 TOOLBAR_DrawFlatSeparator (&rc, hdc);
639 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
640 if (!(dwStyle & TBSTYLE_FLAT))
642 DrawEdge (hdc, &rc, EDGE_RAISED,
643 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
644 if (hasDropDownArrow)
645 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
646 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
649 if (hasDropDownArrow)
651 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
652 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
655 if (!TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDis,
656 hdc, rcBitmap.left, rcBitmap.top,
658 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
660 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
664 /* pressed TBSTYLE_BUTTON */
665 if (btnPtr->fsState & TBSTATE_PRESSED) {
666 if (dwStyle & TBSTYLE_FLAT)
668 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
669 if (hasDropDownArrow)
670 DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
674 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
675 if (hasDropDownArrow)
676 DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
679 if (hasDropDownArrow)
680 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
682 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
683 hdc, rcBitmap.left+1, rcBitmap.top+1,
686 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
690 /* checked TBSTYLE_CHECK */
691 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
692 (btnPtr->fsState & TBSTATE_CHECKED)) {
693 if (dwStyle & TBSTYLE_FLAT)
694 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
695 BF_RECT | BF_ADJUST);
697 DrawEdge (hdc, &rc, EDGE_SUNKEN,
698 BF_RECT | BF_MIDDLE | BF_ADJUST);
700 TOOLBAR_DrawPattern (hdc, &rc);
702 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
703 hdc, rcBitmap.left+1, rcBitmap.top+1,
706 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
711 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
712 DrawEdge (hdc, &rc, EDGE_RAISED,
713 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
715 TOOLBAR_DrawPattern (hdc, &rc);
716 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
717 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
722 if (dwStyle & TBSTYLE_FLAT)
726 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT);
727 if (hasDropDownArrow)
728 DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT);
731 else /* The following code needs to be removed after
732 * "hot item" support has been implemented for the
733 * case where it is being de-selected.
736 FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
737 if (hasDropDownArrow)
738 FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
742 if (hasDropDownArrow)
743 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
746 /* if hot, attempt to draw with himlHot, if fails, use himlDef */
747 if (!TOOLBAR_DrawImageList (infoPtr, btnPtr,
750 rcBitmap.top, ILD_NORMAL))
751 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
752 hdc, rcBitmap.left, rcBitmap.top,
756 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
757 hdc, rcBitmap.left, rcBitmap.top,
762 DrawEdge (hdc, &rc, EDGE_RAISED,
763 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
765 if (hasDropDownArrow)
767 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
768 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
769 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
772 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
773 hdc, rcBitmap.left, rcBitmap.top,
777 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
782 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
784 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
785 TBUTTON_INFO *btnPtr;
786 INT i, oldBKmode = 0;
789 /* if imagelist belongs to the app, it can be changed
790 by the app after setting it */
791 if (infoPtr->himlDef != infoPtr->himlInt)
792 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
794 TOOLBAR_DumpToolbar (infoPtr, __LINE__);
796 if (infoPtr->bBtnTranspnt)
797 oldBKmode = SetBkMode (hdc, TRANSPARENT);
799 /* redraw necessary buttons */
800 btnPtr = infoPtr->buttons;
801 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
803 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
804 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
807 if (infoPtr->bBtnTranspnt && (oldBKmode != TRANSPARENT))
808 SetBkMode (hdc, oldBKmode);
811 /***********************************************************************
812 * TOOLBAR_MeasureString
814 * This function gets the width and height of a string in pixels. This
815 * is done first by using GetTextExtentPoint to get the basic width
816 * and height. The DrawText is called with DT_CALCRECT to get the exact
817 * width. The reason is because the text may have more than one "&" (or
818 * prefix characters as M$ likes to call them). The prefix character
819 * indicates where the underline goes, except for the string "&&" which
820 * is reduced to a single "&". GetTextExtentPoint does not process these
821 * only DrawText does. Note that the TBSTYLE_NOPREFIX is handled here.
824 TOOLBAR_MeasureString(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
825 HDC hdc, LPSIZE lpSize)
832 if (!(btnPtr->fsState & TBSTATE_HIDDEN) )
834 LPWSTR lpText = TOOLBAR_GetText(infoPtr, btnPtr);
837 /* first get size of all the text */
838 GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
840 /* feed above size into the rectangle for DrawText */
841 myrect.left = myrect.top = 0;
842 myrect.right = lpSize->cx;
843 myrect.bottom = lpSize->cy;
845 /* Use DrawText to get true size as drawn (less pesky "&") */
846 DrawTextW (hdc, lpText, -1, &myrect, DT_VCENTER | DT_SINGLELINE |
847 DT_CALCRECT | ((btnPtr->fsStyle & TBSTYLE_NOPREFIX) ?
850 /* feed back to caller */
851 lpSize->cx = myrect.right;
852 lpSize->cy = myrect.bottom;
856 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
859 /***********************************************************************
860 * TOOLBAR_CalcStrings
862 * This function walks through each string and measures it and returns
863 * the largest height and width to caller.
866 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
868 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
869 TBUTTON_INFO *btnPtr;
879 hOldFont = SelectObject (hdc, infoPtr->hFont);
881 btnPtr = infoPtr->buttons;
882 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
883 if(TOOLBAR_HasText(infoPtr, btnPtr))
885 TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
886 if (sz.cx > lpSize->cx)
888 if (sz.cy > lpSize->cy)
893 SelectObject (hdc, hOldFont);
894 ReleaseDC (hwnd, hdc);
896 TRACE("max string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
899 /***********************************************************************
900 * TOOLBAR_WrapToolbar
902 * This function walks through the buttons and seperators in the
903 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
904 * wrapping should occur based on the width of the toolbar window.
905 * It does *not* calculate button placement itself. That task
906 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
907 * the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE
908 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
910 * Note: TBSTYLE_WRAPABLE or CCS_VERT can be used also to allow vertical
915 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
917 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
918 TBUTTON_INFO *btnPtr;
921 BOOL bWrap, bButtonWrap;
923 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
924 /* no layout is necessary. Applications may use this style */
925 /* to perform their own layout on the toolbar. */
926 if( !(dwStyle & TBSTYLE_WRAPABLE) && !(dwStyle & CCS_VERT) )
929 btnPtr = infoPtr->buttons;
930 x = infoPtr->nIndent;
932 /* this can get the parents width, to know how far we can extend
933 * this toolbar. We cannot use its height, as there may be multiple
934 * toolbars in a rebar control
936 GetClientRect( GetParent(hwnd), &rc );
937 infoPtr->nWidth = rc.right - rc.left;
940 TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
941 infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth,
944 for (i = 0; i < infoPtr->nNumButtons; i++ )
947 btnPtr[i].fsState &= ~TBSTATE_WRAP;
949 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
952 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
953 /* it is the actual width of the separator. This is used for */
954 /* custom controls in toolbars. */
956 /* TBSTYLE_DROPDOWN separators are treated as buttons for */
957 /* width. - GA 8/01 */
958 if ((btnPtr[i].fsStyle & TBSTYLE_SEP) &&
959 !(btnPtr[i].fsStyle & TBSTYLE_DROPDOWN))
960 cx = (btnPtr[i].iBitmap > 0) ?
961 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
963 cx = infoPtr->nButtonWidth;
965 /* Two or more adjacent separators form a separator group. */
966 /* The first separator in a group should be wrapped to the */
967 /* next row if the previous wrapping is on a button. */
969 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
970 (i + 1 < infoPtr->nNumButtons ) &&
971 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
973 TRACE("wrap point 1 btn %d style %02x\n", i, btnPtr[i].fsStyle);
974 btnPtr[i].fsState |= TBSTATE_WRAP;
975 x = infoPtr->nIndent;
981 /* The layout makes sure the bitmap is visible, but not the button. */
982 /* Test added to also wrap after a button that starts a row but */
983 /* is bigger than the area. - GA 8/01 */
984 if (( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
985 > infoPtr->nWidth ) ||
986 ((x == infoPtr->nIndent) && (cx > infoPtr->nWidth)))
990 /* If the current button is a separator and not hidden, */
991 /* go to the next until it reaches a non separator. */
992 /* Wrap the last separator if it is before a button. */
993 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
994 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
995 i < infoPtr->nNumButtons )
1001 if( bFound && i < infoPtr->nNumButtons )
1004 TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
1005 i, btnPtr[i].fsStyle, x, cx);
1006 btnPtr[i].fsState |= TBSTATE_WRAP;
1007 x = infoPtr->nIndent;
1008 bButtonWrap = FALSE;
1011 else if ( i >= infoPtr->nNumButtons)
1014 /* If the current button is not a separator, find the last */
1015 /* separator and wrap it. */
1016 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
1018 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
1019 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
1023 TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
1024 i, btnPtr[i].fsStyle, x, cx);
1025 x = infoPtr->nIndent;
1026 btnPtr[j].fsState |= TBSTATE_WRAP;
1027 bButtonWrap = FALSE;
1032 /* If no separator available for wrapping, wrap one of */
1033 /* non-hidden previous button. */
1037 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
1039 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
1044 TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
1045 i, btnPtr[i].fsStyle, x, cx);
1046 x = infoPtr->nIndent;
1047 btnPtr[j].fsState |= TBSTATE_WRAP;
1053 /* If all above failed, wrap the current button. */
1056 TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
1057 i, btnPtr[i].fsStyle, x, cx);
1058 btnPtr[i].fsState |= TBSTATE_WRAP;
1060 x = infoPtr->nIndent;
1061 if (btnPtr[i].fsStyle & TBSTYLE_SEP )
1062 bButtonWrap = FALSE;
1068 TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
1069 i, btnPtr[i].fsStyle, x, cx);
1076 /***********************************************************************
1077 * TOOLBAR_CalcToolbar
1079 * This function calculates button and separator placement. It first
1080 * calculates the button sizes, gets the toolbar window width and then
1081 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
1082 * on. It assigns a new location to each item and sends this location to
1083 * the tooltip window if appropriate. Finally, it updates the rcBound
1084 * rect and calculates the new required toolbar window height.
1088 TOOLBAR_CalcToolbar (HWND hwnd)
1090 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
1091 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1092 TBUTTON_INFO *btnPtr;
1093 INT i, nRows, nSepRows;
1097 BOOL usesBitmaps = FALSE;
1098 BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
1100 TOOLBAR_CalcStrings (hwnd, &sizeString);
1102 if (dwStyle & TBSTYLE_LIST)
1104 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
1106 if (infoPtr->buttons[i].iBitmap >= 0)
1109 infoPtr->nButtonHeight = max((usesBitmaps) ? infoPtr->nBitmapHeight :
1110 0, sizeString.cy) + 6;
1111 infoPtr->nButtonWidth = ((usesBitmaps) ? infoPtr->nBitmapWidth :
1112 0) + sizeString.cx + 6;
1113 TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n",
1114 infoPtr->nButtonWidth, infoPtr->nButtonHeight, usesBitmaps,
1115 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
1116 TOOLBAR_DumpToolbar (infoPtr, __LINE__);
1119 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
1121 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
1125 if (sizeString.cy > 0)
1128 infoPtr->nButtonHeight = sizeString.cy +
1129 2 + /* this is the space to separate text from bitmap */
1130 infoPtr->nBitmapHeight + 6;
1132 infoPtr->nButtonHeight = sizeString.cy + 6;
1134 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
1135 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
1137 if (sizeString.cx > infoPtr->nBitmapWidth)
1138 infoPtr->nButtonWidth = sizeString.cx + 6;
1139 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
1140 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
1143 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
1144 infoPtr->nButtonWidth = infoPtr->cxMin;
1145 if ( infoPtr->cxMax > 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
1146 infoPtr->nButtonWidth = infoPtr->cxMax;
1148 TOOLBAR_WrapToolbar( hwnd, dwStyle );
1150 x = infoPtr->nIndent;
1154 * We will set the height below, and we set the width on entry
1155 * so we do not reset them here..
1158 GetClientRect( hwnd, &rc );
1159 /* get initial values for toolbar */
1160 infoPtr->nWidth = rc.right - rc.left;
1161 infoPtr->nHeight = rc.bottom - rc.top;
1164 /* from above, minimum is a button, and possible text */
1165 cx = infoPtr->nButtonWidth;
1167 /* cannot use just ButtonHeight, we may have no buttons! */
1168 if (infoPtr->nNumButtons > 0)
1169 infoPtr->nHeight = infoPtr->nButtonHeight;
1171 cy = infoPtr->nHeight;
1173 nRows = nSepRows = 0;
1175 infoPtr->rcBound.top = y;
1176 infoPtr->rcBound.left = x;
1177 infoPtr->rcBound.bottom = y + cy;
1178 infoPtr->rcBound.right = x;
1180 btnPtr = infoPtr->buttons;
1182 /* do not base height/width on parent, if the parent is a */
1183 /* rebar control it could have multiple rows of toolbars */
1184 /* GetClientRect( GetParent(hwnd), &rc ); */
1185 /* cx = rc.right - rc.left; */
1186 /* cy = rc.bottom - rc.top; */
1188 TRACE("cy=%d\n", cy);
1190 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
1193 if (btnPtr->fsState & TBSTATE_HIDDEN)
1195 SetRectEmpty (&btnPtr->rect);
1199 cy = infoPtr->nHeight;
1201 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1202 /* it is the actual width of the separator. This is used for */
1203 /* custom controls in toolbars. */
1204 if (btnPtr->fsStyle & TBSTYLE_SEP) {
1205 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
1206 cy = (btnPtr->iBitmap > 0) ?
1207 btnPtr->iBitmap : SEPARATOR_WIDTH;
1208 cx = infoPtr->nButtonWidth;
1211 cx = (btnPtr->iBitmap > 0) ?
1212 btnPtr->iBitmap : SEPARATOR_WIDTH;
1216 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
1223 hOldFont = SelectObject (hdc, infoPtr->hFont);
1225 TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
1227 SelectObject (hdc, hOldFont);
1228 ReleaseDC (hwnd, hdc);
1230 /* Fudge amount measured against IE4 "menu" and "Links" */
1231 /* toolbars with native control (v4.71). - GA 8/01 */
1232 cx = sz.cx + 6 + 5 + 5;
1233 if ((dwStyle & TBSTYLE_LIST) &&
1234 (TOOLBAR_TestImageExist (infoPtr, btnPtr, infoPtr->himlDef)))
1235 cx += infoPtr->nBitmapWidth;
1238 cx = infoPtr->nButtonWidth;
1240 if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
1241 cx += DDARROW_WIDTH;
1243 if (btnPtr->fsState & TBSTATE_WRAP )
1246 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
1248 if (infoPtr->rcBound.left > x)
1249 infoPtr->rcBound.left = x;
1250 if (infoPtr->rcBound.right < x + cx)
1251 infoPtr->rcBound.right = x + cx;
1252 if (infoPtr->rcBound.bottom < y + cy)
1253 infoPtr->rcBound.bottom = y + cy;
1255 /* Set the toolTip only for non-hidden, non-separator button */
1256 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
1260 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1261 ti.cbSize = sizeof(TTTOOLINFOA);
1263 ti.uId = btnPtr->idCommand;
1264 ti.rect = btnPtr->rect;
1265 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
1269 /* btnPtr->nRow is zero based. The space between the rows is */
1270 /* also considered as a row. */
1271 btnPtr->nRow = nRows + nSepRows;
1273 TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d\n",
1274 i, btnPtr->fsStyle, bWrap, nRows, nSepRows, btnPtr->nRow);
1278 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
1282 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1283 /* it is the actual width of the separator. This is used for */
1284 /* custom controls in toolbars. */
1285 if ( !(btnPtr->fsStyle & TBSTYLE_DROPDOWN))
1286 y += cy + ( (btnPtr->iBitmap > 0 ) ?
1287 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
1291 /* nSepRows is used to calculate the extra height follwoing */
1295 x = infoPtr->nIndent;
1302 /* infoPtr->nRows is the number of rows on the toolbar */
1303 infoPtr->nRows = nRows + nSepRows + 1;
1305 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
1307 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
1308 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
1309 nSepRows * (infoPtr->nBitmapHeight + 1) +
1311 TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
1316 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
1318 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1319 TBUTTON_INFO *btnPtr;
1322 btnPtr = infoPtr->buttons;
1323 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
1324 if (btnPtr->fsState & TBSTATE_HIDDEN)
1327 if (btnPtr->fsStyle & TBSTYLE_SEP) {
1328 if (PtInRect (&btnPtr->rect, *lpPt)) {
1329 TRACE(" ON SEPARATOR %d!\n", i);
1334 if (PtInRect (&btnPtr->rect, *lpPt)) {
1335 TRACE(" ON BUTTON %d!\n", i);
1341 TRACE(" NOWHERE!\n");
1347 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand, BOOL CommandIsIndex)
1349 TBUTTON_INFO *btnPtr;
1352 if (CommandIsIndex) {
1353 TRACE("command is really index command=%d\n", idCommand);
1354 if (idCommand >= infoPtr->nNumButtons) return -1;
1357 btnPtr = infoPtr->buttons;
1358 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
1359 if (btnPtr->idCommand == idCommand) {
1360 TRACE("command=%d index=%d\n", idCommand, i);
1364 TRACE("no index found for command=%d\n", idCommand);
1370 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
1372 TBUTTON_INFO *btnPtr;
1375 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
1378 /* check index button */
1379 btnPtr = &infoPtr->buttons[nIndex];
1380 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1381 if (btnPtr->fsState & TBSTATE_CHECKED)
1385 /* check previous buttons */
1386 nRunIndex = nIndex - 1;
1387 while (nRunIndex >= 0) {
1388 btnPtr = &infoPtr->buttons[nRunIndex];
1389 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1390 if (btnPtr->fsState & TBSTATE_CHECKED)
1398 /* check next buttons */
1399 nRunIndex = nIndex + 1;
1400 while (nRunIndex < infoPtr->nNumButtons) {
1401 btnPtr = &infoPtr->buttons[nRunIndex];
1402 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1403 if (btnPtr->fsState & TBSTATE_CHECKED)
1416 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
1417 WPARAM wParam, LPARAM lParam)
1423 msg.wParam = wParam;
1424 msg.lParam = lParam;
1425 msg.time = GetMessageTime ();
1426 msg.pt.x = LOWORD(GetMessagePos ());
1427 msg.pt.y = HIWORD(GetMessagePos ());
1429 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1433 /***********************************************************************
1434 * TOOLBAR_CustomizeDialogProc
1435 * This function implements the toolbar customization dialog.
1438 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1440 PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongA (hwnd, DWL_USER);
1441 PCUSTOMBUTTON btnInfo;
1443 TOOLBAR_INFO *infoPtr = custInfo ? custInfo->tbInfo : NULL;
1448 custInfo = (PCUSTDLG_INFO)lParam;
1449 SetWindowLongA (hwnd, DWL_USER, (DWORD)custInfo);
1457 infoPtr = custInfo->tbInfo;
1459 /* send TBN_QUERYINSERT notification */
1460 nmtb.iItem = custInfo->tbInfo->nNumButtons;
1462 if (!TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_QUERYINSERT))
1465 /* add items to 'toolbar buttons' list and check if removable */
1466 for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
1468 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1469 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1470 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1471 btnInfo->bVirtual = FALSE;
1472 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1474 /* send TBN_QUERYDELETE notification */
1476 btnInfo->bRemovable = TOOLBAR_SendNotify ((NMHDR *) &nmtb,
1480 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
1481 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1484 /* insert separator button into 'available buttons' list */
1485 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1486 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1487 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1488 btnInfo->bVirtual = FALSE;
1489 btnInfo->bRemovable = TRUE;
1490 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1491 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1492 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1494 /* insert all buttons into dsa */
1497 /* send TBN_GETBUTTONINFO notification */
1499 nmtb.pszText = Buffer;
1502 if (!TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_GETBUTTONINFOA))
1505 TRACE("style: %x\n", nmtb.tbButton.fsStyle);
1507 /* insert button into the apropriate list */
1508 index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand, FALSE);
1511 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1512 memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1513 btnInfo->bVirtual = FALSE;
1514 btnInfo->bRemovable = TRUE;
1515 if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1516 strcpy (btnInfo->text, nmtb.pszText);
1518 index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1519 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1523 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1524 memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1525 if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1526 strcpy (btnInfo->text, nmtb.pszText);
1528 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1532 /* select first item in the 'available' list */
1533 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);
1535 /* append 'virtual' separator button to the 'toolbar buttons' list */
1536 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1537 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1538 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1539 btnInfo->bVirtual = TRUE;
1540 btnInfo->bRemovable = FALSE;
1541 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1542 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1543 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1545 /* select last item in the 'toolbar' list */
1546 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
1547 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);
1549 /* set focus and disable buttons */
1550 PostMessageA (hwnd, WM_USER, 0, 0);
1555 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1556 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1557 EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
1558 SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
1562 EndDialog(hwnd, FALSE);
1566 switch (LOWORD(wParam))
1568 case IDC_TOOLBARBTN_LBOX:
1569 if (HIWORD(wParam) == LBN_SELCHANGE)
1571 PCUSTOMBUTTON btnInfo;
1576 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1577 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1579 /* send TBN_QUERYINSERT notification */
1581 TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1584 /* get list box item */
1585 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1587 if (index == (count - 1))
1589 /* last item (virtual separator) */
1590 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1591 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1593 else if (index == (count - 2))
1595 /* second last item (last non-virtual item) */
1596 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1597 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1599 else if (index == 0)
1602 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1603 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1607 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1608 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1611 EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
1615 case IDC_MOVEUP_BTN:
1617 PCUSTOMBUTTON btnInfo;
1621 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1622 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1623 TRACE("Move up: index %d\n", index);
1625 /* send TBN_QUERYINSERT notification */
1628 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1631 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1633 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1634 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index-1, 0);
1635 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index-1, (LPARAM)btnInfo);
1636 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1639 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1640 else if (index >= (count - 3))
1641 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1643 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1644 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index-1, (LPARAM)&(btnInfo->btn));
1649 case IDC_MOVEDN_BTN: /* move down */
1651 PCUSTOMBUTTON btnInfo;
1655 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1656 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1657 TRACE("Move up: index %d\n", index);
1659 /* send TBN_QUERYINSERT notification */
1661 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1664 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1666 /* move button down */
1667 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1668 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index+1, 0);
1669 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index+1, (LPARAM)btnInfo);
1670 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index+1 , 0);
1673 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1674 else if (index >= (count - 3))
1675 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1677 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1678 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index+1, (LPARAM)&(btnInfo->btn));
1683 case IDC_REMOVE_BTN: /* remove button */
1685 PCUSTOMBUTTON btnInfo;
1688 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1689 TRACE("Remove: index %d\n", index);
1691 /* send TBN_QUERYDELETE notification */
1693 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1696 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1697 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1698 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index , 0);
1700 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1702 /* insert into 'available button' list */
1703 if (!(btnInfo->btn.fsStyle & TBSTYLE_SEP))
1705 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1706 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1709 COMCTL32_Free (btnInfo);
1714 case IDOK: /* Add button */
1719 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1720 index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
1721 TRACE("Add: index %d\n", index);
1723 /* send TBN_QUERYINSERT notification */
1725 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1728 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, index, 0);
1732 /* remove from 'available buttons' list */
1733 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_DELETESTRING, index, 0);
1734 if (index == count-1)
1735 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1737 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index , 0);
1741 PCUSTOMBUTTON btnNew;
1743 /* duplicate 'separator' button */
1744 btnNew = (PCUSTOMBUTTON)COMCTL32_Alloc (sizeof(CUSTOMBUTTON));
1745 memcpy (btnNew, btnInfo, sizeof(CUSTOMBUTTON));
1749 /* insert into 'toolbar button' list */
1750 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1751 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index, 0);
1752 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1754 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index, (LPARAM)&(btnInfo->btn));
1760 EndDialog(hwnd, FALSE);
1770 /* delete items from 'toolbar buttons' listbox*/
1771 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1772 for (i = 0; i < count; i++)
1774 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
1775 COMCTL32_Free(btnInfo);
1776 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
1778 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);
1781 /* delete items from 'available buttons' listbox*/
1782 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1783 for (i = 0; i < count; i++)
1785 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
1786 COMCTL32_Free(btnInfo);
1787 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
1789 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
1794 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1796 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1801 COLORREF oldText = 0;
1805 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0);
1806 if (btnInfo == NULL)
1808 FIXME("btnInfo invalid!\n");
1812 /* set colors and select objects */
1813 oldBk = SetBkColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1814 if (btnInfo->bVirtual)
1815 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
1817 oldText = SetTextColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHTTEXT:COLOR_WINDOWTEXT));
1818 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1819 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1821 /* fill background rectangle */
1822 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1823 lpdis->rcItem.right, lpdis->rcItem.bottom);
1825 /* calculate button and text rectangles */
1826 CopyRect (&rcButton, &lpdis->rcItem);
1827 InflateRect (&rcButton, -1, -1);
1828 CopyRect (&rcText, &rcButton);
1829 rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
1830 rcText.left = rcButton.right + 2;
1832 /* draw focus rectangle */
1833 if (lpdis->itemState & ODS_FOCUS)
1834 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1837 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1839 /* draw image and text */
1840 if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
1841 ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
1842 rcButton.left+3, rcButton.top+3, ILD_NORMAL);
1843 DrawTextA (lpdis->hDC, btnInfo->text, -1, &rcText,
1844 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1846 /* delete objects and reset colors */
1847 SelectObject (lpdis->hDC, hOldBrush);
1848 SelectObject (lpdis->hDC, hOldPen);
1849 SetBkColor (lpdis->hDC, oldBk);
1850 SetTextColor (lpdis->hDC, oldText);
1856 case WM_MEASUREITEM:
1857 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1859 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1861 if (custInfo && custInfo->tbInfo)
1862 lpmis->itemHeight = custInfo->tbInfo->nBitmapHeight + 8;
1864 lpmis->itemHeight = 15 + 8; /* default height */
1876 /***********************************************************************
1877 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1881 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1883 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1884 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1885 INT nIndex = 0, nButtons, nCount;
1888 TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1892 if (lpAddBmp->hInst == HINST_COMMCTRL)
1894 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1896 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1898 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1903 TRACE ("adding %d internal bitmaps!\n", nButtons);
1905 /* Windows resize all the buttons to the size of a newly added standard image */
1906 if (lpAddBmp->nID & 1)
1909 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
1910 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
1912 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1913 MAKELPARAM((WORD)24, (WORD)24));
1914 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1915 MAKELPARAM((WORD)31, (WORD)30));
1920 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1921 MAKELPARAM((WORD)16, (WORD)16));
1922 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1923 MAKELPARAM((WORD)22, (WORD)22));
1926 TOOLBAR_CalcToolbar (hwnd);
1930 nButtons = (INT)wParam;
1934 TRACE ("adding %d bitmaps!\n", nButtons);
1937 if (!(infoPtr->himlDef)) {
1938 /* create new default image list */
1939 TRACE ("creating default image list!\n");
1942 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1943 ILC_COLOR | ILC_MASK, nButtons, 2);
1944 infoPtr->himlInt = infoPtr->himlDef;
1947 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1949 /* Add bitmaps to the default image list */
1950 if (lpAddBmp->hInst == (HINSTANCE)0)
1953 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1956 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1958 /* Add system bitmaps */
1959 switch (lpAddBmp->nID)
1961 case IDB_STD_SMALL_COLOR:
1962 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1963 MAKEINTRESOURCEA(IDB_STD_SMALL));
1964 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1965 hbmLoad, CLR_DEFAULT);
1966 DeleteObject (hbmLoad);
1969 case IDB_STD_LARGE_COLOR:
1970 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1971 MAKEINTRESOURCEA(IDB_STD_LARGE));
1972 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1973 hbmLoad, CLR_DEFAULT);
1974 DeleteObject (hbmLoad);
1977 case IDB_VIEW_SMALL_COLOR:
1978 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1979 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1980 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1981 hbmLoad, CLR_DEFAULT);
1982 DeleteObject (hbmLoad);
1985 case IDB_VIEW_LARGE_COLOR:
1986 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1987 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1988 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1989 hbmLoad, CLR_DEFAULT);
1990 DeleteObject (hbmLoad);
1993 case IDB_HIST_SMALL_COLOR:
1994 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1995 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1996 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1997 hbmLoad, CLR_DEFAULT);
1998 DeleteObject (hbmLoad);
2001 case IDB_HIST_LARGE_COLOR:
2002 hbmLoad = LoadBitmapA (COMCTL32_hModule,
2003 MAKEINTRESOURCEA(IDB_HIST_LARGE));
2004 nIndex = ImageList_AddMasked (infoPtr->himlDef,
2005 hbmLoad, CLR_DEFAULT);
2006 DeleteObject (hbmLoad);
2010 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
2011 ERR ("invalid imagelist!\n");
2017 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
2018 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
2019 DeleteObject (hbmLoad);
2024 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
2026 if (infoPtr->nNumBitmaps + nButtons != imagecount)
2028 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",
2029 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
2030 infoPtr->nNumBitmaps+nButtons,imagecount);
2032 infoPtr->nNumBitmaps = imagecount;
2035 infoPtr->nNumBitmaps += nButtons;
2038 InvalidateRect(hwnd, NULL, FALSE);
2045 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2047 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2048 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2049 INT nOldButtons, nNewButtons, nAddButtons, nCount;
2051 TRACE("adding %d buttons!\n", wParam);
2053 nAddButtons = (UINT)wParam;
2054 nOldButtons = infoPtr->nNumButtons;
2055 nNewButtons = nOldButtons + nAddButtons;
2057 if (infoPtr->nNumButtons == 0) {
2059 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2062 TBUTTON_INFO *oldButtons = infoPtr->buttons;
2064 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2065 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2066 nOldButtons * sizeof(TBUTTON_INFO));
2067 COMCTL32_Free (oldButtons);
2070 infoPtr->nNumButtons = nNewButtons;
2072 /* insert new button data */
2073 for (nCount = 0; nCount < nAddButtons; nCount++) {
2074 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
2075 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
2076 btnPtr->idCommand = lpTbb[nCount].idCommand;
2077 btnPtr->fsState = lpTbb[nCount].fsState;
2078 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
2079 btnPtr->dwData = lpTbb[nCount].dwData;
2080 btnPtr->iString = lpTbb[nCount].iString;
2081 btnPtr->bHot = FALSE;
2083 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
2086 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2087 ti.cbSize = sizeof (TTTOOLINFOA);
2089 ti.uId = btnPtr->idCommand;
2091 ti.lpszText = LPSTR_TEXTCALLBACKA;
2093 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2098 TOOLBAR_CalcToolbar (hwnd);
2100 TOOLBAR_DumpToolbar (infoPtr, __LINE__);
2102 InvalidateRect(hwnd, NULL, FALSE);
2109 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2111 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2112 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2113 INT nOldButtons, nNewButtons, nAddButtons, nCount;
2115 TRACE("adding %d buttons!\n", wParam);
2117 nAddButtons = (UINT)wParam;
2118 nOldButtons = infoPtr->nNumButtons;
2119 nNewButtons = nOldButtons + nAddButtons;
2121 if (infoPtr->nNumButtons == 0) {
2123 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2126 TBUTTON_INFO *oldButtons = infoPtr->buttons;
2128 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2129 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2130 nOldButtons * sizeof(TBUTTON_INFO));
2131 COMCTL32_Free (oldButtons);
2134 infoPtr->nNumButtons = nNewButtons;
2136 /* insert new button data */
2137 for (nCount = 0; nCount < nAddButtons; nCount++) {
2138 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
2139 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
2140 btnPtr->idCommand = lpTbb[nCount].idCommand;
2141 btnPtr->fsState = lpTbb[nCount].fsState;
2142 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
2143 btnPtr->dwData = lpTbb[nCount].dwData;
2144 btnPtr->iString = lpTbb[nCount].iString;
2145 btnPtr->bHot = FALSE;
2147 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
2150 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2151 ti.cbSize = sizeof (TTTOOLINFOW);
2153 ti.uId = btnPtr->idCommand;
2155 ti.lpszText = LPSTR_TEXTCALLBACKW;
2157 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2162 TOOLBAR_CalcToolbar (hwnd);
2164 TOOLBAR_DumpToolbar (infoPtr, __LINE__);
2166 InvalidateRect(hwnd, NULL, FALSE);
2173 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2175 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2178 if ((wParam) && (HIWORD(lParam) == 0)) {
2181 TRACE("adding string from resource!\n");
2183 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
2186 TRACE("len=%d \"%s\"\n", len, szString);
2187 nIndex = infoPtr->nNumStrings;
2188 if (infoPtr->nNumStrings == 0) {
2190 COMCTL32_Alloc (sizeof(LPWSTR));
2193 LPWSTR *oldStrings = infoPtr->strings;
2195 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2196 memcpy (&infoPtr->strings[0], &oldStrings[0],
2197 sizeof(LPWSTR) * infoPtr->nNumStrings);
2198 COMCTL32_Free (oldStrings);
2201 /*COMCTL32_Alloc zeros out the allocated memory*/
2202 Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], szString );
2203 infoPtr->nNumStrings++;
2206 LPSTR p = (LPSTR)lParam;
2211 TRACE("adding string(s) from array!\n");
2213 nIndex = infoPtr->nNumStrings;
2216 TRACE("len=%d \"%s\"\n", len, p);
2218 if (infoPtr->nNumStrings == 0) {
2220 COMCTL32_Alloc (sizeof(LPWSTR));
2223 LPWSTR *oldStrings = infoPtr->strings;
2225 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2226 memcpy (&infoPtr->strings[0], &oldStrings[0],
2227 sizeof(LPWSTR) * infoPtr->nNumStrings);
2228 COMCTL32_Free (oldStrings);
2231 Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], p );
2232 infoPtr->nNumStrings++;
2243 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2245 #define MAX_RESOURCE_STRING_LENGTH 512
2246 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2249 if ((wParam) && (HIWORD(lParam) == 0)) {
2250 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
2252 TRACE("adding string from resource!\n");
2254 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
2255 szString, MAX_RESOURCE_STRING_LENGTH);
2257 TRACE("len=%d %s\n", len, debugstr_w(szString));
2258 TRACE("First char: 0x%x\n", *szString);
2259 if (szString[0] == L'|')
2261 PWSTR p = szString + 1;
2263 nIndex = infoPtr->nNumStrings;
2264 while (*p != L'|') {
2266 if (infoPtr->nNumStrings == 0) {
2268 COMCTL32_Alloc (sizeof(LPWSTR));
2271 LPWSTR *oldStrings = infoPtr->strings;
2273 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2274 memcpy (&infoPtr->strings[0], &oldStrings[0],
2275 sizeof(LPWSTR) * infoPtr->nNumStrings);
2276 COMCTL32_Free (oldStrings);
2279 len = COMCTL32_StrChrW (p, L'|') - p;
2280 TRACE("len=%d %s\n", len, debugstr_w(p));
2281 infoPtr->strings[infoPtr->nNumStrings] =
2282 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
2283 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len+1);
2284 infoPtr->nNumStrings++;
2291 nIndex = infoPtr->nNumStrings;
2292 if (infoPtr->nNumStrings == 0) {
2294 COMCTL32_Alloc (sizeof(LPWSTR));
2297 LPWSTR *oldStrings = infoPtr->strings;
2299 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2300 memcpy (&infoPtr->strings[0], &oldStrings[0],
2301 sizeof(LPWSTR) * infoPtr->nNumStrings);
2302 COMCTL32_Free (oldStrings);
2305 Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], szString);
2306 infoPtr->nNumStrings++;
2310 LPWSTR p = (LPWSTR)lParam;
2315 TRACE("adding string(s) from array!\n");
2316 nIndex = infoPtr->nNumStrings;
2320 TRACE("len=%d %s\n", len, debugstr_w(p));
2321 if (infoPtr->nNumStrings == 0) {
2323 COMCTL32_Alloc (sizeof(LPWSTR));
2326 LPWSTR *oldStrings = infoPtr->strings;
2328 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2329 memcpy (&infoPtr->strings[0], &oldStrings[0],
2330 sizeof(LPWSTR) * infoPtr->nNumStrings);
2331 COMCTL32_Free (oldStrings);
2334 Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], p);
2335 infoPtr->nNumStrings++;
2346 TOOLBAR_AutoSize (HWND hwnd)
2348 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2349 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2355 UINT uPosFlags = SWP_NOZORDER;
2357 TRACE("resize forced, style=%lx!\n", dwStyle);
2359 parent = GetParent (hwnd);
2360 GetClientRect(parent, &parent_rect);
2362 x = parent_rect.left;
2363 y = parent_rect.top;
2365 /* FIXME: we should be able to early out if nothing */
2366 /* has changed with nWidth != parent_rect width */
2368 if (dwStyle & CCS_NORESIZE) {
2369 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
2372 TOOLBAR_CalcToolbar (hwnd);
2375 infoPtr->nWidth = parent_rect.right - parent_rect.left;
2376 TOOLBAR_CalcToolbar (hwnd);
2377 InvalidateRect( hwnd, NULL, TRUE );
2378 cy = infoPtr->nHeight;
2379 cx = infoPtr->nWidth;
2381 if (dwStyle & CCS_NOMOVEY) {
2382 GetWindowRect(hwnd, &window_rect);
2383 ScreenToClient(parent, (LPPOINT)&window_rect.left);
2384 y = window_rect.top;
2388 if (dwStyle & CCS_NOPARENTALIGN)
2389 uPosFlags |= SWP_NOMOVE;
2391 if (!(dwStyle & CCS_NODIVIDER))
2392 cy += GetSystemMetrics(SM_CYEDGE);
2394 if (dwStyle & WS_BORDER)
2397 cy += GetSystemMetrics(SM_CYEDGE);
2398 cx += GetSystemMetrics(SM_CYEDGE);
2401 infoPtr->bAutoSize = TRUE;
2402 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
2404 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2405 * the setwindowpos calls */
2406 infoPtr->bAutoSize = FALSE;
2413 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
2415 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2417 return infoPtr->nNumButtons;
2422 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2424 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2426 if (infoPtr == NULL) {
2427 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
2428 ERR("infoPtr == NULL!\n");
2432 infoPtr->dwStructSize = (DWORD)wParam;
2439 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2441 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2442 TBUTTON_INFO *btnPtr;
2445 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2449 btnPtr = &infoPtr->buttons[nIndex];
2450 btnPtr->iBitmap = LOWORD(lParam);
2452 /* we HAVE to erase the background, the new bitmap could be */
2454 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2461 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2463 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2464 TBUTTON_INFO *btnPtr;
2467 BOOL bChecked = FALSE;
2469 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2473 btnPtr = &infoPtr->buttons[nIndex];
2475 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
2478 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
2480 if (LOWORD(lParam) == FALSE)
2481 btnPtr->fsState &= ~TBSTATE_CHECKED;
2483 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2485 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
2486 if (nOldIndex == nIndex)
2488 if (nOldIndex != -1)
2489 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2491 btnPtr->fsState |= TBSTATE_CHECKED;
2494 if( bChecked != LOWORD(lParam) )
2496 if (nOldIndex != -1)
2498 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
2499 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
2501 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2504 /* FIXME: Send a WM_NOTIFY?? */
2511 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2513 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2515 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2520 TOOLBAR_Customize (HWND hwnd)
2522 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2523 CUSTDLG_INFO custInfo;
2529 custInfo.tbInfo = infoPtr;
2530 custInfo.tbHwnd = hwnd;
2532 /* send TBN_BEGINADJUST notification */
2533 TOOLBAR_SendNotify ((NMHDR *) &nmhdr, infoPtr,
2536 if (!(hRes = FindResourceA (COMCTL32_hModule,
2537 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
2541 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
2544 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
2545 (LPDLGTEMPLATEA)template,
2547 (DLGPROC)TOOLBAR_CustomizeDialogProc,
2550 /* send TBN_ENDADJUST notification */
2551 TOOLBAR_SendNotify ((NMHDR *) &nmhdr, infoPtr,
2559 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2561 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2562 INT nIndex = (INT)wParam;
2564 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2567 if ((infoPtr->hwndToolTip) &&
2568 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2571 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2572 ti.cbSize = sizeof (TTTOOLINFOA);
2574 ti.uId = infoPtr->buttons[nIndex].idCommand;
2576 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
2579 if (infoPtr->nNumButtons == 1) {
2580 TRACE(" simple delete!\n");
2581 COMCTL32_Free (infoPtr->buttons);
2582 infoPtr->buttons = NULL;
2583 infoPtr->nNumButtons = 0;
2586 TBUTTON_INFO *oldButtons = infoPtr->buttons;
2587 TRACE("complex delete! [nIndex=%d]\n", nIndex);
2589 infoPtr->nNumButtons--;
2590 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2592 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2593 nIndex * sizeof(TBUTTON_INFO));
2596 if (nIndex < infoPtr->nNumButtons) {
2597 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
2598 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
2601 COMCTL32_Free (oldButtons);
2604 TOOLBAR_CalcToolbar (hwnd);
2606 InvalidateRect (hwnd, NULL, TRUE);
2613 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2615 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2616 TBUTTON_INFO *btnPtr;
2620 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2624 btnPtr = &infoPtr->buttons[nIndex];
2626 bState = btnPtr->fsState & TBSTATE_ENABLED;
2628 /* update the toolbar button state */
2629 if(LOWORD(lParam) == FALSE) {
2630 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
2632 btnPtr->fsState |= TBSTATE_ENABLED;
2635 /* redraw the button only if the state of the button changed */
2636 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2638 InvalidateRect(hwnd, &btnPtr->rect,
2639 TOOLBAR_HasText(infoPtr, btnPtr));
2646 static inline LRESULT
2647 TOOLBAR_GetAnchorHighlight (HWND hwnd)
2649 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2651 return infoPtr->bAnchor;
2656 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2658 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2661 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2665 return infoPtr->buttons[nIndex].iBitmap;
2669 static inline LRESULT
2670 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
2677 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2679 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2680 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2681 INT nIndex = (INT)wParam;
2682 TBUTTON_INFO *btnPtr;
2684 if (infoPtr == NULL)
2690 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2693 btnPtr = &infoPtr->buttons[nIndex];
2694 lpTbb->iBitmap = btnPtr->iBitmap;
2695 lpTbb->idCommand = btnPtr->idCommand;
2696 lpTbb->fsState = btnPtr->fsState;
2697 lpTbb->fsStyle = btnPtr->fsStyle;
2698 lpTbb->dwData = btnPtr->dwData;
2699 lpTbb->iString = btnPtr->iString;
2706 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2708 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2709 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2710 TBUTTON_INFO *btnPtr;
2713 if (infoPtr == NULL)
2715 if (lpTbInfo == NULL)
2717 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2720 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam,
2721 lpTbInfo->dwMask & 0x80000000);
2725 if (!(btnPtr = &infoPtr->buttons[nIndex])) return -1;
2727 if (lpTbInfo->dwMask & TBIF_COMMAND)
2728 lpTbInfo->idCommand = btnPtr->idCommand;
2729 if (lpTbInfo->dwMask & TBIF_IMAGE)
2730 lpTbInfo->iImage = btnPtr->iBitmap;
2731 if (lpTbInfo->dwMask & TBIF_LPARAM)
2732 lpTbInfo->lParam = btnPtr->dwData;
2733 if (lpTbInfo->dwMask & TBIF_SIZE)
2734 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2735 if (lpTbInfo->dwMask & TBIF_STATE)
2736 lpTbInfo->fsState = btnPtr->fsState;
2737 if (lpTbInfo->dwMask & TBIF_STYLE)
2738 lpTbInfo->fsStyle = btnPtr->fsStyle;
2739 if (lpTbInfo->dwMask & TBIF_TEXT) {
2740 LPWSTR lpText = TOOLBAR_GetText(infoPtr,btnPtr);
2741 Str_GetPtrWtoA (lpText, lpTbInfo->pszText,lpTbInfo->cchText);
2748 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2750 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2751 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2752 TBUTTON_INFO *btnPtr;
2755 if (infoPtr == NULL)
2757 if (lpTbInfo == NULL)
2759 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2762 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam,
2763 lpTbInfo->dwMask & 0x80000000);
2767 btnPtr = &infoPtr->buttons[nIndex];
2769 if (lpTbInfo->dwMask & TBIF_COMMAND)
2770 lpTbInfo->idCommand = btnPtr->idCommand;
2771 if (lpTbInfo->dwMask & TBIF_IMAGE)
2772 lpTbInfo->iImage = btnPtr->iBitmap;
2773 if (lpTbInfo->dwMask & TBIF_LPARAM)
2774 lpTbInfo->lParam = btnPtr->dwData;
2775 if (lpTbInfo->dwMask & TBIF_SIZE)
2776 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2777 if (lpTbInfo->dwMask & TBIF_STATE)
2778 lpTbInfo->fsState = btnPtr->fsState;
2779 if (lpTbInfo->dwMask & TBIF_STYLE)
2780 lpTbInfo->fsStyle = btnPtr->fsStyle;
2781 if (lpTbInfo->dwMask & TBIF_TEXT) {
2782 LPWSTR lpText = TOOLBAR_GetText(infoPtr,btnPtr);
2783 Str_GetPtrW (lpText,lpTbInfo->pszText,lpTbInfo->cchText);
2791 TOOLBAR_GetButtonSize (HWND hwnd)
2793 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2795 if (infoPtr->nNumButtons > 0)
2796 return MAKELONG((WORD)infoPtr->nButtonWidth,
2797 (WORD)infoPtr->nButtonHeight);
2799 return MAKELONG(8,7);
2804 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2806 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2813 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2817 lpText = TOOLBAR_GetText(infoPtr,&infoPtr->buttons[nIndex]);
2819 return WideCharToMultiByte( CP_ACP, 0, lpText, -1,
2820 (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1;
2825 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2827 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2834 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2838 lpText = TOOLBAR_GetText(infoPtr,&infoPtr->buttons[nIndex]);
2840 strcpyW ((LPWSTR)lParam, lpText);
2842 return strlenW (lpText);
2846 /* << TOOLBAR_GetColorScheme >> */
2850 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2852 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2854 return (LRESULT)infoPtr->himlDis;
2858 inline static LRESULT
2859 TOOLBAR_GetExtendedStyle (HWND hwnd)
2861 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2863 return infoPtr->dwExStyle;
2868 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2870 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2872 return (LRESULT)infoPtr->himlHot;
2877 TOOLBAR_GetHotItem (HWND hwnd)
2879 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2881 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2884 if (infoPtr->nHotItem < 0)
2887 return (LRESULT)infoPtr->nHotItem;
2892 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2894 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2896 return (LRESULT)infoPtr->himlDef;
2900 /* << TOOLBAR_GetInsertMark >> */
2901 /* << TOOLBAR_GetInsertMarkColor >> */
2905 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2907 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2908 TBUTTON_INFO *btnPtr;
2912 if (infoPtr == NULL)
2914 nIndex = (INT)wParam;
2915 btnPtr = &infoPtr->buttons[nIndex];
2916 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2918 lpRect = (LPRECT)lParam;
2921 if (btnPtr->fsState & TBSTATE_HIDDEN)
2924 lpRect->left = btnPtr->rect.left;
2925 lpRect->right = btnPtr->rect.right;
2926 lpRect->bottom = btnPtr->rect.bottom;
2927 lpRect->top = btnPtr->rect.top;
2934 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2936 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2937 LPSIZE lpSize = (LPSIZE)lParam;
2942 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2943 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2945 TRACE("maximum size %d x %d\n",
2946 infoPtr->rcBound.right - infoPtr->rcBound.left,
2947 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2953 /* << TOOLBAR_GetObject >> */
2954 /* << TOOLBAR_GetPadding >> */
2958 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2960 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2961 TBUTTON_INFO *btnPtr;
2965 if (infoPtr == NULL)
2967 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2968 btnPtr = &infoPtr->buttons[nIndex];
2969 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2971 lpRect = (LPRECT)lParam;
2975 lpRect->left = btnPtr->rect.left;
2976 lpRect->right = btnPtr->rect.right;
2977 lpRect->bottom = btnPtr->rect.bottom;
2978 lpRect->top = btnPtr->rect.top;
2985 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2987 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2989 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2990 return infoPtr->nRows;
2997 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2999 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3002 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3006 return infoPtr->buttons[nIndex].fsState;
3011 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3013 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3016 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3020 return infoPtr->buttons[nIndex].fsStyle;
3025 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3027 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3029 if (infoPtr == NULL)
3032 return infoPtr->nMaxTextRows;
3037 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3039 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3041 if (infoPtr == NULL)
3043 return infoPtr->hwndToolTip;
3048 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3050 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3052 TRACE("%s hwnd=0x%x stub!\n",
3053 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
3055 return infoPtr->bUnicode;
3059 inline static LRESULT
3060 TOOLBAR_GetVersion (HWND hwnd)
3062 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3063 return infoPtr->iVersion;
3068 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3070 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3071 TBUTTON_INFO *btnPtr;
3076 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3080 btnPtr = &infoPtr->buttons[nIndex];
3081 if (LOWORD(lParam) == FALSE)
3082 btnPtr->fsState &= ~TBSTATE_HIDDEN;
3084 btnPtr->fsState |= TBSTATE_HIDDEN;
3086 TOOLBAR_CalcToolbar (hwnd);
3088 InvalidateRect (hwnd, NULL, TRUE);
3094 inline static LRESULT
3095 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
3097 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
3102 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3104 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3105 TBUTTON_INFO *btnPtr;
3108 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3112 btnPtr = &infoPtr->buttons[nIndex];
3113 if (LOWORD(lParam) == FALSE)
3114 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
3116 btnPtr->fsState |= TBSTATE_INDETERMINATE;
3118 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3125 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3127 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3128 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
3129 INT nIndex = (INT)wParam;
3130 TBUTTON_INFO *oldButtons;
3135 TOOLBAR_DumpButton(infoPtr, (TBUTTON_INFO *)lpTbb, nIndex, FALSE);
3138 /* EPP: this seems to be an undocumented call (from my IE4)
3139 * I assume in that case that:
3140 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3141 * - index of insertion is at the end of existing buttons
3142 * I only see this happen with nIndex == -1, but it could have a special
3143 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3145 nIndex = infoPtr->nNumButtons;
3147 } else if (nIndex < 0)
3150 /* If the string passed is not an index, assume address of string
3151 and do our own AddString */
3152 if ((HIWORD(lpTbb->iString) != 0) && (lpTbb->iString != -1)) {
3156 TRACE("string %s passed instead of index, adding string\n",
3157 debugstr_a((LPSTR)lpTbb->iString));
3158 len = strlen((LPSTR)lpTbb->iString) + 2;
3159 ptr = COMCTL32_Alloc(len);
3160 strcpy(ptr, (LPSTR)lpTbb->iString);
3161 ptr[len - 1] = 0; /* ended by two '\0' */
3162 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
3166 TRACE("inserting button index=%d\n", nIndex);
3167 if (nIndex > infoPtr->nNumButtons) {
3168 nIndex = infoPtr->nNumButtons;
3169 TRACE("adjust index=%d\n", nIndex);
3172 oldButtons = infoPtr->buttons;
3173 infoPtr->nNumButtons++;
3174 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
3175 /* pre insert copy */
3177 memcpy (&infoPtr->buttons[0], &oldButtons[0],
3178 nIndex * sizeof(TBUTTON_INFO));
3181 /* insert new button */
3182 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
3183 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
3184 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
3185 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
3186 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
3187 /* if passed string and not index, then add string */
3188 if(HIWORD(lpTbb->iString) && lpTbb->iString!=-1) {
3189 Str_SetPtrAtoW ((LPWSTR *)&infoPtr->buttons[nIndex].iString, (LPCSTR )lpTbb->iString);
3192 infoPtr->buttons[nIndex].iString = lpTbb->iString;
3194 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
3197 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
3198 ti.cbSize = sizeof (TTTOOLINFOA);
3200 ti.uId = lpTbb->idCommand;
3202 ti.lpszText = LPSTR_TEXTCALLBACKA;
3204 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
3208 /* post insert copy */
3209 if (nIndex < infoPtr->nNumButtons - 1) {
3210 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
3211 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
3214 COMCTL32_Free (oldButtons);
3216 TOOLBAR_CalcToolbar (hwnd);
3218 InvalidateRect (hwnd, NULL, TRUE);
3225 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3227 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3228 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
3229 INT nIndex = (INT)wParam;
3230 TBUTTON_INFO *oldButtons;
3235 TOOLBAR_DumpButton(infoPtr, (TBUTTON_INFO *)lpTbb, nIndex, FALSE);
3238 /* EPP: this seems to be an undocumented call (from my IE4)
3239 * I assume in that case that:
3240 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3241 * - index of insertion is at the end of existing buttons
3242 * I only see this happen with nIndex == -1, but it could have a special
3243 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3245 nIndex = infoPtr->nNumButtons;
3247 } else if (nIndex < 0)
3250 /* If the string passed is not an index, assume address of string
3251 and do our own AddString */
3252 if ((HIWORD(lpTbb->iString) != 0) && (lpTbb->iString != -1)) {
3256 TRACE("string %s passed instead of index, adding string\n",
3257 debugstr_w((LPWSTR)lpTbb->iString));
3258 len = strlenW((LPWSTR)lpTbb->iString) + 2;
3259 ptr = COMCTL32_Alloc(len*sizeof(WCHAR));
3260 strcpyW(ptr, (LPWSTR)lpTbb->iString);
3261 ptr[len - 1] = 0; /* ended by two '\0' */
3262 lpTbb->iString = TOOLBAR_AddStringW(hwnd, 0, (LPARAM)ptr);
3266 TRACE("inserting button index=%d\n", nIndex);
3267 if (nIndex > infoPtr->nNumButtons) {
3268 nIndex = infoPtr->nNumButtons;
3269 TRACE("adjust index=%d\n", nIndex);
3272 oldButtons = infoPtr->buttons;
3273 infoPtr->nNumButtons++;
3274 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
3275 /* pre insert copy */
3277 memcpy (&infoPtr->buttons[0], &oldButtons[0],
3278 nIndex * sizeof(TBUTTON_INFO));
3281 /* insert new button */
3282 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
3283 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
3284 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
3285 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
3286 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
3287 /* if passed string and not index, then add string */
3288 if(HIWORD(lpTbb->iString) && lpTbb->iString!=-1) {
3289 Str_SetPtrW ((LPWSTR *)&infoPtr->buttons[nIndex].iString, (LPWSTR)lpTbb->iString);
3292 infoPtr->buttons[nIndex].iString = lpTbb->iString;
3294 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
3297 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
3298 ti.cbSize = sizeof (TTTOOLINFOW);
3300 ti.uId = lpTbb->idCommand;
3302 ti.lpszText = LPSTR_TEXTCALLBACKW;
3304 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
3308 /* post insert copy */
3309 if (nIndex < infoPtr->nNumButtons - 1) {
3310 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
3311 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
3314 COMCTL32_Free (oldButtons);
3316 TOOLBAR_CalcToolbar (hwnd);
3318 InvalidateRect (hwnd, NULL, TRUE);
3324 /* << TOOLBAR_InsertMarkHitTest >> */
3328 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
3330 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3333 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3337 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
3342 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
3344 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3347 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3351 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
3356 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
3358 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3361 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3365 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
3370 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
3372 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3375 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3379 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
3384 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3386 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3389 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3393 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
3398 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
3400 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3403 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3407 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
3411 /* << TOOLBAR_LoadImages >> */
3412 /* << TOOLBAR_MapAccelerator >> */
3413 /* << TOOLBAR_MarkButton >> */
3414 /* << TOOLBAR_MoveButton >> */
3418 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3420 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3421 TBUTTON_INFO *btnPtr;
3424 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3428 btnPtr = &infoPtr->buttons[nIndex];
3429 if (LOWORD(lParam) == FALSE)
3430 btnPtr->fsState &= ~TBSTATE_PRESSED;
3432 btnPtr->fsState |= TBSTATE_PRESSED;
3434 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3440 /* << TOOLBAR_ReplaceBitmap >> */
3444 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3447 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3448 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
3450 if (lpSave == NULL) return 0;
3453 /* save toolbar information */
3454 FIXME("save to \"%s\" \"%s\"\n",
3455 lpSave->pszSubKey, lpSave->pszValueName);
3460 /* restore toolbar information */
3462 FIXME("restore from \"%s\" \"%s\"\n",
3463 lpSave->pszSubKey, lpSave->pszValueName);
3474 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3477 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3478 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
3484 /* save toolbar information */
3485 FIXME("save to \"%s\" \"%s\"\n",
3486 lpSave->pszSubKey, lpSave->pszValueName);
3491 /* restore toolbar information */
3493 FIXME("restore from \"%s\" \"%s\"\n",
3494 lpSave->pszSubKey, lpSave->pszValueName);
3505 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
3507 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3508 BOOL bOldAnchor = infoPtr->bAnchor;
3510 infoPtr->bAnchor = (BOOL)wParam;
3512 return (LRESULT)bOldAnchor;
3517 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3519 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3521 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3524 if (infoPtr->nNumButtons > 0)
3525 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
3526 infoPtr->nNumButtons,
3527 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
3528 LOWORD(lParam), HIWORD(lParam));
3530 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
3531 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
3533 /* uses image list internals directly */
3534 if (infoPtr->himlDef) {
3535 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
3536 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
3544 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3546 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3547 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
3548 TBUTTON_INFO *btnPtr;
3553 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
3556 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam,
3557 lptbbi->dwMask & 0x80000000);
3561 btnPtr = &infoPtr->buttons[nIndex];
3562 if (lptbbi->dwMask & TBIF_COMMAND)
3563 btnPtr->idCommand = lptbbi->idCommand;
3564 if (lptbbi->dwMask & TBIF_IMAGE)
3565 btnPtr->iBitmap = lptbbi->iImage;
3566 if (lptbbi->dwMask & TBIF_LPARAM)
3567 btnPtr->dwData = lptbbi->lParam;
3568 /* if (lptbbi->dwMask & TBIF_SIZE) */
3569 /* btnPtr->cx = lptbbi->cx; */
3570 if (lptbbi->dwMask & TBIF_STATE)
3571 btnPtr->fsState = lptbbi->fsState;
3572 if (lptbbi->dwMask & TBIF_STYLE)
3573 btnPtr->fsStyle = lptbbi->fsStyle;
3575 if ((lptbbi->dwMask & TBIF_TEXT) && ((INT)lptbbi->pszText != -1)) {
3576 if ((HIWORD(btnPtr->iString) == 0) || (btnPtr->iString == -1))
3577 /* iString is index, zero it to make Str_SetPtr succeed */
3580 Str_SetPtrAtoW ((LPWSTR *)&btnPtr->iString, lptbbi->pszText);
3587 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3589 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3590 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
3591 TBUTTON_INFO *btnPtr;
3596 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
3599 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam,
3600 lptbbi->dwMask & 0x80000000);
3604 btnPtr = &infoPtr->buttons[nIndex];
3605 if (lptbbi->dwMask & TBIF_COMMAND)
3606 btnPtr->idCommand = lptbbi->idCommand;
3607 if (lptbbi->dwMask & TBIF_IMAGE)
3608 btnPtr->iBitmap = lptbbi->iImage;
3609 if (lptbbi->dwMask & TBIF_LPARAM)
3610 btnPtr->dwData = lptbbi->lParam;
3611 /* if (lptbbi->dwMask & TBIF_SIZE) */
3612 /* btnPtr->cx = lptbbi->cx; */
3613 if (lptbbi->dwMask & TBIF_STATE)
3614 btnPtr->fsState = lptbbi->fsState;
3615 if (lptbbi->dwMask & TBIF_STYLE)
3616 btnPtr->fsStyle = lptbbi->fsStyle;
3618 if ((lptbbi->dwMask & TBIF_TEXT) && ((INT)lptbbi->pszText != -1)) {
3619 if ((HIWORD(btnPtr->iString) == 0) || (btnPtr->iString == -1))
3620 /* iString is index, zero it to make Str_SetPtr succeed */
3622 Str_SetPtrW ((LPWSTR *)&btnPtr->iString, lptbbi->pszText);
3629 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3631 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3633 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3635 ERR("invalid parameter\n");
3639 /* The documentation claims you can only change the button size before
3640 * any button has been added. But this is wrong.
3641 * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding
3642 * it to the toolbar, and it checks that the return value is nonzero - mjm
3643 * Further testing shows that we must actually perform the change too.
3645 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
3646 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
3652 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
3654 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3656 if (infoPtr == NULL) {
3657 TRACE("Toolbar not initialized yet?????\n");
3661 /* if setting to current values, ignore */
3662 if ((infoPtr->cxMin == (INT)LOWORD(lParam)) &&
3663 (infoPtr->cxMax == (INT)HIWORD(lParam))) {
3664 TRACE("matches current width, min=%d, max=%d, no recalc\n",
3665 infoPtr->cxMin, infoPtr->cxMax);
3669 /* save new values */
3670 infoPtr->cxMin = (INT)LOWORD(lParam);
3671 infoPtr->cxMax = (INT)HIWORD(lParam);
3673 /* if both values are 0 then we are done */
3675 TRACE("setting both min and max to 0, norecalc\n");
3679 /* otherwise we need to recalc the toolbar and in some cases
3680 recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
3681 which doesn't actually draw - GA). */
3682 TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n",
3683 infoPtr->nNumButtons, infoPtr->cxMin, infoPtr->cxMax);
3685 TOOLBAR_CalcToolbar (hwnd);
3687 InvalidateRect (hwnd, NULL, TRUE);
3694 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
3696 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3697 INT nIndex = (INT)wParam;
3699 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3702 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
3704 if (infoPtr->hwndToolTip) {
3706 FIXME("change tool tip!\n");
3714 /* << TOOLBAR_SetColorScheme >> */
3718 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3720 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3721 HIMAGELIST himlTemp;
3725 FIXME("no support for multiple image lists\n");
3729 himlTemp = infoPtr->himlDis;
3730 infoPtr->himlDis = (HIMAGELIST)lParam;
3732 /* FIXME: redraw ? */
3734 return (LRESULT)himlTemp;
3739 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
3741 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3744 dwTemp = infoPtr->dwDTFlags;
3745 infoPtr->dwDTFlags =
3746 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
3748 return (LRESULT)dwTemp;
3753 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3755 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3758 dwTemp = infoPtr->dwExStyle;
3759 infoPtr->dwExStyle = (DWORD)lParam;
3761 return (LRESULT)dwTemp;
3766 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3768 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3769 HIMAGELIST himlTemp;
3772 FIXME("no support for multiple image lists\n");
3776 himlTemp = infoPtr->himlHot;
3777 infoPtr->himlHot = (HIMAGELIST)lParam;
3779 /* FIXME: redraw ? */
3781 return (LRESULT)himlTemp;
3786 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3788 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3789 INT nOldHotItem = infoPtr->nHotItem;
3790 TBUTTON_INFO *btnPtr;
3792 if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons)
3795 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3798 infoPtr->nHotItem = (INT)wParam;
3799 if ((INT)wParam >=0)
3801 btnPtr = &infoPtr->buttons[(INT)wParam];
3802 btnPtr->bHot = TRUE;
3803 InvalidateRect (hwnd, &btnPtr->rect,
3804 TOOLBAR_HasText(infoPtr, btnPtr));
3808 btnPtr = &infoPtr->buttons[nOldHotItem];
3809 btnPtr->bHot = FALSE;
3810 InvalidateRect (hwnd, &btnPtr->rect,
3811 TOOLBAR_HasText(infoPtr, btnPtr));
3815 if (nOldHotItem < 0)
3818 return (LRESULT)nOldHotItem;
3823 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3825 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3826 HIMAGELIST himlTemp;
3829 FIXME("no support for multiple image lists\n");
3833 himlTemp = infoPtr->himlDef;
3834 infoPtr->himlDef = (HIMAGELIST)lParam;
3836 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3838 ImageList_GetIconSize(infoPtr->himlDef, &infoPtr->nBitmapWidth,
3839 &infoPtr->nBitmapHeight);
3840 TRACE("hwnd %08x, new himl=%08x, count=%d, bitmap w=%d, h=%d\n",
3841 hwnd, (INT)infoPtr->himlDef, infoPtr->nNumBitmaps,
3842 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
3844 /* FIXME: redraw ? */
3845 InvalidateRect(hwnd, NULL, TRUE);
3847 return (LRESULT)himlTemp;
3852 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3854 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3856 infoPtr->nIndent = (INT)wParam;
3860 /* process only on indent changing */
3861 if(infoPtr->nIndent != (INT)wParam)
3863 infoPtr->nIndent = (INT)wParam;
3864 TOOLBAR_CalcToolbar (hwnd);
3865 InvalidateRect(hwnd, NULL, FALSE);
3872 /* << TOOLBAR_SetInsertMark >> */
3876 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3878 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3880 infoPtr->clrInsertMark = (COLORREF)lParam;
3882 /* FIXME : redraw ??*/
3889 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3891 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3893 if (infoPtr == NULL)
3896 infoPtr->nMaxTextRows = (INT)wParam;
3902 /* << TOOLBAR_SetPadding >> */
3906 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3908 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3913 if (infoPtr == NULL)
3915 hwndOldNotify = infoPtr->hwndNotify;
3916 infoPtr->hwndNotify = (HWND)wParam;
3918 return hwndOldNotify;
3923 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3925 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3926 LPRECT lprc = (LPRECT)lParam;
3930 if (LOWORD(wParam) > 1) {
3931 FIXME("multiple rows not supported!\n");
3934 if(infoPtr->nRows != LOWORD(wParam))
3936 infoPtr->nRows = LOWORD(wParam);
3938 /* recalculate toolbar */
3939 TOOLBAR_CalcToolbar (hwnd);
3941 /* repaint toolbar */
3942 InvalidateRect(hwnd, NULL, FALSE);
3945 /* return bounding rectangle */
3947 lprc->left = infoPtr->rcBound.left;
3948 lprc->right = infoPtr->rcBound.right;
3949 lprc->top = infoPtr->rcBound.top;
3950 lprc->bottom = infoPtr->rcBound.bottom;
3958 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3960 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3961 TBUTTON_INFO *btnPtr;
3964 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3968 btnPtr = &infoPtr->buttons[nIndex];
3970 /* if hidden state has changed the invalidate entire window and recalc */
3971 if ((btnPtr->fsState & TBSTATE_HIDDEN) != (LOWORD(lParam) & TBSTATE_HIDDEN)) {
3972 btnPtr->fsState = LOWORD(lParam);
3973 TOOLBAR_CalcToolbar (hwnd);
3974 InvalidateRect(hwnd, 0, TOOLBAR_HasText(infoPtr, btnPtr));
3978 /* process state changing if current state doesn't match new state */
3979 if(btnPtr->fsState != LOWORD(lParam))
3981 btnPtr->fsState = LOWORD(lParam);
3982 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3991 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3993 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3994 TBUTTON_INFO *btnPtr;
3997 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
4001 btnPtr = &infoPtr->buttons[nIndex];
4003 /* process style change if current style doesn't match new style */
4004 if(btnPtr->fsStyle != LOWORD(lParam))
4006 btnPtr->fsStyle = LOWORD(lParam);
4007 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4010 if (infoPtr->hwndToolTip) {
4011 FIXME("change tool tip!\n");
4019 inline static LRESULT
4020 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
4022 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4024 if (infoPtr == NULL)
4026 infoPtr->hwndToolTip = (HWND)wParam;
4032 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
4034 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4037 TRACE("%s hwnd=0x%04x stub!\n",
4038 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
4040 bTemp = infoPtr->bUnicode;
4041 infoPtr->bUnicode = (BOOL)wParam;
4048 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
4050 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4051 INT iOldVersion = infoPtr->iVersion;
4053 infoPtr->iVersion = iVersion;
4060 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
4062 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4063 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4066 /* initialize info structure */
4067 infoPtr->nButtonHeight = 22;
4068 infoPtr->nButtonWidth = 24;
4069 infoPtr->nBitmapHeight = 15;
4070 infoPtr->nBitmapWidth = 16;
4072 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
4074 infoPtr->nMaxTextRows = 1;
4075 infoPtr->cxMin = -1;
4076 infoPtr->cxMax = -1;
4077 infoPtr->nNumBitmaps = 0;
4078 infoPtr->nNumStrings = 0;
4080 infoPtr->bCaptured = FALSE;
4081 infoPtr->bUnicode = IsWindowUnicode (hwnd);
4082 infoPtr->nButtonDown = -1;
4083 infoPtr->nOldHit = -1;
4084 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
4085 infoPtr->hwndNotify = GetParent (hwnd);
4086 infoPtr->bTransparent = (dwStyle & TBSTYLE_TRANSPARENT);
4087 infoPtr->bBtnTranspnt = (dwStyle & (TBSTYLE_FLAT | TBSTYLE_LIST));
4088 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
4089 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
4090 infoPtr->iVersion = 0;
4091 infoPtr->bNtfUnicode = FALSE;
4092 infoPtr->hwndSelf = hwnd;
4093 infoPtr->bDoRedraw = TRUE;
4095 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
4096 infoPtr->hFont = infoPtr->hDefaultFont = CreateFontIndirectA (&logFont);
4098 if (dwStyle & TBSTYLE_TOOLTIPS) {
4099 /* Create tooltip control */
4100 infoPtr->hwndToolTip =
4101 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
4102 CW_USEDEFAULT, CW_USEDEFAULT,
4103 CW_USEDEFAULT, CW_USEDEFAULT,
4106 /* Send NM_TOOLTIPSCREATED notification */
4107 if (infoPtr->hwndToolTip) {
4108 NMTOOLTIPSCREATED nmttc;
4110 nmttc.hwndToolTips = infoPtr->hwndToolTip;
4112 TOOLBAR_SendNotify ((NMHDR *) &nmttc, infoPtr,
4113 NM_TOOLTIPSCREATED);
4117 TOOLBAR_CheckStyle (hwnd, dwStyle);
4119 TOOLBAR_CalcToolbar(hwnd);
4126 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
4128 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4130 /* delete tooltip control */
4131 if (infoPtr->hwndToolTip)
4132 DestroyWindow (infoPtr->hwndToolTip);
4134 /* delete button data */
4135 if (infoPtr->buttons)
4136 COMCTL32_Free (infoPtr->buttons);
4138 /* delete strings */
4139 if (infoPtr->strings) {
4141 for (i = 0; i < infoPtr->nNumStrings; i++)
4142 if (infoPtr->strings[i])
4143 COMCTL32_Free (infoPtr->strings[i]);
4145 COMCTL32_Free (infoPtr->strings);
4148 /* destroy internal image list */
4149 if (infoPtr->himlInt)
4150 ImageList_Destroy (infoPtr->himlInt);
4152 /* delete default font */
4154 DeleteObject (infoPtr->hDefaultFont);
4156 /* free toolbar info data */
4157 COMCTL32_Free (infoPtr);
4158 SetWindowLongA (hwnd, 0, 0);
4165 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
4167 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4168 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4169 NMTBCUSTOMDRAW tbcd;
4170 INT ret = FALSE, ntfret;
4172 if (dwStyle & TBSTYLE_CUSTOMERASE) {
4173 ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
4174 tbcd.nmcd.dwDrawStage = CDDS_PREERASE;
4175 tbcd.nmcd.hdc = (HDC)wParam;
4176 ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
4177 /* FIXME: in general the return flags *can* be or'ed together */
4180 case CDRF_DODEFAULT:
4182 case CDRF_SKIPDEFAULT:
4185 FIXME("[%04x] response %d not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4190 /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up
4191 * to my parent for processing.
4193 if (infoPtr->bTransparent) {
4195 HDC hdc = (HDC)wParam;
4200 parent = GetParent(hwnd);
4201 MapWindowPoints(hwnd, parent, &pt, 1);
4202 OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
4203 ret = SendMessageA (parent, WM_ERASEBKGND, wParam, lParam);
4204 SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
4207 ret = DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
4209 if (dwStyle & TBSTYLE_CUSTOMERASE) {
4210 ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
4211 tbcd.nmcd.dwDrawStage = CDDS_POSTERASE;
4212 tbcd.nmcd.hdc = (HDC)wParam;
4213 ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
4216 case CDRF_DODEFAULT:
4218 case CDRF_SKIPDEFAULT:
4221 FIXME("[%04x] response %d not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4230 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
4232 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4234 return infoPtr->hFont;
4239 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
4241 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4242 TBUTTON_INFO *btnPtr;
4246 pt.x = (INT)LOWORD(lParam);
4247 pt.y = (INT)HIWORD(lParam);
4248 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4251 btnPtr = &infoPtr->buttons[nHit];
4252 if (!(btnPtr->fsState & TBSTATE_ENABLED))
4255 infoPtr->bCaptured = TRUE;
4256 infoPtr->nButtonDown = nHit;
4258 btnPtr->fsState |= TBSTATE_PRESSED;
4260 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4263 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
4264 TOOLBAR_Customize (hwnd);
4271 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
4273 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4274 TBUTTON_INFO *btnPtr;
4279 if (infoPtr->hwndToolTip)
4280 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4281 WM_LBUTTONDOWN, wParam, lParam);
4283 pt.x = (INT)LOWORD(lParam);
4284 pt.y = (INT)HIWORD(lParam);
4285 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4289 btnPtr = &infoPtr->buttons[nHit];
4290 if (!(btnPtr->fsState & TBSTATE_ENABLED))
4293 infoPtr->nOldHit = nHit;
4295 CopyRect(&arrowRect, &btnPtr->rect);
4296 arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
4298 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
4299 if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
4300 ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
4301 (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))
4305 * this time we must force a Redraw, so the btn is
4306 * painted down before CaptureChanged repaints it up
4308 RedrawWindow(hwnd,&btnPtr->rect,0,
4309 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
4311 nmtb.iItem = btnPtr->idCommand;
4312 memset(&nmtb.tbButton, 0, sizeof(TBBUTTON));
4315 memset(&nmtb.rcButton, 0, sizeof(RECT));
4316 res = TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4318 if (res != TBDDRET_TREATPRESSED)
4319 /* ??? guess (GA) */
4321 /* otherwise drop through and process as pushed */
4323 /* SetCapture (hwnd); */
4324 infoPtr->bCaptured = TRUE;
4325 infoPtr->nButtonDown = nHit;
4327 btnPtr->fsState |= TBSTATE_PRESSED;
4328 btnPtr->bHot = FALSE;
4330 InvalidateRect(hwnd, &btnPtr->rect,
4331 TOOLBAR_HasText(infoPtr, btnPtr));
4335 /* native issues the TBN_BEGINDRAG here */
4336 nmtb.iItem = btnPtr->idCommand;
4337 nmtb.tbButton.iBitmap = btnPtr->iBitmap;
4338 nmtb.tbButton.idCommand = btnPtr->idCommand;
4339 nmtb.tbButton.fsState = btnPtr->fsState;
4340 nmtb.tbButton.fsStyle = btnPtr->fsStyle;
4341 nmtb.tbButton.dwData = btnPtr->dwData;
4342 nmtb.tbButton.iString = btnPtr->iString;
4343 nmtb.cchText = 0; /* !!! not correct */
4344 nmtb.pszText = 0; /* !!! not correct */
4345 TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4353 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
4355 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4356 TBUTTON_INFO *btnPtr;
4360 BOOL bSendMessage = TRUE;
4365 if (infoPtr->hwndToolTip)
4366 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4367 WM_LBUTTONUP, wParam, lParam);
4369 pt.x = (INT)LOWORD(lParam);
4370 pt.y = (INT)HIWORD(lParam);
4371 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4373 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
4374 /* if the cursor is still inside of the toolbar */
4375 if((infoPtr->nHotItem >= 0) && (nHit != -1))
4376 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
4378 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
4379 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4380 btnPtr->fsState &= ~TBSTATE_PRESSED;
4382 if (nHit == infoPtr->nButtonDown) {
4383 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
4384 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
4385 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
4386 infoPtr->nButtonDown);
4387 if (nOldIndex == infoPtr->nButtonDown)
4388 bSendMessage = FALSE;
4389 if ((nOldIndex != infoPtr->nButtonDown) &&
4391 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
4392 btnPtr->fsState |= TBSTATE_CHECKED;
4395 if (btnPtr->fsState & TBSTATE_CHECKED)
4396 btnPtr->fsState &= ~TBSTATE_CHECKED;
4398 btnPtr->fsState |= TBSTATE_CHECKED;
4403 bSendMessage = FALSE;
4405 if (nOldIndex != -1)
4407 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
4408 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
4412 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
4413 * that resets bCaptured and btn TBSTATE_PRESSED flags,
4414 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
4418 /* Issue NM_RELEASEDCAPTURE to parent to let him know it is released */
4419 TOOLBAR_SendNotify ((NMHDR *) &hdr, infoPtr,
4420 NM_RELEASEDCAPTURE);
4422 /* native issues TBN_ENDDRAG here, if _LBUTTONDOWN issued the
4425 nmtb.iItem = btnPtr->idCommand;
4426 nmtb.tbButton.iBitmap = btnPtr->iBitmap;
4427 nmtb.tbButton.idCommand = btnPtr->idCommand;
4428 nmtb.tbButton.fsState = btnPtr->fsState;
4429 nmtb.tbButton.fsStyle = btnPtr->fsStyle;
4430 nmtb.tbButton.dwData = btnPtr->dwData;
4431 nmtb.tbButton.iString = btnPtr->iString;
4432 nmtb.cchText = 0; /* !!! not correct */
4433 nmtb.pszText = 0; /* !!! not correct */
4434 TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4438 SendMessageA (infoPtr->hwndNotify, WM_COMMAND,
4439 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
4441 /* !!! Undocumented - toolbar at 4.71 level and above sends
4442 * either NMRCLICK or NM_CLICK with the NMMOUSE structure.
4443 * Only NM_RCLICK is documented.
4445 nmmouse.dwItemSpec = btnPtr->idCommand;
4446 nmmouse.dwItemData = btnPtr->dwData;
4447 TOOLBAR_SendNotify ((NMHDR *) &nmmouse, infoPtr,
4455 TOOLBAR_CaptureChanged(HWND hwnd)
4457 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4458 TBUTTON_INFO *btnPtr;
4460 infoPtr->bCaptured = FALSE;
4462 if (infoPtr->nButtonDown >= 0)
4464 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4465 btnPtr->fsState &= ~TBSTATE_PRESSED;
4467 infoPtr->nButtonDown = -1;
4468 infoPtr->nOldHit = -1;
4470 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4477 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
4479 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4480 TBUTTON_INFO *hotBtnPtr, *btnPtr;
4483 if (infoPtr->nOldHit < 0)
4486 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
4488 /* Redraw the button if the last button we were over is the hot button and it
4490 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
4492 hotBtnPtr->bHot = FALSE;
4493 rc1 = hotBtnPtr->rect;
4494 InflateRect (&rc1, 1, 1);
4495 InvalidateRect (hwnd, &rc1, TOOLBAR_HasText(infoPtr,
4499 /* If the last button we were over is depressed then make it not */
4500 /* depressed and redraw it */
4501 if(infoPtr->nOldHit == infoPtr->nButtonDown)
4503 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4505 btnPtr->fsState &= ~TBSTATE_PRESSED;
4507 rc1 = hotBtnPtr->rect;
4508 InflateRect (&rc1, 1, 1);
4509 InvalidateRect (hwnd, &rc1, TRUE);
4512 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
4513 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
4519 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
4521 TBUTTON_INFO *btnPtr, *oldBtnPtr;
4522 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4525 TRACKMOUSEEVENT trackinfo;
4527 /* fill in the TRACKMOUSEEVENT struct */
4528 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
4529 trackinfo.dwFlags = TME_QUERY;
4530 trackinfo.hwndTrack = hwnd;
4531 trackinfo.dwHoverTime = HOVER_DEFAULT;
4533 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
4534 _TrackMouseEvent(&trackinfo);
4536 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
4537 if(!(trackinfo.dwFlags & TME_LEAVE)) {
4538 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
4540 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
4541 /* and can properly deactivate the hot toolbar button */
4542 _TrackMouseEvent(&trackinfo);
4545 if (infoPtr->hwndToolTip)
4546 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4547 WM_MOUSEMOVE, wParam, lParam);
4549 pt.x = (INT)LOWORD(lParam);
4550 pt.y = (INT)HIWORD(lParam);
4552 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4554 if (infoPtr->nOldHit != nHit)
4556 /* Remove the effect of an old hot button if the button was enabled and was
4557 drawn with the hot button effect */
4558 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
4559 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
4561 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
4562 oldBtnPtr->bHot = FALSE;
4564 InvalidateRect (hwnd, &oldBtnPtr->rect,
4565 TOOLBAR_HasText(infoPtr, oldBtnPtr));
4568 /* It's not a separator or in nowhere. It's a hot button. */
4571 btnPtr = &infoPtr->buttons[nHit];
4573 infoPtr->nHotItem = nHit;
4575 /* only enabled buttons show hot effect */
4576 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
4578 btnPtr->bHot = TRUE;
4579 InvalidateRect(hwnd, &btnPtr->rect,
4580 TOOLBAR_HasText(infoPtr, btnPtr));
4585 if (infoPtr->bCaptured) {
4586 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4587 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
4588 btnPtr->fsState &= ~TBSTATE_PRESSED;
4589 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4591 else if (nHit == infoPtr->nButtonDown) {
4592 btnPtr->fsState |= TBSTATE_PRESSED;
4593 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4596 infoPtr->nOldHit = nHit;
4602 inline static LRESULT
4603 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4605 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
4606 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
4608 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
4612 inline static LRESULT
4613 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
4615 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
4616 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
4618 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
4623 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4625 TOOLBAR_INFO *infoPtr;
4626 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
4629 /* allocate memory for info structure */
4630 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
4631 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
4634 infoPtr->dwStructSize = sizeof(TBBUTTON);
4636 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
4637 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
4638 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
4639 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
4642 /* native control does:
4643 * Get a lot of colors and brushes
4645 * SystemParametersInfoA(0x1f, 0x3c, adr1, 0)
4646 * CreateFontIndirectA(adr1)
4647 * CreateBitmap(0x27, 0x24, 1, 1, 0)
4648 * hdc = GetDC(toolbar)
4649 * GetSystemMetrics(0x48)
4650 * fnt2=CreateFontA(0xe, 0, 0, 0, 0x190, 0, 0, 0, 0, 2,
4651 * 0, 0, 0, 0, "MARLETT")
4652 * oldfnt = SelectObject(hdc, fnt2)
4653 * GetCharWidthA(hdc, 0x36, 0x36, adr2)
4654 * GetTextMetricsA(hdc, adr3)
4655 * SelectObject(hdc, oldfnt)
4656 * DeleteObject(fnt2)
4658 * InvalidateRect(toolbar, 0, 1)
4659 * SetWindowLongA(toolbar, 0, addr)
4660 * SetWindowLongA(toolbar, -16, xxx) **sometimes**
4663 * ie 1 0x56000a4c 0x46000a4c 0x56008a4d
4664 * ie 2 0x4600094c 0x4600094c 0x4600894d
4665 * ie 3 0x56000b4c 0x46000b4c 0x56008b4d
4666 * rebar 0x50008844 0x40008844 0x50008845
4667 * pager 0x50000844 0x40000844 0x50008845
4668 * IC35mgr 0x5400084e **nochange**
4669 * on entry to _NCCREATE 0x5400084e
4670 * rowlist 0x5400004e **nochange**
4671 * on entry to _NCCREATE 0x5400004e
4675 /* I think the code below is a bug, but it is the way that the native
4676 * controls seem to work. The effect is that if the user of TBSTYLE_FLAT
4677 * forgets to specify TBSTYLE_TRANSPARENT but does specify either
4678 * CCS_TOP or CCS_BOTTOM (_NOMOVEY and _TOP), then the control
4679 * does *not* set TBSTYLE_TRANSPARENT even though it should!!!!
4680 * Some how, the only cases of this seem to be MFC programs.
4682 * Note also that the addition of _TRANSPARENT occurs *only* here. It
4683 * does not occur in the WM_STYLECHANGING routine.
4684 * (Guy Albertelli 9/2001)
4687 if ((cs->style & TBSTYLE_FLAT) && !(cs->style & TBSTYLE_TRANSPARENT))
4688 styleadd |= TBSTYLE_TRANSPARENT;
4689 if (!(cs->style & (CCS_TOP | CCS_NOMOVEY))) {
4690 styleadd |= CCS_TOP; /* default to top */
4691 SetWindowLongA (hwnd, GWL_STYLE, cs->style | styleadd);
4694 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
4699 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
4701 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4705 if (dwStyle & WS_MINIMIZE)
4706 return 0; /* Nothing to do */
4708 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
4710 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
4713 if (!(dwStyle & CCS_NODIVIDER))
4715 GetWindowRect (hwnd, &rcWindow);
4716 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4717 if( dwStyle & WS_BORDER )
4718 OffsetRect (&rcWindow, 1, 1);
4719 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
4722 ReleaseDC( hwnd, hdc );
4728 inline static LRESULT
4729 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
4731 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4732 LPNMHDR lpnmh = (LPNMHDR)lParam;
4734 if (lpnmh->code == PGN_CALCSIZE) {
4735 LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam;
4737 if (lppgc->dwFlag == PGF_CALCWIDTH) {
4738 lppgc->iWidth = infoPtr->nWidth;
4739 TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
4743 lppgc->iHeight = infoPtr->nHeight;
4744 TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
4751 TRACE("passing WM_NOTIFY!\n");
4753 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
4754 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
4757 if (lpnmh->code == TTN_GETDISPINFOA) {
4758 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
4760 FIXME("retrieving ASCII string\n");
4763 else if (lpnmh->code == TTN_GETDISPINFOW) {
4764 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
4766 FIXME("retrieving UNICODE string\n");
4777 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
4779 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4783 /* fill ps.rcPaint with a default rect */
4784 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
4786 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
4788 TRACE("psrect=(%d,%d)-(%d,%d)\n",
4789 ps.rcPaint.left, ps.rcPaint.top,
4790 ps.rcPaint.right, ps.rcPaint.bottom);
4792 TOOLBAR_Refresh (hwnd, hdc, &ps);
4793 if (!wParam) EndPaint (hwnd, &ps);
4800 TOOLBAR_SetRedraw (HWND hwnd, WPARAM wParam, LPARAM lParam)
4801 /*****************************************************
4804 * Handles the WM_SETREDRAW message.
4807 * According to testing V4.71 of COMCTL32 returns the
4808 * *previous* status of the redraw flag (either 0 or 1)
4809 * instead of the MSDN documented value of 0 if handled.
4810 * (For laughs see the "consistancy" with same function
4813 *****************************************************/
4815 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4816 BOOL oldredraw = infoPtr->bDoRedraw;
4818 TRACE("set to %s\n",
4819 (wParam) ? "TRUE" : "FALSE");
4820 infoPtr->bDoRedraw = (BOOL) wParam;
4822 InvalidateRect (infoPtr->hwndSelf, 0, TRUE);
4824 return (oldredraw) ? 1 : 0;
4829 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
4831 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4832 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4841 /* Resize deadlock check */
4842 if (infoPtr->bAutoSize) {
4843 infoPtr->bAutoSize = FALSE;
4847 /* FIXME: optimize to only update size if the new size doesn't */
4848 /* match the current size */
4850 flags = (INT) wParam;
4852 /* FIXME for flags =
4853 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
4856 TRACE("sizing toolbar!\n");
4858 if (flags == SIZE_RESTORED) {
4859 /* width and height don't apply */
4860 parent = GetParent (hwnd);
4861 GetClientRect(parent, &parent_rect);
4862 x = parent_rect.left;
4863 y = parent_rect.top;
4865 if (dwStyle & CCS_NORESIZE) {
4866 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
4869 * this sets the working width of the toolbar, and
4870 * Calc Toolbar will not adjust it, only the height
4872 infoPtr->nWidth = parent_rect.right - parent_rect.left;
4873 cy = infoPtr->nHeight;
4874 cx = infoPtr->nWidth;
4875 TOOLBAR_CalcToolbar (hwnd);
4876 infoPtr->nWidth = cx;
4877 infoPtr->nHeight = cy;
4880 infoPtr->nWidth = parent_rect.right - parent_rect.left;
4881 TOOLBAR_CalcToolbar (hwnd);
4882 cy = infoPtr->nHeight;
4883 cx = infoPtr->nWidth;
4885 if (dwStyle & CCS_NOMOVEY) {
4886 GetWindowRect(hwnd, &window_rect);
4887 ScreenToClient(parent, (LPPOINT)&window_rect.left);
4888 y = window_rect.top;
4892 if (dwStyle & CCS_NOPARENTALIGN) {
4893 uPosFlags |= SWP_NOMOVE;
4894 cy = infoPtr->nHeight;
4895 cx = infoPtr->nWidth;
4898 if (!(dwStyle & CCS_NODIVIDER))
4899 cy += GetSystemMetrics(SM_CYEDGE);
4901 if (dwStyle & WS_BORDER)
4904 cy += GetSystemMetrics(SM_CYEDGE);
4905 cx += GetSystemMetrics(SM_CYEDGE);
4908 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
4909 cx, cy, uPosFlags | SWP_NOZORDER);
4916 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
4918 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4920 if (nType == GWL_STYLE) {
4921 if (lpStyle->styleNew & TBSTYLE_LIST) {
4922 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
4925 infoPtr->dwDTFlags = DT_CENTER;
4927 infoPtr->bTransparent = (lpStyle->styleNew & TBSTYLE_TRANSPARENT);
4928 infoPtr->bBtnTranspnt = (lpStyle->styleNew &
4929 (TBSTYLE_FLAT | TBSTYLE_LIST));
4930 TOOLBAR_CheckStyle (hwnd, lpStyle->styleNew);
4933 TOOLBAR_AutoSize (hwnd);
4935 InvalidateRect(hwnd, NULL, FALSE);
4942 static LRESULT WINAPI
4943 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4945 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n",
4946 hwnd, uMsg, /* SPY_GetMsgName(uMsg), */ wParam, lParam);
4948 if (!TOOLBAR_GetInfoPtr(hwnd) && (uMsg != WM_NCCREATE))
4949 return DefWindowProcA( hwnd, uMsg, wParam, lParam );
4954 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
4956 case TB_ADDBUTTONSA:
4957 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
4959 case TB_ADDBUTTONSW:
4960 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
4963 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
4966 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
4969 return TOOLBAR_AutoSize (hwnd);
4971 case TB_BUTTONCOUNT:
4972 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
4974 case TB_BUTTONSTRUCTSIZE:
4975 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
4977 case TB_CHANGEBITMAP:
4978 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
4980 case TB_CHECKBUTTON:
4981 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
4983 case TB_COMMANDTOINDEX:
4984 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
4987 return TOOLBAR_Customize (hwnd);
4989 case TB_DELETEBUTTON:
4990 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
4992 case TB_ENABLEBUTTON:
4993 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
4995 case TB_GETANCHORHIGHLIGHT:
4996 return TOOLBAR_GetAnchorHighlight (hwnd);
4999 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
5001 case TB_GETBITMAPFLAGS:
5002 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
5005 return TOOLBAR_GetButton (hwnd, wParam, lParam);
5007 case TB_GETBUTTONINFOA:
5008 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
5010 case TB_GETBUTTONINFOW:
5011 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
5013 case TB_GETBUTTONSIZE:
5014 return TOOLBAR_GetButtonSize (hwnd);
5016 case TB_GETBUTTONTEXTA:
5017 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
5019 case TB_GETBUTTONTEXTW:
5020 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
5022 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
5024 case TB_GETDISABLEDIMAGELIST:
5025 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
5027 case TB_GETEXTENDEDSTYLE:
5028 return TOOLBAR_GetExtendedStyle (hwnd);
5030 case TB_GETHOTIMAGELIST:
5031 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
5034 return TOOLBAR_GetHotItem (hwnd);
5036 case TB_GETIMAGELIST:
5037 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
5039 /* case TB_GETINSERTMARK: */ /* 4.71 */
5040 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
5042 case TB_GETITEMRECT:
5043 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
5046 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
5048 /* case TB_GETOBJECT: */ /* 4.71 */
5049 /* case TB_GETPADDING: */ /* 4.71 */
5052 return TOOLBAR_GetRect (hwnd, wParam, lParam);
5055 return TOOLBAR_GetRows (hwnd, wParam, lParam);
5058 return TOOLBAR_GetState (hwnd, wParam, lParam);
5061 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
5063 case TB_GETTEXTROWS:
5064 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
5066 case TB_GETTOOLTIPS:
5067 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
5069 case TB_GETUNICODEFORMAT:
5070 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
5072 case CCM_GETVERSION:
5073 return TOOLBAR_GetVersion (hwnd);
5076 return TOOLBAR_HideButton (hwnd, wParam, lParam);
5079 return TOOLBAR_HitTest (hwnd, wParam, lParam);
5081 case TB_INDETERMINATE:
5082 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
5084 case TB_INSERTBUTTONA:
5085 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
5087 case TB_INSERTBUTTONW:
5088 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
5090 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
5092 case TB_ISBUTTONCHECKED:
5093 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
5095 case TB_ISBUTTONENABLED:
5096 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
5098 case TB_ISBUTTONHIDDEN:
5099 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
5101 case TB_ISBUTTONHIGHLIGHTED:
5102 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
5104 case TB_ISBUTTONINDETERMINATE:
5105 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
5107 case TB_ISBUTTONPRESSED:
5108 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
5110 case TB_LOADIMAGES: /* 4.70 */
5111 FIXME("missing standard imagelists\n");
5114 /* case TB_MAPACCELERATORA: */ /* 4.71 */
5115 /* case TB_MAPACCELERATORW: */ /* 4.71 */
5116 /* case TB_MARKBUTTON: */ /* 4.71 */
5117 /* case TB_MOVEBUTTON: */ /* 4.71 */
5119 case TB_PRESSBUTTON:
5120 return TOOLBAR_PressButton (hwnd, wParam, lParam);
5122 /* case TB_REPLACEBITMAP: */
5124 case TB_SAVERESTOREA:
5125 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
5127 case TB_SAVERESTOREW:
5128 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
5130 case TB_SETANCHORHIGHLIGHT:
5131 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
5133 case TB_SETBITMAPSIZE:
5134 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
5136 case TB_SETBUTTONINFOA:
5137 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
5139 case TB_SETBUTTONINFOW:
5140 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
5142 case TB_SETBUTTONSIZE:
5143 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
5145 case TB_SETBUTTONWIDTH:
5146 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
5149 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
5151 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
5153 case TB_SETDISABLEDIMAGELIST:
5154 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
5156 case TB_SETDRAWTEXTFLAGS:
5157 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
5159 case TB_SETEXTENDEDSTYLE:
5160 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
5162 case TB_SETHOTIMAGELIST:
5163 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
5166 return TOOLBAR_SetHotItem (hwnd, wParam);
5168 case TB_SETIMAGELIST:
5169 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
5172 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
5174 /* case TB_SETINSERTMARK: */ /* 4.71 */
5176 case TB_SETINSERTMARKCOLOR:
5177 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
5179 case TB_SETMAXTEXTROWS:
5180 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
5182 /* case TB_SETPADDING: */ /* 4.71 */
5185 return TOOLBAR_SetParent (hwnd, wParam, lParam);
5188 return TOOLBAR_SetRows (hwnd, wParam, lParam);
5191 return TOOLBAR_SetState (hwnd, wParam, lParam);
5194 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
5196 case TB_SETTOOLTIPS:
5197 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
5199 case TB_SETUNICODEFORMAT:
5200 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
5202 case CCM_SETVERSION:
5203 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
5209 return TOOLBAR_Create (hwnd, wParam, lParam);
5212 return TOOLBAR_Destroy (hwnd, wParam, lParam);
5215 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
5218 return TOOLBAR_GetFont (hwnd, wParam, lParam);
5220 /* case WM_KEYDOWN: */
5221 /* case WM_KILLFOCUS: */
5223 case WM_LBUTTONDBLCLK:
5224 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
5226 case WM_LBUTTONDOWN:
5227 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
5230 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
5233 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
5236 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
5238 case WM_CAPTURECHANGED:
5239 return TOOLBAR_CaptureChanged(hwnd);
5242 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
5245 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
5248 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
5251 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
5254 return TOOLBAR_Notify (hwnd, wParam, lParam);
5256 /* case WM_NOTIFYFORMAT: */
5259 return TOOLBAR_Paint (hwnd, wParam);
5262 return TOOLBAR_SetRedraw (hwnd, wParam, lParam);
5265 return TOOLBAR_Size (hwnd, wParam, lParam);
5267 case WM_STYLECHANGED:
5268 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
5270 /* case WM_SYSCOLORCHANGE: */
5272 /* case WM_WININICHANGE: */
5277 case WM_MEASUREITEM:
5280 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
5282 return SendMessageA (infoPtr->hwndNotify, uMsg, wParam, lParam);
5284 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
5288 if (uMsg >= WM_USER)
5289 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
5290 uMsg, wParam, lParam);
5291 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
5298 TOOLBAR_Register (void)
5302 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
5303 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
5304 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
5305 wndClass.cbClsExtra = 0;
5306 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
5307 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
5308 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
5309 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
5311 RegisterClassA (&wndClass);
5316 TOOLBAR_Unregister (void)
5318 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);