4 * Copyright 1998,1999 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
7 * Differences between MSDN and actual native control operation:
8 * 1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
9 * to the right of the bitmap. Otherwise, this style is
10 * identical to TBSTYLE_FLAT."
11 * As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
12 * you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
13 * is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
14 * *not* imply TBSTYLE_FLAT as documented. (GA 8/2001)
18 * - A little bug in TOOLBAR_DrawMasked()
19 * - Button wrapping (under construction).
21 * - Notifications (under construction).
23 * - Tooltip support (almost complete).
24 * - Unicode suppport (under construction).
25 * - Fix TOOLBAR_SetButtonInfo32A/W.
26 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
27 * - I_IMAGECALLBACK support.
28 * - iString of -1 is undocumented
29 * - Customization dialog:
31 * - Minor buglet in 'available buttons' list:
32 * Buttons are not listed in M$-like order. M$ seems to use a single
33 * internal list to store the button information of both listboxes.
34 * - Drag list support.
35 * - Help and Reset button support.
38 * - Run tests using Waite Group Windows95 API Bible Volume 2.
39 * The second cdrom contains executables addstr.exe, btncount.exe,
40 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
41 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
42 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
43 * setparnt.exe, setrows.exe, toolwnd.exe.
44 * - Microsofts controlspy examples.
45 * - Charles Petzold's 'Programming Windows': gadgets.exe
54 #include "wine/unicode.h"
56 #include "imagelist.h"
58 #include "debugtools.h"
60 DEFAULT_DEBUG_CHANNEL(toolbar);
78 DWORD dwStructSize; /* size of TBBUTTON struct */
79 INT nHeight; /* height of the toolbar */
80 INT nWidth; /* width of the toolbar */
86 INT nRows; /* number of button rows */
87 INT nMaxTextRows; /* maximum number of text rows */
88 INT cxMin; /* minimum button width */
89 INT cxMax; /* maximum button width */
90 INT nNumButtons; /* number of buttons */
91 INT nNumBitmaps; /* number of bitmaps */
92 INT nNumStrings; /* number of strings */
93 BOOL bUnicode; /* ASCII (FALSE) or Unicode (TRUE)? */
94 BOOL bCaptured; /* mouse captured? */
97 INT nHotItem; /* index of the "hot" item */
98 HFONT hFont; /* text font */
99 HIMAGELIST himlInt; /* image list created internally */
100 HIMAGELIST himlDef; /* default image list */
101 HIMAGELIST himlHot; /* hot image list */
102 HIMAGELIST himlDis; /* disabled image list */
103 HWND hwndToolTip; /* handle to tool tip control */
104 HWND hwndNotify; /* handle to the window that gets notifications */
105 HWND hwndSelf; /* my own handle */
106 BOOL bTransparent; /* background transparency flag */
107 BOOL bAutoSize; /* auto size deadlock indicator */
108 BOOL bAnchor; /* anchor highlight enabled */
109 BOOL bNtfUnicode; /* TRUE if NOTIFYs use {W} */
110 DWORD dwExStyle; /* extended toolbar style */
111 DWORD dwDTFlags; /* DrawText flags */
113 COLORREF clrInsertMark; /* insert mark color */
114 RECT rcBound; /* bounding rectangle */
117 TBUTTON_INFO *buttons; /* pointer to button array */
118 LPWSTR *strings; /* pointer to string array */
119 } TOOLBAR_INFO, *PTOOLBAR_INFO;
122 /* used by customization dialog */
125 PTOOLBAR_INFO tbInfo;
127 } CUSTDLG_INFO, *PCUSTDLG_INFO;
135 } CUSTOMBUTTON, *PCUSTOMBUTTON;
138 #define SEPARATOR_WIDTH 8
140 #define BOTTOM_BORDER 2
141 #define DDARROW_WIDTH 11
143 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
144 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
145 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
149 TOOLBAR_DumpButton(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *bP, INT btn_num, BOOL internal)
151 if (TRACE_ON(toolbar)){
152 TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, string=%d\n",
153 btn_num, bP->idCommand,
154 bP->iBitmap, bP->fsState, bP->fsStyle, bP->dwData, bP->iString);
156 TRACE("button %d id %d, hot=%s, row=%d, rect=(%d,%d)-(%d,%d)\n",
157 btn_num, bP->idCommand,
158 (bP->bHot) ? "TRUE":"FALSE", bP->nRow,
159 bP->rect.left, bP->rect.top,
160 bP->rect.right, bP->rect.bottom);
166 TOOLBAR_DumpToolbar(TOOLBAR_INFO *iP, INT line)
168 if (TRACE_ON(toolbar)) {
172 dwStyle = GetWindowLongA (iP->hwndSelf, GWL_STYLE);
173 TRACE("toolbar %08x at line %d, exStyle=%08lx, buttons=%d, bitmaps=%d, strings=%d, style=%08lx\n",
175 iP->dwExStyle, iP->nNumButtons, iP->nNumBitmaps,
176 iP->nNumStrings, dwStyle);
177 TRACE("toolbar %08x at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p\n",
179 iP->himlInt, iP->himlDef, iP->himlHot, iP->himlDis);
180 for(i=0; i<iP->nNumButtons; i++) {
181 TOOLBAR_DumpButton(iP, &iP->buttons[i], i, TRUE);
187 /***********************************************************************
190 * This function validates that the styles set are implemented and
191 * issues FIXME's warning of possible problems. In a perfect world this
192 * function should be null.
195 TOOLBAR_CheckStyle (HWND hwnd, DWORD dwStyle)
197 if (dwStyle & TBSTYLE_ALTDRAG)
198 FIXME("[%04x] TBSTYLE_ALTDRAG not implemented\n", hwnd);
199 if (dwStyle & TBSTYLE_REGISTERDROP)
200 FIXME("[%04x] TBSTYLE_REGISTERDROP not implemented\n", hwnd);
201 if (dwStyle & TBSTYLE_TRANSPARENT)
202 FIXME("[%04x] TBSTYLE_TRANSPARENT not implemented\n", hwnd);
207 TOOLBAR_SendNotify (NMHDR *nmhdr, TOOLBAR_INFO *infoPtr, UINT code)
209 nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
210 nmhdr->hwndFrom = infoPtr->hwndSelf;
213 TRACE("to window %04x, code=%08x, %s\n", infoPtr->hwndNotify, code,
214 (infoPtr->bNtfUnicode) ? "via Unicode" : "via ANSI");
216 if (infoPtr->bNtfUnicode)
217 return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
218 (WPARAM) nmhdr->idFrom, (LPARAM)nmhdr);
220 return SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
221 (WPARAM) nmhdr->idFrom, (LPARAM)nmhdr);
225 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
227 LPWSTR lpText = NULL;
229 /* FIXME: iString == -1 is undocumented */
230 if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
231 lpText = (LPWSTR)btnPtr->iString;
232 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
233 lpText = infoPtr->strings[btnPtr->iString];
238 /***********************************************************************
239 * TOOLBAR_GetBitmapIndex
241 * This function returns the bitmap index associated with a button.
242 * If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO
243 * is issued to retrieve the index.
246 TOOLBAR_GetBitmapIndex(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
248 INT ret = btnPtr->iBitmap;
250 if (ret == I_IMAGECALLBACK) {
251 /* issue TBN_GETDISPINFO */
254 nmgd.idCommand = btnPtr->idCommand;
255 nmgd.lParam = btnPtr->dwData;
256 nmgd.dwMask = TBNF_IMAGE;
257 TOOLBAR_SendNotify ((NMHDR *) &nmgd, infoPtr,
258 (infoPtr->bNtfUnicode) ? TBN_GETDISPINFOW :
260 if (nmgd.dwMask & TBNF_DI_SETITEM) {
261 btnPtr->iBitmap = nmgd.iImage;
264 TRACE("TBN_GETDISPINFOA returned bitmap id %d, mask=%08lx, nNumBitmaps=%d\n",
265 ret, nmgd.dwMask, infoPtr->nNumBitmaps);
272 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
274 if (((index>=0) && (index <= infoPtr->nNumBitmaps)) ||
275 (index == I_IMAGECALLBACK))
282 /***********************************************************************
283 * TOOLBAR_DrawImageList
285 * This function validates the bitmap index (including I_IMAGECALLBACK
286 * functionality). It then draws the image via the ImageList_Draw
287 * function. It returns TRUE if the image was drawn, FALSE otherwise.
290 TOOLBAR_DrawImageList (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl,
291 HDC hdc, UINT left, UINT top, UINT draw_flags)
295 if (!himl) return FALSE;
297 if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
298 ERR("index %d is not valid, max %d\n",
299 btnPtr->iBitmap, infoPtr->nNumBitmaps);
303 if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {
304 if (index == -1) return FALSE;
305 ERR("TBN_GETDISPINFO returned invalid index %d\n",
309 TRACE("drawing index=%d, himl=%p, left=%d, top=%d, flags=%08x\n",
310 index, himl, left, top, draw_flags);
312 ImageList_Draw (himl, index, hdc, left, top, draw_flags);
317 /***********************************************************************
318 * TOOLBAR_TestImageExist
320 * This function is similar to TOOLBAR_DrawImageList, except it does not
321 * draw the image. The I_IMAGECALLBACK functionality is implemented.
324 TOOLBAR_TestImageExist (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl)
328 if (!himl) return FALSE;
330 if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
331 ERR("index %d is not valid, max %d\n",
332 btnPtr->iBitmap, infoPtr->nNumBitmaps);
336 if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {
337 if (index == -1) return FALSE;
338 ERR("TBN_GETDISPINFO returned invalid index %d\n",
347 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
349 INT x = (lpRect->left + lpRect->right) / 2 - 1;
350 INT yBottom = lpRect->bottom - 3;
351 INT yTop = lpRect->top + 1;
353 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
354 MoveToEx (hdc, x, yBottom, NULL);
355 LineTo (hdc, x, yTop);
357 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
358 MoveToEx (hdc, x, yBottom, NULL);
359 LineTo (hdc, x, yTop);
363 /***********************************************************************
364 * TOOLBAR_DrawDDFlatSeparator
366 * This function draws the separator that was flaged as TBSTYLE_DROPDOWN.
367 * In this case, the separator is a pixel high line of COLOR_BTNSHADOW,
368 * followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators
369 * are horizontal as opposed to the vertical separators for not dropdown
372 * FIXME: It is possible that the height of each line is really SM_CYBORDER.
375 TOOLBAR_DrawDDFlatSeparator (LPRECT lpRect, HDC hdc, TBUTTON_INFO *btnPtr)
378 COLORREF oldcolor, newcolor;
380 myrect.left = lpRect->left;
381 myrect.right = lpRect->right;
382 myrect.top = lpRect->top + (lpRect->bottom - lpRect->top - 2)/2;
383 myrect.bottom = myrect.top + 1;
385 InflateRect (&myrect, -2, 0);
387 TRACE("rect=(%d,%d)-(%d,%d)\n",
388 myrect.left, myrect.top, myrect.right, myrect.bottom);
390 newcolor = GetSysColor (COLOR_BTNSHADOW);
391 oldcolor = SetBkColor (hdc, newcolor);
392 ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
394 myrect.top = myrect.bottom;
395 myrect.bottom = myrect.top + 1;
397 newcolor = GetSysColor (COLOR_BTNHIGHLIGHT);
398 SetBkColor (hdc, newcolor);
399 ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
401 SetBkColor (hdc, oldcolor);
406 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
409 SelectObject ( hdc, GetSysColorPen (colorRef));
412 MoveToEx (hdc, x, y, NULL);
413 LineTo (hdc, x+5, y++); x++;
414 MoveToEx (hdc, x, y, NULL);
415 LineTo (hdc, x+3, y++); x++;
416 MoveToEx (hdc, x, y, NULL);
417 LineTo (hdc, x+1, y++);
421 * Draw the text string for this button.
422 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
423 * is non-zero, so we can simply check himlDef to see if we have
427 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
428 HDC hdc, INT nState, DWORD dwStyle)
430 RECT rcText = btnPtr->rect;
433 LPWSTR lpText = NULL;
434 HIMAGELIST himl = infoPtr->himlDef;
436 TRACE ("iString: %x\n", btnPtr->iString);
438 /* get a pointer to the text */
439 lpText = TOOLBAR_GetText(infoPtr, btnPtr);
441 TRACE ("lpText: %s\n", debugstr_w(lpText));
446 InflateRect (&rcText, -3, -3);
448 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
449 /* The following test looked like this before
450 * I changed it. IE4 "Links" toolbar would not
451 * draw correctly with the original code. - GA 8/01
452 * ((dwStyle & TBSTYLE_LIST) &&
453 * ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
454 * (btnPtr->iBitmap != I_IMAGENONE))
456 if (dwStyle & TBSTYLE_LIST) {
457 /* LIST style w/ ICON offset is by matching native. */
458 /* Matches IE4 "Links" bar. - GA 8/01 */
459 rcText.left += (infoPtr->nBitmapWidth + 2);
462 rcText.top += infoPtr->nBitmapHeight;
466 if (dwStyle & TBSTYLE_LIST) {
467 /* LIST style w/o ICON offset is by matching native. */
468 /* Matches IE4 "menu" bar. - GA 8/01 */
473 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
474 OffsetRect (&rcText, 1, 1);
476 TRACE("string rect=(%d,%d)-(%d,%d)\n",
477 rcText.left, rcText.top, rcText.right, rcText.bottom);
479 hOldFont = SelectObject (hdc, infoPtr->hFont);
480 if (!(nState & TBSTATE_ENABLED)) {
481 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
482 OffsetRect (&rcText, 1, 1);
483 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
484 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
485 OffsetRect (&rcText, -1, -1);
486 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
488 else if (nState & TBSTATE_INDETERMINATE) {
489 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
490 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
493 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
494 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
497 SetTextColor (hdc, clrOld);
498 SelectObject (hdc, hOldFont);
504 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
506 HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush);
507 INT cx = lpRect->right - lpRect->left;
508 INT cy = lpRect->bottom - lpRect->top;
509 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
510 SelectObject (hdc, hbr);
515 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
516 HDC hdc, INT x, INT y)
518 /* FIXME: this function is a hack since it uses image list
519 internals directly */
521 HIMAGELIST himl = infoPtr->himlDef;
529 /* create new dc's */
530 hdcImageList = CreateCompatibleDC (0);
531 hdcMask = CreateCompatibleDC (0);
533 /* create new bitmap */
534 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
535 SelectObject (hdcMask, hbmMask);
537 /* copy the mask bitmap */
538 SelectObject (hdcImageList, himl->hbmMask);
539 SetBkColor (hdcImageList, RGB(255, 255, 255));
540 SetTextColor (hdcImageList, RGB(0, 0, 0));
541 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
542 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
544 /* draw the new mask */
545 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
546 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
547 hdcMask, 0, 0, 0xB8074A);
549 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
550 BitBlt (hdc, x, y, himl->cx, himl->cy,
551 hdcMask, 0, 0, 0xB8074A);
553 DeleteObject (hbmMask);
555 DeleteDC (hdcImageList);
560 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
562 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
563 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
564 BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
565 (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
566 RECT rc, rcArrow, rcBitmap;
568 if (btnPtr->fsState & TBSTATE_HIDDEN)
572 CopyRect (&rcArrow, &rc);
573 CopyRect(&rcBitmap, &rc);
575 if (!infoPtr->bTransparent)
576 FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
578 if (hasDropDownArrow)
580 if (dwStyle & TBSTYLE_FLAT)
581 rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
583 rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
584 rcArrow.left = rc.right;
587 /* Center the bitmap horizontally and vertically */
588 if (dwStyle & TBSTYLE_LIST)
591 rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
593 if(TOOLBAR_HasText(infoPtr, btnPtr))
594 rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
596 rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
598 TRACE("iBitmap: %d, start=(%d,%d) w=%d, h=%d\n",
599 btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,
600 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
603 if (btnPtr->fsStyle & TBSTYLE_SEP) {
604 /* with the FLAT style, iBitmap is the width and has already */
605 /* been taken into consideration in calculating the width */
606 /* so now we need to draw the vertical separator */
607 /* empirical tests show that iBitmap can/will be non-zero */
608 /* when drawing the vertical bar... */
609 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */) {
610 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
611 TOOLBAR_DrawDDFlatSeparator (&rc, hdc, btnPtr);
613 TOOLBAR_DrawFlatSeparator (&rc, hdc);
619 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
620 if (!(dwStyle & TBSTYLE_FLAT))
622 DrawEdge (hdc, &rc, EDGE_RAISED,
623 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
624 if (hasDropDownArrow)
625 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
626 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
629 if (hasDropDownArrow)
631 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
632 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
635 if (!TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDis,
636 hdc, rcBitmap.left, rcBitmap.top,
638 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
640 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
644 /* pressed TBSTYLE_BUTTON */
645 if (btnPtr->fsState & TBSTATE_PRESSED) {
646 if (dwStyle & TBSTYLE_FLAT)
648 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
649 if (hasDropDownArrow)
650 DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
654 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
655 if (hasDropDownArrow)
656 DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
659 if (hasDropDownArrow)
660 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
662 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
663 hdc, rcBitmap.left+1, rcBitmap.top+1,
666 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
670 /* checked TBSTYLE_CHECK */
671 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
672 (btnPtr->fsState & TBSTATE_CHECKED)) {
673 if (dwStyle & TBSTYLE_FLAT)
674 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
675 BF_RECT | BF_ADJUST);
677 DrawEdge (hdc, &rc, EDGE_SUNKEN,
678 BF_RECT | BF_MIDDLE | BF_ADJUST);
680 TOOLBAR_DrawPattern (hdc, &rc);
682 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
683 hdc, rcBitmap.left+1, rcBitmap.top+1,
686 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
691 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
692 DrawEdge (hdc, &rc, EDGE_RAISED,
693 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
695 TOOLBAR_DrawPattern (hdc, &rc);
696 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
697 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
702 if (dwStyle & TBSTYLE_FLAT)
706 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT);
707 if (hasDropDownArrow)
708 DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT);
711 else /* The following code needs to be removed after
712 * "hot item" support has been implemented for the
713 * case where it is being de-selected.
716 FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
717 if (hasDropDownArrow)
718 FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
722 if (hasDropDownArrow)
723 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
726 /* if hot, attempt to draw with himlHot, if fails, use himlDef */
727 if (!TOOLBAR_DrawImageList (infoPtr, btnPtr,
730 rcBitmap.top, ILD_NORMAL))
731 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
732 hdc, rcBitmap.left, rcBitmap.top,
736 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
737 hdc, rcBitmap.left, rcBitmap.top,
742 DrawEdge (hdc, &rc, EDGE_RAISED,
743 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
745 if (hasDropDownArrow)
747 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
748 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
749 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
752 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
753 hdc, rcBitmap.left, rcBitmap.top,
757 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
762 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
764 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
765 TBUTTON_INFO *btnPtr;
766 INT i, oldBKmode = 0;
769 /* if imagelist belongs to the app, it can be changed
770 by the app after setting it */
771 if (infoPtr->himlDef != infoPtr->himlInt)
772 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
774 TOOLBAR_DumpToolbar (infoPtr, __LINE__);
776 if (infoPtr->bTransparent)
777 oldBKmode = SetBkMode (hdc, TRANSPARENT);
779 /* redraw necessary buttons */
780 btnPtr = infoPtr->buttons;
781 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
783 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
784 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
787 if (infoPtr->bTransparent && (oldBKmode != TRANSPARENT))
788 SetBkMode (hdc, oldBKmode);
791 /***********************************************************************
792 * TOOLBAR_MeasureString
794 * This function gets the width and height of a string in pixels. This
795 * is done first by using GetTextExtentPoint to get the basic width
796 * and height. The DrawText is called with DT_CALCRECT to get the exact
797 * width. The reason is because the text may have more than one "&" (or
798 * prefix characters as M$ likes to call them). The prefix character
799 * indicates where the underline goes, except for the string "&&" which
800 * is reduced to a single "&". GetTextExtentPoint does not process these
801 * only DrawText does. Note that the TBSTYLE_NOPREFIX is handled here.
804 TOOLBAR_MeasureString(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
805 HDC hdc, LPSIZE lpSize)
812 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
813 (btnPtr->iString > -1) &&
814 (btnPtr->iString < infoPtr->nNumStrings))
816 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
818 /* first get size of all the text */
819 GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
821 /* feed above size into the rectangle for DrawText */
822 myrect.left = myrect.top = 0;
823 myrect.right = lpSize->cx;
824 myrect.bottom = lpSize->cy;
826 /* Use DrawText to get true size as drawn (less pesky "&") */
827 DrawTextW (hdc, lpText, -1, &myrect, DT_VCENTER | DT_SINGLELINE |
828 DT_CALCRECT | ((btnPtr->fsStyle & TBSTYLE_NOPREFIX) ?
831 /* feed back to caller */
832 lpSize->cx = myrect.right;
833 lpSize->cy = myrect.bottom;
836 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
839 /***********************************************************************
840 * TOOLBAR_CalcStrings
842 * This function walks through each string and measures it and returns
843 * the largest height and width to caller.
846 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
848 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
849 TBUTTON_INFO *btnPtr;
859 hOldFont = SelectObject (hdc, infoPtr->hFont);
861 btnPtr = infoPtr->buttons;
862 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
863 if(TOOLBAR_HasText(infoPtr, btnPtr))
865 TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
866 if (sz.cx > lpSize->cx)
868 if (sz.cy > lpSize->cy)
873 SelectObject (hdc, hOldFont);
874 ReleaseDC (hwnd, hdc);
876 TRACE("max string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
879 /***********************************************************************
880 * TOOLBAR_WrapToolbar
882 * This function walks through the buttons and seperators in the
883 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
884 * wrapping should occur based on the width of the toolbar window.
885 * It does *not* calculate button placement itself. That task
886 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
887 * the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE
888 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
892 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
894 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
895 TBUTTON_INFO *btnPtr;
898 BOOL bWrap, bButtonWrap;
900 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
901 /* no layout is necessary. Applications may use this style */
902 /* to perform their own layout on the toolbar. */
903 if( !(dwStyle & TBSTYLE_WRAPABLE) )
906 btnPtr = infoPtr->buttons;
907 x = infoPtr->nIndent;
909 /* this can get the parents width, to know how far we can extend
910 * this toolbar. We cannot use its height, as there may be multiple
911 * toolbars in a rebar control
913 GetClientRect( GetParent(hwnd), &rc );
914 infoPtr->nWidth = rc.right - rc.left;
917 TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
918 infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth,
921 for (i = 0; i < infoPtr->nNumButtons; i++ )
924 btnPtr[i].fsState &= ~TBSTATE_WRAP;
926 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
929 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
930 /* it is the actual width of the separator. This is used for */
931 /* custom controls in toolbars. */
933 /* TBSTYLE_DROPDOWN separators are treated as buttons for */
934 /* width. - GA 8/01 */
935 if ((btnPtr[i].fsStyle & TBSTYLE_SEP) &&
936 !(btnPtr[i].fsStyle & TBSTYLE_DROPDOWN))
937 cx = (btnPtr[i].iBitmap > 0) ?
938 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
940 cx = infoPtr->nButtonWidth;
942 /* Two or more adjacent separators form a separator group. */
943 /* The first separator in a group should be wrapped to the */
944 /* next row if the previous wrapping is on a button. */
946 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
947 (i + 1 < infoPtr->nNumButtons ) &&
948 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
950 TRACE("wrap point 1 btn %d style %02x\n", i, btnPtr[i].fsStyle);
951 btnPtr[i].fsState |= TBSTATE_WRAP;
952 x = infoPtr->nIndent;
958 /* The layout makes sure the bitmap is visible, but not the button. */
959 /* Test added to also wrap after a button that starts a row but */
960 /* is bigger than the area. - GA 8/01 */
961 if (( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
962 > infoPtr->nWidth ) ||
963 ((x == infoPtr->nIndent) && (cx > infoPtr->nWidth)))
967 /* If the current button is a separator and not hidden, */
968 /* go to the next until it reaches a non separator. */
969 /* Wrap the last separator if it is before a button. */
970 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
971 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
972 i < infoPtr->nNumButtons )
978 if( bFound && i < infoPtr->nNumButtons )
981 TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
982 i, btnPtr[i].fsStyle, x, cx);
983 btnPtr[i].fsState |= TBSTATE_WRAP;
984 x = infoPtr->nIndent;
988 else if ( i >= infoPtr->nNumButtons)
991 /* If the current button is not a separator, find the last */
992 /* separator and wrap it. */
993 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
995 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
996 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
1000 TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
1001 i, btnPtr[i].fsStyle, x, cx);
1002 x = infoPtr->nIndent;
1003 btnPtr[j].fsState |= TBSTATE_WRAP;
1004 bButtonWrap = FALSE;
1009 /* If no separator available for wrapping, wrap one of */
1010 /* non-hidden previous button. */
1014 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
1016 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
1021 TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
1022 i, btnPtr[i].fsStyle, x, cx);
1023 x = infoPtr->nIndent;
1024 btnPtr[j].fsState |= TBSTATE_WRAP;
1030 /* If all above failed, wrap the current button. */
1033 TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
1034 i, btnPtr[i].fsStyle, x, cx);
1035 btnPtr[i].fsState |= TBSTATE_WRAP;
1037 x = infoPtr->nIndent;
1038 if (btnPtr[i].fsStyle & TBSTYLE_SEP )
1039 bButtonWrap = FALSE;
1045 TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
1046 i, btnPtr[i].fsStyle, x, cx);
1053 /***********************************************************************
1054 * TOOLBAR_CalcToolbar
1056 * This function calculates button and separator placement. It first
1057 * calculates the button sizes, gets the toolbar window width and then
1058 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
1059 * on. It assigns a new location to each item and sends this location to
1060 * the tooltip window if appropriate. Finally, it updates the rcBound
1061 * rect and calculates the new required toolbar window height.
1065 TOOLBAR_CalcToolbar (HWND hwnd)
1067 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
1068 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1069 TBUTTON_INFO *btnPtr;
1070 INT i, nRows, nSepRows;
1074 BOOL usesBitmaps = FALSE;
1075 BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
1077 TOOLBAR_CalcStrings (hwnd, &sizeString);
1079 if (dwStyle & TBSTYLE_LIST)
1081 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
1082 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
1085 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
1087 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
1091 if (sizeString.cy > 0)
1094 infoPtr->nButtonHeight = sizeString.cy +
1095 infoPtr->nBitmapHeight + 6;
1097 infoPtr->nButtonHeight = sizeString.cy + 6;
1099 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
1100 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
1102 if (sizeString.cx > infoPtr->nBitmapWidth)
1103 infoPtr->nButtonWidth = sizeString.cx + 6;
1104 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
1105 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
1108 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
1109 infoPtr->nButtonWidth = infoPtr->cxMin;
1110 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
1111 infoPtr->nButtonWidth = infoPtr->cxMax;
1113 TOOLBAR_WrapToolbar( hwnd, dwStyle );
1115 x = infoPtr->nIndent;
1116 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
1119 * We will set the height below, and we set the width on entry
1120 * so we do not reset them here..
1123 GetClientRect( hwnd, &rc );
1124 /* get initial values for toolbar */
1125 infoPtr->nWidth = rc.right - rc.left;
1126 infoPtr->nHeight = rc.bottom - rc.top;
1129 /* from above, minimum is a button, and possible text */
1130 cx = infoPtr->nButtonWidth;
1132 /* cannot use just ButtonHeight, we may have no buttons! */
1133 if (infoPtr->nNumButtons > 0)
1134 infoPtr->nHeight = infoPtr->nButtonHeight;
1136 cy = infoPtr->nHeight;
1138 nRows = nSepRows = 0;
1140 infoPtr->rcBound.top = y;
1141 infoPtr->rcBound.left = x;
1142 infoPtr->rcBound.bottom = y + cy;
1143 infoPtr->rcBound.right = x;
1145 btnPtr = infoPtr->buttons;
1147 /* do not base height/width on parent, if the parent is a */
1148 /* rebar control it could have multiple rows of toolbars */
1149 /* GetClientRect( GetParent(hwnd), &rc ); */
1150 /* cx = rc.right - rc.left; */
1151 /* cy = rc.bottom - rc.top; */
1153 TRACE("cy=%d\n", cy);
1155 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
1158 if (btnPtr->fsState & TBSTATE_HIDDEN)
1160 SetRectEmpty (&btnPtr->rect);
1164 cy = infoPtr->nHeight;
1166 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1167 /* it is the actual width of the separator. This is used for */
1168 /* custom controls in toolbars. */
1169 if (btnPtr->fsStyle & TBSTYLE_SEP) {
1170 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
1171 cy = (btnPtr->iBitmap > 0) ?
1172 btnPtr->iBitmap : SEPARATOR_WIDTH;
1173 cx = infoPtr->nButtonWidth;
1176 cx = (btnPtr->iBitmap > 0) ?
1177 btnPtr->iBitmap : SEPARATOR_WIDTH;
1181 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
1188 hOldFont = SelectObject (hdc, infoPtr->hFont);
1190 TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
1192 SelectObject (hdc, hOldFont);
1193 ReleaseDC (hwnd, hdc);
1195 /* Fudge amount measured against IE4 "menu" and "Links" */
1196 /* toolbars with native control (v4.71). - GA 8/01 */
1197 cx = sz.cx + 6 + 5 + 5;
1198 if ((dwStyle & TBSTYLE_LIST) &&
1199 (TOOLBAR_TestImageExist (infoPtr, btnPtr, infoPtr->himlDef)))
1200 cx += infoPtr->nBitmapWidth;
1203 cx = infoPtr->nButtonWidth;
1205 if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
1206 cx += DDARROW_WIDTH;
1208 if (btnPtr->fsState & TBSTATE_WRAP )
1211 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
1213 if (infoPtr->rcBound.left > x)
1214 infoPtr->rcBound.left = x;
1215 if (infoPtr->rcBound.right < x + cx)
1216 infoPtr->rcBound.right = x + cx;
1217 if (infoPtr->rcBound.bottom < y + cy)
1218 infoPtr->rcBound.bottom = y + cy;
1220 /* Set the toolTip only for non-hidden, non-separator button */
1221 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
1225 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1226 ti.cbSize = sizeof(TTTOOLINFOA);
1228 ti.uId = btnPtr->idCommand;
1229 ti.rect = btnPtr->rect;
1230 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
1234 /* btnPtr->nRow is zero based. The space between the rows is */
1235 /* also considered as a row. */
1236 btnPtr->nRow = nRows + nSepRows;
1238 TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d\n",
1239 i, btnPtr->fsStyle, bWrap, nRows, nSepRows, btnPtr->nRow);
1243 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
1247 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1248 /* it is the actual width of the separator. This is used for */
1249 /* custom controls in toolbars. */
1250 if ( !(btnPtr->fsStyle & TBSTYLE_DROPDOWN))
1251 y += cy + ( (btnPtr->iBitmap > 0 ) ?
1252 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
1256 /* nSepRows is used to calculate the extra height follwoing */
1260 x = infoPtr->nIndent;
1267 /* infoPtr->nRows is the number of rows on the toolbar */
1268 infoPtr->nRows = nRows + nSepRows + 1;
1270 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
1272 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
1273 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
1274 nSepRows * (infoPtr->nBitmapHeight + 1) +
1276 TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
1281 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
1283 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1284 TBUTTON_INFO *btnPtr;
1287 btnPtr = infoPtr->buttons;
1288 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
1289 if (btnPtr->fsState & TBSTATE_HIDDEN)
1292 if (btnPtr->fsStyle & TBSTYLE_SEP) {
1293 if (PtInRect (&btnPtr->rect, *lpPt)) {
1294 TRACE(" ON SEPARATOR %d!\n", i);
1299 if (PtInRect (&btnPtr->rect, *lpPt)) {
1300 TRACE(" ON BUTTON %d!\n", i);
1306 TRACE(" NOWHERE!\n");
1312 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
1314 TBUTTON_INFO *btnPtr;
1317 btnPtr = infoPtr->buttons;
1318 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
1319 if (btnPtr->idCommand == idCommand) {
1320 TRACE("command=%d index=%d\n", idCommand, i);
1324 TRACE("no index found for command=%d\n", idCommand);
1330 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
1332 TBUTTON_INFO *btnPtr;
1335 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
1338 /* check index button */
1339 btnPtr = &infoPtr->buttons[nIndex];
1340 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1341 if (btnPtr->fsState & TBSTATE_CHECKED)
1345 /* check previous buttons */
1346 nRunIndex = nIndex - 1;
1347 while (nRunIndex >= 0) {
1348 btnPtr = &infoPtr->buttons[nRunIndex];
1349 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1350 if (btnPtr->fsState & TBSTATE_CHECKED)
1358 /* check next buttons */
1359 nRunIndex = nIndex + 1;
1360 while (nRunIndex < infoPtr->nNumButtons) {
1361 btnPtr = &infoPtr->buttons[nRunIndex];
1362 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1363 if (btnPtr->fsState & TBSTATE_CHECKED)
1376 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
1377 WPARAM wParam, LPARAM lParam)
1383 msg.wParam = wParam;
1384 msg.lParam = lParam;
1385 msg.time = GetMessageTime ();
1386 msg.pt.x = LOWORD(GetMessagePos ());
1387 msg.pt.y = HIWORD(GetMessagePos ());
1389 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1393 /***********************************************************************
1394 * TOOLBAR_CustomizeDialogProc
1395 * This function implements the toolbar customization dialog.
1398 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1400 PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongA (hwnd, DWL_USER);
1401 PCUSTOMBUTTON btnInfo;
1403 TOOLBAR_INFO *infoPtr = custInfo->tbInfo;
1408 custInfo = (PCUSTDLG_INFO)lParam;
1409 SetWindowLongA (hwnd, DWL_USER, (DWORD)custInfo);
1417 /* send TBN_QUERYINSERT notification */
1418 nmtb.iItem = custInfo->tbInfo->nNumButtons;
1420 if (!TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_QUERYINSERT))
1423 /* add items to 'toolbar buttons' list and check if removable */
1424 for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
1426 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1427 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1428 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1429 btnInfo->bVirtual = FALSE;
1430 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1432 /* send TBN_QUERYDELETE notification */
1434 btnInfo->bRemovable = TOOLBAR_SendNotify ((NMHDR *) &nmtb,
1438 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
1439 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1442 /* insert separator button into 'available buttons' list */
1443 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1444 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1445 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1446 btnInfo->bVirtual = FALSE;
1447 btnInfo->bRemovable = TRUE;
1448 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1449 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1450 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1452 /* insert all buttons into dsa */
1455 /* send TBN_GETBUTTONINFO notification */
1457 nmtb.pszText = Buffer;
1460 if (!TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_GETBUTTONINFOA))
1463 TRACE("style: %x\n", nmtb.tbButton.fsStyle);
1465 /* insert button into the apropriate list */
1466 index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand);
1469 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1470 memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1471 btnInfo->bVirtual = FALSE;
1472 btnInfo->bRemovable = TRUE;
1473 if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1474 strcpy (btnInfo->text, nmtb.pszText);
1476 index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1477 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1481 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1482 memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1483 if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1484 strcpy (btnInfo->text, nmtb.pszText);
1486 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1490 /* select first item in the 'available' list */
1491 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);
1493 /* append 'virtual' separator button to the 'toolbar buttons' list */
1494 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1495 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1496 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1497 btnInfo->bVirtual = TRUE;
1498 btnInfo->bRemovable = FALSE;
1499 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1500 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1501 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1503 /* select last item in the 'toolbar' list */
1504 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
1505 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);
1507 /* set focus and disable buttons */
1508 PostMessageA (hwnd, WM_USER, 0, 0);
1513 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1514 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1515 EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
1516 SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
1520 EndDialog(hwnd, FALSE);
1524 switch (LOWORD(wParam))
1526 case IDC_TOOLBARBTN_LBOX:
1527 if (HIWORD(wParam) == LBN_SELCHANGE)
1529 PCUSTOMBUTTON btnInfo;
1534 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1535 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1537 /* send TBN_QUERYINSERT notification */
1539 TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1542 /* get list box item */
1543 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1545 if (index == (count - 1))
1547 /* last item (virtual separator) */
1548 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1549 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1551 else if (index == (count - 2))
1553 /* second last item (last non-virtual item) */
1554 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1555 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1557 else if (index == 0)
1560 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1561 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1565 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1566 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1569 EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
1573 case IDC_MOVEUP_BTN:
1575 PCUSTOMBUTTON btnInfo;
1579 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1580 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1581 TRACE("Move up: index %d\n", index);
1583 /* send TBN_QUERYINSERT notification */
1586 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1589 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1591 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1592 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index-1, 0);
1593 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index-1, (LPARAM)btnInfo);
1594 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1597 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1598 else if (index >= (count - 3))
1599 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1601 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1602 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index-1, (LPARAM)&(btnInfo->btn));
1607 case IDC_MOVEDN_BTN: /* move down */
1609 PCUSTOMBUTTON btnInfo;
1613 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1614 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1615 TRACE("Move up: index %d\n", index);
1617 /* send TBN_QUERYINSERT notification */
1619 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1622 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1624 /* move button down */
1625 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1626 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index+1, 0);
1627 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index+1, (LPARAM)btnInfo);
1628 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index+1 , 0);
1631 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1632 else if (index >= (count - 3))
1633 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1635 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1636 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index+1, (LPARAM)&(btnInfo->btn));
1641 case IDC_REMOVE_BTN: /* remove button */
1643 PCUSTOMBUTTON btnInfo;
1646 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1647 TRACE("Remove: index %d\n", index);
1649 /* send TBN_QUERYDELETE notification */
1651 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1654 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1655 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1656 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index , 0);
1658 SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1660 /* insert into 'available button' list */
1661 if (!(btnInfo->btn.fsStyle & TBSTYLE_SEP))
1663 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1664 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1667 COMCTL32_Free (btnInfo);
1672 case IDOK: /* Add button */
1677 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1678 index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
1679 TRACE("Add: index %d\n", index);
1681 /* send TBN_QUERYINSERT notification */
1683 if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1686 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, index, 0);
1690 /* remove from 'available buttons' list */
1691 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_DELETESTRING, index, 0);
1692 if (index == count-1)
1693 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1695 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index , 0);
1699 PCUSTOMBUTTON btnNew;
1701 /* duplicate 'separator' button */
1702 btnNew = (PCUSTOMBUTTON)COMCTL32_Alloc (sizeof(CUSTOMBUTTON));
1703 memcpy (btnNew, btnInfo, sizeof(CUSTOMBUTTON));
1707 /* insert into 'toolbar button' list */
1708 index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1709 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index, 0);
1710 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1712 SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index, (LPARAM)&(btnInfo->btn));
1718 EndDialog(hwnd, FALSE);
1728 /* delete items from 'toolbar buttons' listbox*/
1729 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1730 for (i = 0; i < count; i++)
1732 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
1733 COMCTL32_Free(btnInfo);
1734 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
1736 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);
1739 /* delete items from 'available buttons' listbox*/
1740 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1741 for (i = 0; i < count; i++)
1743 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
1744 COMCTL32_Free(btnInfo);
1745 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
1747 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
1752 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1754 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1759 COLORREF oldText = 0;
1763 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0);
1764 if (btnInfo == NULL)
1766 FIXME("btnInfo invalid!\n");
1770 /* set colors and select objects */
1771 oldBk = SetBkColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1772 if (btnInfo->bVirtual)
1773 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
1775 oldText = SetTextColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHTTEXT:COLOR_WINDOWTEXT));
1776 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1777 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1779 /* fill background rectangle */
1780 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1781 lpdis->rcItem.right, lpdis->rcItem.bottom);
1783 /* calculate button and text rectangles */
1784 CopyRect (&rcButton, &lpdis->rcItem);
1785 InflateRect (&rcButton, -1, -1);
1786 CopyRect (&rcText, &rcButton);
1787 rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
1788 rcText.left = rcButton.right + 2;
1790 /* draw focus rectangle */
1791 if (lpdis->itemState & ODS_FOCUS)
1792 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1795 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1797 /* draw image and text */
1798 if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
1799 ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
1800 rcButton.left+3, rcButton.top+3, ILD_NORMAL);
1801 DrawTextA (lpdis->hDC, btnInfo->text, -1, &rcText,
1802 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1804 /* delete objects and reset colors */
1805 SelectObject (lpdis->hDC, hOldBrush);
1806 SelectObject (lpdis->hDC, hOldPen);
1807 SetBkColor (lpdis->hDC, oldBk);
1808 SetTextColor (lpdis->hDC, oldText);
1814 case WM_MEASUREITEM:
1815 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1817 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1819 if (custInfo && custInfo->tbInfo)
1820 lpmis->itemHeight = custInfo->tbInfo->nBitmapHeight + 8;
1822 lpmis->itemHeight = 15 + 8; /* default height */
1834 /***********************************************************************
1835 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1839 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1841 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1842 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1843 INT nIndex = 0, nButtons, nCount;
1846 TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1850 if (lpAddBmp->hInst == HINST_COMMCTRL)
1852 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1854 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1856 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1861 TRACE ("adding %d internal bitmaps!\n", nButtons);
1863 /* Windows resize all the buttons to the size of a newly added standard image */
1864 if (lpAddBmp->nID & 1)
1867 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
1868 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
1870 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1871 MAKELPARAM((WORD)24, (WORD)24));
1872 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1873 MAKELPARAM((WORD)31, (WORD)30));
1878 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1879 MAKELPARAM((WORD)16, (WORD)16));
1880 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1881 MAKELPARAM((WORD)22, (WORD)22));
1884 TOOLBAR_CalcToolbar (hwnd);
1888 nButtons = (INT)wParam;
1892 TRACE ("adding %d bitmaps!\n", nButtons);
1895 if (!(infoPtr->himlDef)) {
1896 /* create new default image list */
1897 TRACE ("creating default image list!\n");
1900 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1901 ILC_COLOR | ILC_MASK, nButtons, 2);
1902 infoPtr->himlInt = infoPtr->himlDef;
1905 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1907 /* Add bitmaps to the default image list */
1908 if (lpAddBmp->hInst == (HINSTANCE)0)
1911 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1914 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1916 /* Add system bitmaps */
1917 switch (lpAddBmp->nID)
1919 case IDB_STD_SMALL_COLOR:
1920 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1921 MAKEINTRESOURCEA(IDB_STD_SMALL));
1922 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1923 hbmLoad, CLR_DEFAULT);
1924 DeleteObject (hbmLoad);
1927 case IDB_STD_LARGE_COLOR:
1928 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1929 MAKEINTRESOURCEA(IDB_STD_LARGE));
1930 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1931 hbmLoad, CLR_DEFAULT);
1932 DeleteObject (hbmLoad);
1935 case IDB_VIEW_SMALL_COLOR:
1936 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1937 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1938 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1939 hbmLoad, CLR_DEFAULT);
1940 DeleteObject (hbmLoad);
1943 case IDB_VIEW_LARGE_COLOR:
1944 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1945 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1946 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1947 hbmLoad, CLR_DEFAULT);
1948 DeleteObject (hbmLoad);
1951 case IDB_HIST_SMALL_COLOR:
1952 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1953 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1954 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1955 hbmLoad, CLR_DEFAULT);
1956 DeleteObject (hbmLoad);
1959 case IDB_HIST_LARGE_COLOR:
1960 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1961 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1962 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1963 hbmLoad, CLR_DEFAULT);
1964 DeleteObject (hbmLoad);
1968 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1969 ERR ("invalid imagelist!\n");
1975 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1976 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1977 DeleteObject (hbmLoad);
1982 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1984 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1986 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",
1987 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1988 infoPtr->nNumBitmaps+nButtons,imagecount);
1990 infoPtr->nNumBitmaps = imagecount;
1993 infoPtr->nNumBitmaps += nButtons;
1996 InvalidateRect(hwnd, NULL, FALSE);
2003 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2005 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2006 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2007 INT nOldButtons, nNewButtons, nAddButtons, nCount;
2009 TRACE("adding %d buttons!\n", wParam);
2011 nAddButtons = (UINT)wParam;
2012 nOldButtons = infoPtr->nNumButtons;
2013 nNewButtons = nOldButtons + nAddButtons;
2015 if (infoPtr->nNumButtons == 0) {
2017 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2020 TBUTTON_INFO *oldButtons = infoPtr->buttons;
2022 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2023 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2024 nOldButtons * sizeof(TBUTTON_INFO));
2025 COMCTL32_Free (oldButtons);
2028 infoPtr->nNumButtons = nNewButtons;
2030 /* insert new button data */
2031 for (nCount = 0; nCount < nAddButtons; nCount++) {
2032 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
2033 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
2034 btnPtr->idCommand = lpTbb[nCount].idCommand;
2035 btnPtr->fsState = lpTbb[nCount].fsState;
2036 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
2037 btnPtr->dwData = lpTbb[nCount].dwData;
2038 btnPtr->iString = lpTbb[nCount].iString;
2039 btnPtr->bHot = FALSE;
2041 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
2044 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2045 ti.cbSize = sizeof (TTTOOLINFOA);
2047 ti.uId = btnPtr->idCommand;
2049 ti.lpszText = LPSTR_TEXTCALLBACKA;
2051 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2056 TOOLBAR_CalcToolbar (hwnd);
2058 InvalidateRect(hwnd, NULL, FALSE);
2065 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2067 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2068 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2069 INT nOldButtons, nNewButtons, nAddButtons, nCount;
2071 TRACE("adding %d buttons!\n", wParam);
2073 nAddButtons = (UINT)wParam;
2074 nOldButtons = infoPtr->nNumButtons;
2075 nNewButtons = nOldButtons + nAddButtons;
2077 if (infoPtr->nNumButtons == 0) {
2079 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2082 TBUTTON_INFO *oldButtons = infoPtr->buttons;
2084 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2085 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2086 nOldButtons * sizeof(TBUTTON_INFO));
2087 COMCTL32_Free (oldButtons);
2090 infoPtr->nNumButtons = nNewButtons;
2092 /* insert new button data */
2093 for (nCount = 0; nCount < nAddButtons; nCount++) {
2094 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
2095 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
2096 btnPtr->idCommand = lpTbb[nCount].idCommand;
2097 btnPtr->fsState = lpTbb[nCount].fsState;
2098 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
2099 btnPtr->dwData = lpTbb[nCount].dwData;
2100 btnPtr->iString = lpTbb[nCount].iString;
2101 btnPtr->bHot = FALSE;
2103 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
2106 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2107 ti.cbSize = sizeof (TTTOOLINFOW);
2109 ti.uId = btnPtr->idCommand;
2111 ti.lpszText = LPSTR_TEXTCALLBACKW;
2113 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2118 TOOLBAR_CalcToolbar (hwnd);
2120 InvalidateRect(hwnd, NULL, FALSE);
2127 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2129 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2132 if ((wParam) && (HIWORD(lParam) == 0)) {
2135 TRACE("adding string from resource!\n");
2137 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
2140 TRACE("len=%d \"%s\"\n", len, szString);
2141 nIndex = infoPtr->nNumStrings;
2142 if (infoPtr->nNumStrings == 0) {
2144 COMCTL32_Alloc (sizeof(LPWSTR));
2147 LPWSTR *oldStrings = infoPtr->strings;
2149 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2150 memcpy (&infoPtr->strings[0], &oldStrings[0],
2151 sizeof(LPWSTR) * infoPtr->nNumStrings);
2152 COMCTL32_Free (oldStrings);
2155 lenW = MultiByteToWideChar( CP_ACP, 0, szString, -1, NULL, 0 );
2156 infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
2157 MultiByteToWideChar( CP_ACP, 0, szString, -1,
2158 infoPtr->strings[infoPtr->nNumStrings], lenW );
2159 infoPtr->nNumStrings++;
2162 LPSTR p = (LPSTR)lParam;
2167 TRACE("adding string(s) from array!\n");
2169 nIndex = infoPtr->nNumStrings;
2172 TRACE("len=%d \"%s\"\n", len, p);
2174 if (infoPtr->nNumStrings == 0) {
2176 COMCTL32_Alloc (sizeof(LPWSTR));
2179 LPWSTR *oldStrings = infoPtr->strings;
2181 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2182 memcpy (&infoPtr->strings[0], &oldStrings[0],
2183 sizeof(LPWSTR) * infoPtr->nNumStrings);
2184 COMCTL32_Free (oldStrings);
2187 lenW = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
2188 infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
2189 MultiByteToWideChar( CP_ACP, 0, p, -1,
2190 infoPtr->strings[infoPtr->nNumStrings], lenW );
2191 infoPtr->nNumStrings++;
2202 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2204 #define MAX_RESOURCE_STRING_LENGTH 512
2205 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2208 if ((wParam) && (HIWORD(lParam) == 0)) {
2209 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
2211 TRACE("adding string from resource!\n");
2213 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
2214 szString, MAX_RESOURCE_STRING_LENGTH);
2216 TRACE("len=%d %s\n", len, debugstr_w(szString));
2217 TRACE("First char: 0x%x\n", *szString);
2218 if (szString[0] == L'|')
2220 PWSTR p = szString + 1;
2222 nIndex = infoPtr->nNumStrings;
2223 while (*p != L'|') {
2225 if (infoPtr->nNumStrings == 0) {
2227 COMCTL32_Alloc (sizeof(LPWSTR));
2230 LPWSTR *oldStrings = infoPtr->strings;
2232 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2233 memcpy (&infoPtr->strings[0], &oldStrings[0],
2234 sizeof(LPWSTR) * infoPtr->nNumStrings);
2235 COMCTL32_Free (oldStrings);
2238 len = COMCTL32_StrChrW (p, L'|') - p;
2239 TRACE("len=%d %s\n", len, debugstr_w(p));
2240 infoPtr->strings[infoPtr->nNumStrings] =
2241 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
2242 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
2243 infoPtr->nNumStrings++;
2250 nIndex = infoPtr->nNumStrings;
2251 if (infoPtr->nNumStrings == 0) {
2253 COMCTL32_Alloc (sizeof(LPWSTR));
2256 LPWSTR *oldStrings = infoPtr->strings;
2258 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2259 memcpy (&infoPtr->strings[0], &oldStrings[0],
2260 sizeof(LPWSTR) * infoPtr->nNumStrings);
2261 COMCTL32_Free (oldStrings);
2264 infoPtr->strings[infoPtr->nNumStrings] =
2265 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
2266 strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
2267 infoPtr->nNumStrings++;
2271 LPWSTR p = (LPWSTR)lParam;
2276 TRACE("adding string(s) from array!\n");
2277 nIndex = infoPtr->nNumStrings;
2281 TRACE("len=%d %s\n", len, debugstr_w(p));
2282 if (infoPtr->nNumStrings == 0) {
2284 COMCTL32_Alloc (sizeof(LPWSTR));
2287 LPWSTR *oldStrings = infoPtr->strings;
2289 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2290 memcpy (&infoPtr->strings[0], &oldStrings[0],
2291 sizeof(LPWSTR) * infoPtr->nNumStrings);
2292 COMCTL32_Free (oldStrings);
2295 infoPtr->strings[infoPtr->nNumStrings] =
2296 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
2297 strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
2298 infoPtr->nNumStrings++;
2309 TOOLBAR_AutoSize (HWND hwnd)
2311 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2312 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2318 UINT uPosFlags = SWP_NOZORDER;
2320 TRACE("resize forced, style=%lx!\n", dwStyle);
2322 parent = GetParent (hwnd);
2323 GetClientRect(parent, &parent_rect);
2325 x = parent_rect.left;
2326 y = parent_rect.top;
2328 /* FIXME: we should be able to early out if nothing */
2329 /* has changed with nWidth != parent_rect width */
2331 if (dwStyle & CCS_NORESIZE) {
2332 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
2337 infoPtr->nWidth = parent_rect.right - parent_rect.left;
2338 TOOLBAR_CalcToolbar (hwnd);
2339 InvalidateRect( hwnd, NULL, TRUE );
2340 cy = infoPtr->nHeight;
2341 cx = infoPtr->nWidth;
2343 if (dwStyle & CCS_NOMOVEY) {
2344 GetWindowRect(hwnd, &window_rect);
2345 ScreenToClient(parent, (LPPOINT)&window_rect.left);
2346 y = window_rect.top;
2350 if (dwStyle & CCS_NOPARENTALIGN)
2351 uPosFlags |= SWP_NOMOVE;
2353 if (!(dwStyle & CCS_NODIVIDER))
2354 cy += GetSystemMetrics(SM_CYEDGE);
2356 if (dwStyle & WS_BORDER)
2359 cy += GetSystemMetrics(SM_CYEDGE);
2360 cx += GetSystemMetrics(SM_CYEDGE);
2363 infoPtr->bAutoSize = TRUE;
2364 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
2366 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2367 * the setwindowpos calls */
2368 infoPtr->bAutoSize = FALSE;
2375 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
2377 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2379 return infoPtr->nNumButtons;
2384 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2386 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2388 if (infoPtr == NULL) {
2389 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
2390 ERR("infoPtr == NULL!\n");
2394 infoPtr->dwStructSize = (DWORD)wParam;
2401 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2403 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2404 TBUTTON_INFO *btnPtr;
2407 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2411 btnPtr = &infoPtr->buttons[nIndex];
2412 btnPtr->iBitmap = LOWORD(lParam);
2414 /* we HAVE to erase the background, the new bitmap could be */
2416 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2423 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2425 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2426 TBUTTON_INFO *btnPtr;
2429 BOOL bChecked = FALSE;
2431 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2435 btnPtr = &infoPtr->buttons[nIndex];
2437 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
2440 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
2442 if (LOWORD(lParam) == FALSE)
2443 btnPtr->fsState &= ~TBSTATE_CHECKED;
2445 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2447 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
2448 if (nOldIndex == nIndex)
2450 if (nOldIndex != -1)
2451 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2453 btnPtr->fsState |= TBSTATE_CHECKED;
2456 if( bChecked != LOWORD(lParam) )
2458 if (nOldIndex != -1)
2460 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
2461 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
2463 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2466 /* FIXME: Send a WM_NOTIFY?? */
2473 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2475 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2477 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2482 TOOLBAR_Customize (HWND hwnd)
2484 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2485 CUSTDLG_INFO custInfo;
2491 custInfo.tbInfo = infoPtr;
2492 custInfo.tbHwnd = hwnd;
2494 /* send TBN_BEGINADJUST notification */
2495 TOOLBAR_SendNotify ((NMHDR *) &nmhdr, infoPtr,
2498 if (!(hRes = FindResourceA (COMCTL32_hModule,
2499 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
2503 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
2506 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
2507 (LPDLGTEMPLATEA)template,
2509 (DLGPROC)TOOLBAR_CustomizeDialogProc,
2512 /* send TBN_ENDADJUST notification */
2513 TOOLBAR_SendNotify ((NMHDR *) &nmhdr, infoPtr,
2521 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2523 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2524 INT nIndex = (INT)wParam;
2526 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2529 if ((infoPtr->hwndToolTip) &&
2530 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2533 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2534 ti.cbSize = sizeof (TTTOOLINFOA);
2536 ti.uId = infoPtr->buttons[nIndex].idCommand;
2538 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
2541 if (infoPtr->nNumButtons == 1) {
2542 TRACE(" simple delete!\n");
2543 COMCTL32_Free (infoPtr->buttons);
2544 infoPtr->buttons = NULL;
2545 infoPtr->nNumButtons = 0;
2548 TBUTTON_INFO *oldButtons = infoPtr->buttons;
2549 TRACE("complex delete! [nIndex=%d]\n", nIndex);
2551 infoPtr->nNumButtons--;
2552 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2554 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2555 nIndex * sizeof(TBUTTON_INFO));
2558 if (nIndex < infoPtr->nNumButtons) {
2559 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
2560 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
2563 COMCTL32_Free (oldButtons);
2566 TOOLBAR_CalcToolbar (hwnd);
2568 InvalidateRect (hwnd, NULL, TRUE);
2575 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2577 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2578 TBUTTON_INFO *btnPtr;
2582 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2586 btnPtr = &infoPtr->buttons[nIndex];
2588 bState = btnPtr->fsState & TBSTATE_ENABLED;
2590 /* update the toolbar button state */
2591 if(LOWORD(lParam) == FALSE) {
2592 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
2594 btnPtr->fsState |= TBSTATE_ENABLED;
2597 /* redraw the button only if the state of the button changed */
2598 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2600 InvalidateRect(hwnd, &btnPtr->rect,
2601 TOOLBAR_HasText(infoPtr, btnPtr));
2608 static inline LRESULT
2609 TOOLBAR_GetAnchorHighlight (HWND hwnd)
2611 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2613 return infoPtr->bAnchor;
2618 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2620 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2623 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2627 return infoPtr->buttons[nIndex].iBitmap;
2631 static inline LRESULT
2632 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2634 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
2639 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2641 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2642 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2643 INT nIndex = (INT)wParam;
2644 TBUTTON_INFO *btnPtr;
2646 if (infoPtr == NULL)
2652 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2655 btnPtr = &infoPtr->buttons[nIndex];
2656 lpTbb->iBitmap = btnPtr->iBitmap;
2657 lpTbb->idCommand = btnPtr->idCommand;
2658 lpTbb->fsState = btnPtr->fsState;
2659 lpTbb->fsStyle = btnPtr->fsStyle;
2660 lpTbb->dwData = btnPtr->dwData;
2661 lpTbb->iString = btnPtr->iString;
2668 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2670 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2671 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2672 TBUTTON_INFO *btnPtr;
2675 if (infoPtr == NULL)
2677 if (lpTbInfo == NULL)
2679 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2682 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2686 btnPtr = &infoPtr->buttons[nIndex];
2688 if (lpTbInfo->dwMask & TBIF_COMMAND)
2689 lpTbInfo->idCommand = btnPtr->idCommand;
2690 if (lpTbInfo->dwMask & TBIF_IMAGE)
2691 lpTbInfo->iImage = btnPtr->iBitmap;
2692 if (lpTbInfo->dwMask & TBIF_LPARAM)
2693 lpTbInfo->lParam = btnPtr->dwData;
2694 if (lpTbInfo->dwMask & TBIF_SIZE)
2695 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2696 if (lpTbInfo->dwMask & TBIF_STATE)
2697 lpTbInfo->fsState = btnPtr->fsState;
2698 if (lpTbInfo->dwMask & TBIF_STYLE)
2699 lpTbInfo->fsStyle = btnPtr->fsStyle;
2700 if (lpTbInfo->dwMask & TBIF_TEXT) {
2701 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2703 if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[btnPtr->iString], -1,
2704 lpTbInfo->pszText, lpTbInfo->cchText, NULL, NULL ))
2705 lpTbInfo->pszText[lpTbInfo->cchText-1] = 0;
2707 else lpTbInfo->pszText[0]=0;
2714 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2716 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2717 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2718 TBUTTON_INFO *btnPtr;
2721 if (infoPtr == NULL)
2723 if (lpTbInfo == NULL)
2725 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2728 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2732 btnPtr = &infoPtr->buttons[nIndex];
2734 if (lpTbInfo->dwMask & TBIF_COMMAND)
2735 lpTbInfo->idCommand = btnPtr->idCommand;
2736 if (lpTbInfo->dwMask & TBIF_IMAGE)
2737 lpTbInfo->iImage = btnPtr->iBitmap;
2738 if (lpTbInfo->dwMask & TBIF_LPARAM)
2739 lpTbInfo->lParam = btnPtr->dwData;
2740 if (lpTbInfo->dwMask & TBIF_SIZE)
2741 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2742 if (lpTbInfo->dwMask & TBIF_STATE)
2743 lpTbInfo->fsState = btnPtr->fsState;
2744 if (lpTbInfo->dwMask & TBIF_STYLE)
2745 lpTbInfo->fsStyle = btnPtr->fsStyle;
2746 if (lpTbInfo->dwMask & TBIF_TEXT) {
2747 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2748 lstrcpynW (lpTbInfo->pszText,
2749 (LPWSTR)infoPtr->strings[btnPtr->iString],
2758 TOOLBAR_GetButtonSize (HWND hwnd)
2760 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2762 return MAKELONG((WORD)infoPtr->nButtonWidth,
2763 (WORD)infoPtr->nButtonHeight);
2768 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2770 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2771 INT nIndex, nStringIndex;
2773 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2777 nStringIndex = infoPtr->buttons[nIndex].iString;
2779 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2781 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2787 return WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[nStringIndex], -1,
2788 (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1;
2793 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2795 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2796 INT nIndex, nStringIndex;
2798 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2802 nStringIndex = infoPtr->buttons[nIndex].iString;
2804 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2806 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2812 strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2814 return strlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2818 /* << TOOLBAR_GetColorScheme >> */
2822 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2824 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2826 return (LRESULT)infoPtr->himlDis;
2830 inline static LRESULT
2831 TOOLBAR_GetExtendedStyle (HWND hwnd)
2833 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2835 return infoPtr->dwExStyle;
2840 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2842 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2844 return (LRESULT)infoPtr->himlHot;
2849 TOOLBAR_GetHotItem (HWND hwnd)
2851 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2853 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2856 if (infoPtr->nHotItem < 0)
2859 return (LRESULT)infoPtr->nHotItem;
2864 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2866 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2868 return (LRESULT)infoPtr->himlDef;
2872 /* << TOOLBAR_GetInsertMark >> */
2873 /* << TOOLBAR_GetInsertMarkColor >> */
2877 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2879 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2880 TBUTTON_INFO *btnPtr;
2884 if (infoPtr == NULL)
2886 nIndex = (INT)wParam;
2887 btnPtr = &infoPtr->buttons[nIndex];
2888 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2890 lpRect = (LPRECT)lParam;
2893 if (btnPtr->fsState & TBSTATE_HIDDEN)
2896 lpRect->left = btnPtr->rect.left;
2897 lpRect->right = btnPtr->rect.right;
2898 lpRect->bottom = btnPtr->rect.bottom;
2899 lpRect->top = btnPtr->rect.top;
2906 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2908 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2909 LPSIZE lpSize = (LPSIZE)lParam;
2914 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2915 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2917 TRACE("maximum size %d x %d\n",
2918 infoPtr->rcBound.right - infoPtr->rcBound.left,
2919 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2925 /* << TOOLBAR_GetObject >> */
2926 /* << TOOLBAR_GetPadding >> */
2930 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2932 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2933 TBUTTON_INFO *btnPtr;
2937 if (infoPtr == NULL)
2939 nIndex = (INT)wParam;
2940 btnPtr = &infoPtr->buttons[nIndex];
2941 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2943 lpRect = (LPRECT)lParam;
2947 lpRect->left = btnPtr->rect.left;
2948 lpRect->right = btnPtr->rect.right;
2949 lpRect->bottom = btnPtr->rect.bottom;
2950 lpRect->top = btnPtr->rect.top;
2957 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2959 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2961 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2962 return infoPtr->nRows;
2969 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2971 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2974 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2978 return infoPtr->buttons[nIndex].fsState;
2983 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2985 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2988 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2992 return infoPtr->buttons[nIndex].fsStyle;
2997 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2999 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3001 if (infoPtr == NULL)
3004 return infoPtr->nMaxTextRows;
3009 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3011 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3013 if (infoPtr == NULL)
3015 return infoPtr->hwndToolTip;
3020 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3022 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3024 TRACE("%s hwnd=0x%x stub!\n",
3025 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
3027 return infoPtr->bUnicode;
3031 inline static LRESULT
3032 TOOLBAR_GetVersion (HWND hwnd)
3034 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3035 return infoPtr->iVersion;
3040 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3042 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3043 TBUTTON_INFO *btnPtr;
3048 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3052 btnPtr = &infoPtr->buttons[nIndex];
3053 if (LOWORD(lParam) == FALSE)
3054 btnPtr->fsState &= ~TBSTATE_HIDDEN;
3056 btnPtr->fsState |= TBSTATE_HIDDEN;
3058 TOOLBAR_CalcToolbar (hwnd);
3060 InvalidateRect (hwnd, NULL, TRUE);
3066 inline static LRESULT
3067 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
3069 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
3074 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3076 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3077 TBUTTON_INFO *btnPtr;
3080 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3084 btnPtr = &infoPtr->buttons[nIndex];
3085 if (LOWORD(lParam) == FALSE)
3086 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
3088 btnPtr->fsState |= TBSTATE_INDETERMINATE;
3090 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3097 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3099 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3100 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
3101 INT nIndex = (INT)wParam;
3102 TBUTTON_INFO *oldButtons;
3107 TOOLBAR_DumpButton(infoPtr, (TBUTTON_INFO *)lpTbb, nIndex, FALSE);
3110 /* EPP: this seems to be an undocumented call (from my IE4)
3111 * I assume in that case that:
3112 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3113 * - index of insertion is at the end of existing buttons
3114 * I only see this happen with nIndex == -1, but it could have a special
3115 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3120 /* FIXME: iString == -1 is undocumented */
3121 if(lpTbb->iString && lpTbb->iString!=-1) {
3122 len = strlen((char*)lpTbb->iString) + 2;
3123 ptr = COMCTL32_Alloc(len);
3124 nIndex = infoPtr->nNumButtons;
3125 strcpy(ptr, (char*)lpTbb->iString);
3126 ptr[len - 1] = 0; /* ended by two '\0' */
3127 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
3131 ERR("lpTbb->iString is NULL\n");
3135 } else if (nIndex < 0)
3138 TRACE("inserting button index=%d\n", nIndex);
3139 if (nIndex > infoPtr->nNumButtons) {
3140 nIndex = infoPtr->nNumButtons;
3141 TRACE("adjust index=%d\n", nIndex);
3144 oldButtons = infoPtr->buttons;
3145 infoPtr->nNumButtons++;
3146 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
3147 /* pre insert copy */
3149 memcpy (&infoPtr->buttons[0], &oldButtons[0],
3150 nIndex * sizeof(TBUTTON_INFO));
3153 /* insert new button */
3154 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
3155 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
3156 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
3157 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
3158 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
3159 infoPtr->buttons[nIndex].iString = lpTbb->iString;
3161 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
3164 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
3165 ti.cbSize = sizeof (TTTOOLINFOA);
3167 ti.uId = lpTbb->idCommand;
3169 ti.lpszText = LPSTR_TEXTCALLBACKA;
3171 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
3175 /* post insert copy */
3176 if (nIndex < infoPtr->nNumButtons - 1) {
3177 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
3178 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
3181 COMCTL32_Free (oldButtons);
3183 TOOLBAR_CalcToolbar (hwnd);
3185 InvalidateRect (hwnd, NULL, FALSE);
3192 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3194 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3195 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
3196 INT nIndex = (INT)wParam;
3197 TBUTTON_INFO *oldButtons;
3204 TRACE("inserting button index=%d\n", nIndex);
3205 if (nIndex > infoPtr->nNumButtons) {
3206 nIndex = infoPtr->nNumButtons;
3207 TRACE("adjust index=%d\n", nIndex);
3210 oldButtons = infoPtr->buttons;
3211 infoPtr->nNumButtons++;
3212 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
3213 /* pre insert copy */
3215 memcpy (&infoPtr->buttons[0], &oldButtons[0],
3216 nIndex * sizeof(TBUTTON_INFO));
3219 /* insert new button */
3220 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
3221 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
3222 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
3223 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
3224 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
3225 infoPtr->buttons[nIndex].iString = lpTbb->iString;
3227 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
3230 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
3231 ti.cbSize = sizeof (TTTOOLINFOW);
3233 ti.uId = lpTbb->idCommand;
3235 ti.lpszText = LPSTR_TEXTCALLBACKW;
3237 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
3241 /* post insert copy */
3242 if (nIndex < infoPtr->nNumButtons - 1) {
3243 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
3244 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
3247 COMCTL32_Free (oldButtons);
3249 InvalidateRect (hwnd, NULL, FALSE);
3255 /* << TOOLBAR_InsertMarkHitTest >> */
3259 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
3261 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3264 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3268 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
3273 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
3275 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3278 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3282 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
3287 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
3289 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3292 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3296 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
3301 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
3303 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3306 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3310 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
3315 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3317 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3320 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3324 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
3329 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
3331 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3334 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3338 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
3342 /* << TOOLBAR_LoadImages >> */
3343 /* << TOOLBAR_MapAccelerator >> */
3344 /* << TOOLBAR_MarkButton >> */
3345 /* << TOOLBAR_MoveButton >> */
3349 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3351 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3352 TBUTTON_INFO *btnPtr;
3355 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3359 btnPtr = &infoPtr->buttons[nIndex];
3360 if (LOWORD(lParam) == FALSE)
3361 btnPtr->fsState &= ~TBSTATE_PRESSED;
3363 btnPtr->fsState |= TBSTATE_PRESSED;
3365 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3371 /* << TOOLBAR_ReplaceBitmap >> */
3375 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3378 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3379 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
3381 if (lpSave == NULL) return 0;
3384 /* save toolbar information */
3385 FIXME("save to \"%s\" \"%s\"\n",
3386 lpSave->pszSubKey, lpSave->pszValueName);
3391 /* restore toolbar information */
3393 FIXME("restore from \"%s\" \"%s\"\n",
3394 lpSave->pszSubKey, lpSave->pszValueName);
3405 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3408 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3409 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
3415 /* save toolbar information */
3416 FIXME("save to \"%s\" \"%s\"\n",
3417 lpSave->pszSubKey, lpSave->pszValueName);
3422 /* restore toolbar information */
3424 FIXME("restore from \"%s\" \"%s\"\n",
3425 lpSave->pszSubKey, lpSave->pszValueName);
3436 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
3438 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3439 BOOL bOldAnchor = infoPtr->bAnchor;
3441 infoPtr->bAnchor = (BOOL)wParam;
3443 return (LRESULT)bOldAnchor;
3448 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3450 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3452 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3455 if (infoPtr->nNumButtons > 0)
3456 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
3457 infoPtr->nNumButtons,
3458 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
3459 LOWORD(lParam), HIWORD(lParam));
3461 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
3462 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
3464 /* uses image list internals directly */
3465 if (infoPtr->himlDef) {
3466 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
3467 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
3475 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3477 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3478 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
3479 TBUTTON_INFO *btnPtr;
3484 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
3487 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3491 btnPtr = &infoPtr->buttons[nIndex];
3492 if (lptbbi->dwMask & TBIF_COMMAND)
3493 btnPtr->idCommand = lptbbi->idCommand;
3494 if (lptbbi->dwMask & TBIF_IMAGE)
3495 btnPtr->iBitmap = lptbbi->iImage;
3496 if (lptbbi->dwMask & TBIF_LPARAM)
3497 btnPtr->dwData = lptbbi->lParam;
3498 /* if (lptbbi->dwMask & TBIF_SIZE) */
3499 /* btnPtr->cx = lptbbi->cx; */
3500 if (lptbbi->dwMask & TBIF_STATE)
3501 btnPtr->fsState = lptbbi->fsState;
3502 if (lptbbi->dwMask & TBIF_STYLE)
3503 btnPtr->fsStyle = lptbbi->fsStyle;
3505 if (lptbbi->dwMask & TBIF_TEXT) {
3506 if ((btnPtr->iString >= 0) ||
3507 (btnPtr->iString < infoPtr->nNumStrings)) {
3508 TRACE("Ooooooch\n");
3510 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3511 INT len = lstrlenA (lptbbi->pszText);
3512 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3515 /* this is the ultimate sollution */
3516 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3525 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3527 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3528 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
3529 TBUTTON_INFO *btnPtr;
3534 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
3537 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3541 btnPtr = &infoPtr->buttons[nIndex];
3542 if (lptbbi->dwMask & TBIF_COMMAND)
3543 btnPtr->idCommand = lptbbi->idCommand;
3544 if (lptbbi->dwMask & TBIF_IMAGE)
3545 btnPtr->iBitmap = lptbbi->iImage;
3546 if (lptbbi->dwMask & TBIF_LPARAM)
3547 btnPtr->dwData = lptbbi->lParam;
3548 /* if (lptbbi->dwMask & TBIF_SIZE) */
3549 /* btnPtr->cx = lptbbi->cx; */
3550 if (lptbbi->dwMask & TBIF_STATE)
3551 btnPtr->fsState = lptbbi->fsState;
3552 if (lptbbi->dwMask & TBIF_STYLE)
3553 btnPtr->fsStyle = lptbbi->fsStyle;
3555 if (lptbbi->dwMask & TBIF_TEXT) {
3556 if ((btnPtr->iString >= 0) ||
3557 (btnPtr->iString < infoPtr->nNumStrings)) {
3559 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3560 INT len = lstrlenW (lptbbi->pszText);
3561 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3564 /* this is the ultimate solution */
3565 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3574 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3576 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3578 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3580 ERR("invalid parameter\n");
3584 /* The documentation claims you can only change the button size before
3585 * any button has been added. But this is wrong.
3586 * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding
3587 * it to the toolbar, and it checks that the return value is nonzero - mjm
3588 * Further testing shows that we must actually perform the change too.
3590 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
3591 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
3597 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
3599 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3601 if (infoPtr == NULL) {
3602 TRACE("Toolbar not initialized yet?????\n");
3606 /* if setting to current values, ignore */
3607 if ((infoPtr->cxMin == (INT)LOWORD(lParam)) &&
3608 (infoPtr->cxMax == (INT)HIWORD(lParam))) {
3609 TRACE("matches current width, min=%d, max=%d, no recalc\n",
3610 infoPtr->cxMin, infoPtr->cxMax);
3614 /* save new values */
3615 infoPtr->cxMin = (INT)LOWORD(lParam);
3616 infoPtr->cxMax = (INT)HIWORD(lParam);
3618 /* if both values are 0 then we are done */
3620 TRACE("setting both min and max to 0, norecalc\n");
3624 /* otherwise we need to recalc the toolbar and in some cases
3625 recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
3626 which doesn't actually draw - GA). */
3627 TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n",
3628 infoPtr->nNumButtons, infoPtr->cxMin, infoPtr->cxMax);
3630 TOOLBAR_CalcToolbar (hwnd);
3632 InvalidateRect (hwnd, NULL, TRUE);
3639 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
3641 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3642 INT nIndex = (INT)wParam;
3644 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3647 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
3649 if (infoPtr->hwndToolTip) {
3651 FIXME("change tool tip!\n");
3659 /* << TOOLBAR_SetColorScheme >> */
3663 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3665 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3666 HIMAGELIST himlTemp;
3669 himlTemp = infoPtr->himlDis;
3670 infoPtr->himlDis = (HIMAGELIST)lParam;
3672 /* FIXME: redraw ? */
3674 return (LRESULT)himlTemp;
3679 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
3681 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3684 dwTemp = infoPtr->dwDTFlags;
3685 infoPtr->dwDTFlags =
3686 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
3688 return (LRESULT)dwTemp;
3693 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3695 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3698 dwTemp = infoPtr->dwExStyle;
3699 infoPtr->dwExStyle = (DWORD)lParam;
3701 return (LRESULT)dwTemp;
3706 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3708 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3709 HIMAGELIST himlTemp;
3711 himlTemp = infoPtr->himlHot;
3712 infoPtr->himlHot = (HIMAGELIST)lParam;
3714 /* FIXME: redraw ? */
3716 return (LRESULT)himlTemp;
3721 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3723 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3724 INT nOldHotItem = infoPtr->nHotItem;
3725 TBUTTON_INFO *btnPtr;
3727 if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons)
3730 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3733 infoPtr->nHotItem = (INT)wParam;
3734 if ((INT)wParam >=0)
3736 btnPtr = &infoPtr->buttons[(INT)wParam];
3737 btnPtr->bHot = TRUE;
3738 InvalidateRect (hwnd, &btnPtr->rect,
3739 TOOLBAR_HasText(infoPtr, btnPtr));
3743 btnPtr = &infoPtr->buttons[nOldHotItem];
3744 btnPtr->bHot = FALSE;
3745 InvalidateRect (hwnd, &btnPtr->rect,
3746 TOOLBAR_HasText(infoPtr, btnPtr));
3750 if (nOldHotItem < 0)
3753 return (LRESULT)nOldHotItem;
3758 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3760 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3761 HIMAGELIST himlTemp;
3763 himlTemp = infoPtr->himlDef;
3764 infoPtr->himlDef = (HIMAGELIST)lParam;
3766 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3768 ImageList_GetIconSize(infoPtr->himlDef, &infoPtr->nBitmapWidth,
3769 &infoPtr->nBitmapHeight);
3770 TRACE("hwnd %08x, new himl=%08x, count=%d, bitmap w=%d, h=%d\n",
3771 hwnd, (INT)infoPtr->himlDef, infoPtr->nNumBitmaps,
3772 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
3774 /* FIXME: redraw ? */
3776 return (LRESULT)himlTemp;
3781 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3783 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3785 infoPtr->nIndent = (INT)wParam;
3789 /* process only on indent changing */
3790 if(infoPtr->nIndent != (INT)wParam)
3792 infoPtr->nIndent = (INT)wParam;
3793 TOOLBAR_CalcToolbar (hwnd);
3794 InvalidateRect(hwnd, NULL, FALSE);
3801 /* << TOOLBAR_SetInsertMark >> */
3805 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3807 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3809 infoPtr->clrInsertMark = (COLORREF)lParam;
3811 /* FIXME : redraw ??*/
3818 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3820 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3822 if (infoPtr == NULL)
3825 infoPtr->nMaxTextRows = (INT)wParam;
3831 /* << TOOLBAR_SetPadding >> */
3835 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3837 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3842 if (infoPtr == NULL)
3844 hwndOldNotify = infoPtr->hwndNotify;
3845 infoPtr->hwndNotify = (HWND)wParam;
3847 return hwndOldNotify;
3852 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3854 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3855 LPRECT lprc = (LPRECT)lParam;
3859 if (LOWORD(wParam) > 1) {
3860 FIXME("multiple rows not supported!\n");
3863 if(infoPtr->nRows != LOWORD(wParam))
3865 infoPtr->nRows = LOWORD(wParam);
3867 /* recalculate toolbar */
3868 TOOLBAR_CalcToolbar (hwnd);
3870 /* repaint toolbar */
3871 InvalidateRect(hwnd, NULL, FALSE);
3874 /* return bounding rectangle */
3876 lprc->left = infoPtr->rcBound.left;
3877 lprc->right = infoPtr->rcBound.right;
3878 lprc->top = infoPtr->rcBound.top;
3879 lprc->bottom = infoPtr->rcBound.bottom;
3887 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3889 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3890 TBUTTON_INFO *btnPtr;
3893 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3897 btnPtr = &infoPtr->buttons[nIndex];
3899 /* if hidden state has changed the invalidate entire window and recalc */
3900 if ((btnPtr->fsState & TBSTATE_HIDDEN) != (LOWORD(lParam) & TBSTATE_HIDDEN)) {
3901 btnPtr->fsState = LOWORD(lParam);
3902 TOOLBAR_CalcToolbar (hwnd);
3903 InvalidateRect(hwnd, 0, TOOLBAR_HasText(infoPtr, btnPtr));
3907 /* process state changing if current state doesn't match new state */
3908 if(btnPtr->fsState != LOWORD(lParam))
3910 btnPtr->fsState = LOWORD(lParam);
3911 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3920 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3922 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3923 TBUTTON_INFO *btnPtr;
3926 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3930 btnPtr = &infoPtr->buttons[nIndex];
3932 /* process style change if current style doesn't match new style */
3933 if(btnPtr->fsStyle != LOWORD(lParam))
3935 btnPtr->fsStyle = LOWORD(lParam);
3936 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3939 if (infoPtr->hwndToolTip) {
3940 FIXME("change tool tip!\n");
3948 inline static LRESULT
3949 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3951 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3953 if (infoPtr == NULL)
3955 infoPtr->hwndToolTip = (HWND)wParam;
3961 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3963 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3966 TRACE("%s hwnd=0x%04x stub!\n",
3967 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3969 bTemp = infoPtr->bUnicode;
3970 infoPtr->bUnicode = (BOOL)wParam;
3977 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3979 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3980 INT iOldVersion = infoPtr->iVersion;
3982 infoPtr->iVersion = iVersion;
3989 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3991 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3992 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3995 /* initialize info structure */
3996 infoPtr->nButtonHeight = 22;
3997 infoPtr->nButtonWidth = 24;
3998 infoPtr->nBitmapHeight = 15;
3999 infoPtr->nBitmapWidth = 16;
4001 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
4003 infoPtr->nMaxTextRows = 1;
4004 infoPtr->cxMin = -1;
4005 infoPtr->cxMax = -1;
4006 infoPtr->nNumBitmaps = 0;
4007 infoPtr->nNumStrings = 0;
4009 infoPtr->bCaptured = FALSE;
4010 infoPtr->bUnicode = IsWindowUnicode (hwnd);
4011 infoPtr->nButtonDown = -1;
4012 infoPtr->nOldHit = -1;
4013 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
4014 infoPtr->hwndNotify = GetParent (hwnd);
4015 infoPtr->bTransparent = (dwStyle & (TBSTYLE_FLAT | TBSTYLE_TRANSPARENT));
4016 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
4017 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
4018 infoPtr->iVersion = 0;
4019 infoPtr->bNtfUnicode = FALSE;
4020 infoPtr->hwndSelf = hwnd;
4022 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
4023 infoPtr->hFont = CreateFontIndirectA (&logFont);
4025 if (dwStyle & TBSTYLE_TOOLTIPS) {
4026 /* Create tooltip control */
4027 infoPtr->hwndToolTip =
4028 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
4029 CW_USEDEFAULT, CW_USEDEFAULT,
4030 CW_USEDEFAULT, CW_USEDEFAULT,
4033 /* Send NM_TOOLTIPSCREATED notification */
4034 if (infoPtr->hwndToolTip) {
4035 NMTOOLTIPSCREATED nmttc;
4037 nmttc.hwndToolTips = infoPtr->hwndToolTip;
4039 TOOLBAR_SendNotify ((NMHDR *) &nmttc, infoPtr,
4040 NM_TOOLTIPSCREATED);
4044 TOOLBAR_CheckStyle (hwnd, dwStyle);
4046 TOOLBAR_CalcToolbar(hwnd);
4053 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
4055 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4057 /* delete tooltip control */
4058 if (infoPtr->hwndToolTip)
4059 DestroyWindow (infoPtr->hwndToolTip);
4061 /* delete button data */
4062 if (infoPtr->buttons)
4063 COMCTL32_Free (infoPtr->buttons);
4065 /* delete strings */
4066 if (infoPtr->strings) {
4068 for (i = 0; i < infoPtr->nNumStrings; i++)
4069 if (infoPtr->strings[i])
4070 COMCTL32_Free (infoPtr->strings[i]);
4072 COMCTL32_Free (infoPtr->strings);
4075 /* destroy internal image list */
4076 if (infoPtr->himlInt)
4077 ImageList_Destroy (infoPtr->himlInt);
4079 /* delete default font */
4081 DeleteObject (infoPtr->hFont);
4083 /* free toolbar info data */
4084 COMCTL32_Free (infoPtr);
4085 SetWindowLongA (hwnd, 0, 0);
4092 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
4094 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4095 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4096 NMTBCUSTOMDRAW tbcd;
4099 if (dwStyle & TBSTYLE_CUSTOMERASE) {
4100 ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
4101 tbcd.nmcd.dwDrawStage = CDDS_PREERASE;
4102 tbcd.nmcd.hdc = (HDC)wParam;
4103 ret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
4104 /* FIXME: in general the return flags *can* be or'ed together */
4107 case CDRF_DODEFAULT:
4109 case CDRF_SKIPDEFAULT:
4112 FIXME("[%04x] response %d not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4117 /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up
4118 * to my parent for processing.
4120 if (infoPtr->bTransparent) {
4122 HDC hdc = (HDC)wParam;
4127 parent = GetParent(hwnd);
4128 MapWindowPoints(hwnd, parent, &pt, 1);
4129 OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
4130 SendMessageA (parent, WM_ERASEBKGND, wParam, lParam);
4131 SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
4135 if (dwStyle & TBSTYLE_CUSTOMERASE) {
4136 ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
4137 tbcd.nmcd.dwDrawStage = CDDS_POSTERASE;
4138 tbcd.nmcd.hdc = (HDC)wParam;
4139 ret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
4142 case CDRF_DODEFAULT:
4144 case CDRF_SKIPDEFAULT:
4147 FIXME("[%04x] response %d not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4151 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
4156 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
4158 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4160 return infoPtr->hFont;
4165 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
4167 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4168 TBUTTON_INFO *btnPtr;
4172 pt.x = (INT)LOWORD(lParam);
4173 pt.y = (INT)HIWORD(lParam);
4174 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4177 btnPtr = &infoPtr->buttons[nHit];
4178 if (!(btnPtr->fsState & TBSTATE_ENABLED))
4181 infoPtr->bCaptured = TRUE;
4182 infoPtr->nButtonDown = nHit;
4184 btnPtr->fsState |= TBSTATE_PRESSED;
4186 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4189 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
4190 TOOLBAR_Customize (hwnd);
4197 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
4199 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4200 TBUTTON_INFO *btnPtr;
4205 if (infoPtr->hwndToolTip)
4206 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4207 WM_LBUTTONDOWN, wParam, lParam);
4209 pt.x = (INT)LOWORD(lParam);
4210 pt.y = (INT)HIWORD(lParam);
4211 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4215 btnPtr = &infoPtr->buttons[nHit];
4216 if (!(btnPtr->fsState & TBSTATE_ENABLED))
4219 infoPtr->nOldHit = nHit;
4221 CopyRect(&arrowRect, &btnPtr->rect);
4222 arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
4224 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
4225 if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
4226 ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
4227 (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))
4231 * this time we must force a Redraw, so the btn is
4232 * painted down before CaptureChanged repaints it up
4234 RedrawWindow(hwnd,&btnPtr->rect,0,
4235 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
4237 nmtb.iItem = btnPtr->idCommand;
4238 memset(&nmtb.tbButton, 0, sizeof(TBBUTTON));
4241 memset(&nmtb.rcButton, 0, sizeof(RECT));
4242 res = TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4244 if (res != TBDDRET_TREATPRESSED)
4245 /* ??? guess (GA) */
4247 /* otherwise drop through and process as pushed */
4249 /* SetCapture (hwnd); */
4250 infoPtr->bCaptured = TRUE;
4251 infoPtr->nButtonDown = nHit;
4253 btnPtr->fsState |= TBSTATE_PRESSED;
4254 btnPtr->bHot = FALSE;
4256 InvalidateRect(hwnd, &btnPtr->rect,
4257 TOOLBAR_HasText(infoPtr, btnPtr));
4261 /* native issues the TBN_BEGINDRAG here */
4262 nmtb.iItem = btnPtr->idCommand;
4263 nmtb.tbButton.iBitmap = btnPtr->iBitmap;
4264 nmtb.tbButton.idCommand = btnPtr->idCommand;
4265 nmtb.tbButton.fsState = btnPtr->fsState;
4266 nmtb.tbButton.fsStyle = btnPtr->fsStyle;
4267 nmtb.tbButton.dwData = btnPtr->dwData;
4268 nmtb.tbButton.iString = btnPtr->iString;
4269 nmtb.cchText = 0; /* !!! not correct */
4270 nmtb.pszText = 0; /* !!! not correct */
4271 TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4279 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
4281 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4282 TBUTTON_INFO *btnPtr;
4286 BOOL bSendMessage = TRUE;
4291 if (infoPtr->hwndToolTip)
4292 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4293 WM_LBUTTONUP, wParam, lParam);
4295 pt.x = (INT)LOWORD(lParam);
4296 pt.y = (INT)HIWORD(lParam);
4297 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4299 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
4300 /* if the cursor is still inside of the toolbar */
4301 if((infoPtr->nHotItem >= 0) && (nHit != -1))
4302 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
4304 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
4305 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4306 btnPtr->fsState &= ~TBSTATE_PRESSED;
4308 if (nHit == infoPtr->nButtonDown) {
4309 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
4310 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
4311 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
4312 infoPtr->nButtonDown);
4313 if (nOldIndex == infoPtr->nButtonDown)
4314 bSendMessage = FALSE;
4315 if ((nOldIndex != infoPtr->nButtonDown) &&
4317 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
4318 btnPtr->fsState |= TBSTATE_CHECKED;
4321 if (btnPtr->fsState & TBSTATE_CHECKED)
4322 btnPtr->fsState &= ~TBSTATE_CHECKED;
4324 btnPtr->fsState |= TBSTATE_CHECKED;
4329 bSendMessage = FALSE;
4331 if (nOldIndex != -1)
4333 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
4334 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
4338 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
4339 * that resets bCaptured and btn TBSTATE_PRESSED flags,
4340 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
4344 /* Issue NM_RELEASEDCAPTURE to parent to let him know it is released */
4345 TOOLBAR_SendNotify ((NMHDR *) &hdr, infoPtr,
4346 NM_RELEASEDCAPTURE);
4348 /* native issues TBN_ENDDRAG here, if _LBUTTONDOWN issued the
4351 nmtb.iItem = btnPtr->idCommand;
4352 nmtb.tbButton.iBitmap = btnPtr->iBitmap;
4353 nmtb.tbButton.idCommand = btnPtr->idCommand;
4354 nmtb.tbButton.fsState = btnPtr->fsState;
4355 nmtb.tbButton.fsStyle = btnPtr->fsStyle;
4356 nmtb.tbButton.dwData = btnPtr->dwData;
4357 nmtb.tbButton.iString = btnPtr->iString;
4358 nmtb.cchText = 0; /* !!! not correct */
4359 nmtb.pszText = 0; /* !!! not correct */
4360 TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4364 SendMessageA (GetParent(hwnd), WM_COMMAND,
4365 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
4367 /* !!! Undocumented - toolbar at 4.71 level and above sends
4368 * either NMRCLICK or NM_CLICK with the NMMOUSE structure.
4369 * Only NM_RCLICK is documented.
4371 nmmouse.dwItemSpec = btnPtr->idCommand;
4372 nmmouse.dwItemData = btnPtr->dwData;
4373 TOOLBAR_SendNotify ((NMHDR *) &nmmouse, infoPtr,
4381 TOOLBAR_CaptureChanged(HWND hwnd)
4383 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4384 TBUTTON_INFO *btnPtr;
4386 infoPtr->bCaptured = FALSE;
4388 if (infoPtr->nButtonDown >= 0)
4390 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4391 btnPtr->fsState &= ~TBSTATE_PRESSED;
4393 infoPtr->nButtonDown = -1;
4394 infoPtr->nOldHit = -1;
4396 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4403 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
4405 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4406 TBUTTON_INFO *hotBtnPtr, *btnPtr;
4409 if (infoPtr->nOldHit < 0)
4412 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
4414 /* Redraw the button if the last button we were over is the hot button and it
4416 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
4418 hotBtnPtr->bHot = FALSE;
4419 rc1 = hotBtnPtr->rect;
4420 InflateRect (&rc1, 1, 1);
4421 InvalidateRect (hwnd, &rc1, TOOLBAR_HasText(infoPtr,
4425 /* If the last button we were over is depressed then make it not */
4426 /* depressed and redraw it */
4427 if(infoPtr->nOldHit == infoPtr->nButtonDown)
4429 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4431 btnPtr->fsState &= ~TBSTATE_PRESSED;
4433 rc1 = hotBtnPtr->rect;
4434 InflateRect (&rc1, 1, 1);
4435 InvalidateRect (hwnd, &rc1, TRUE);
4438 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
4439 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
4445 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
4447 TBUTTON_INFO *btnPtr, *oldBtnPtr;
4448 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4451 TRACKMOUSEEVENT trackinfo;
4453 /* fill in the TRACKMOUSEEVENT struct */
4454 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
4455 trackinfo.dwFlags = TME_QUERY;
4456 trackinfo.hwndTrack = hwnd;
4457 trackinfo.dwHoverTime = HOVER_DEFAULT;
4459 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
4460 _TrackMouseEvent(&trackinfo);
4462 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
4463 if(!(trackinfo.dwFlags & TME_LEAVE)) {
4464 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
4466 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
4467 /* and can properly deactivate the hot toolbar button */
4468 _TrackMouseEvent(&trackinfo);
4471 if (infoPtr->hwndToolTip)
4472 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4473 WM_MOUSEMOVE, wParam, lParam);
4475 pt.x = (INT)LOWORD(lParam);
4476 pt.y = (INT)HIWORD(lParam);
4478 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4480 if (infoPtr->nOldHit != nHit)
4482 /* Remove the effect of an old hot button if the button was enabled and was
4483 drawn with the hot button effect */
4484 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
4485 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
4487 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
4488 oldBtnPtr->bHot = FALSE;
4490 InvalidateRect (hwnd, &oldBtnPtr->rect,
4491 TOOLBAR_HasText(infoPtr, oldBtnPtr));
4494 /* It's not a separator or in nowhere. It's a hot button. */
4497 btnPtr = &infoPtr->buttons[nHit];
4499 infoPtr->nHotItem = nHit;
4501 /* only enabled buttons show hot effect */
4502 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
4504 btnPtr->bHot = TRUE;
4505 InvalidateRect(hwnd, &btnPtr->rect,
4506 TOOLBAR_HasText(infoPtr, btnPtr));
4511 if (infoPtr->bCaptured) {
4512 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4513 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
4514 btnPtr->fsState &= ~TBSTATE_PRESSED;
4515 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4517 else if (nHit == infoPtr->nButtonDown) {
4518 btnPtr->fsState |= TBSTATE_PRESSED;
4519 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4522 infoPtr->nOldHit = nHit;
4528 inline static LRESULT
4529 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4531 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
4532 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
4534 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
4538 inline static LRESULT
4539 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
4541 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
4542 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
4544 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
4549 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4551 TOOLBAR_INFO *infoPtr;
4553 /* allocate memory for info structure */
4554 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
4555 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
4558 infoPtr->dwStructSize = sizeof(TBBUTTON);
4560 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
4561 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
4562 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
4563 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
4566 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
4571 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
4573 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4577 if (dwStyle & WS_MINIMIZE)
4578 return 0; /* Nothing to do */
4580 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
4582 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
4585 if (!(dwStyle & CCS_NODIVIDER))
4587 GetWindowRect (hwnd, &rcWindow);
4588 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4589 if( dwStyle & WS_BORDER )
4590 OffsetRect (&rcWindow, 1, 1);
4591 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
4594 ReleaseDC( hwnd, hdc );
4600 inline static LRESULT
4601 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
4603 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4604 LPNMHDR lpnmh = (LPNMHDR)lParam;
4606 if (lpnmh->code == PGN_CALCSIZE) {
4607 LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam;
4609 if (lppgc->dwFlag == PGF_CALCWIDTH) {
4610 lppgc->iWidth = infoPtr->nWidth;
4611 TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
4615 lppgc->iHeight = infoPtr->nHeight;
4616 TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
4623 TRACE("passing WM_NOTIFY!\n");
4625 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
4626 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
4629 if (lpnmh->code == TTN_GETDISPINFOA) {
4630 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
4632 FIXME("retrieving ASCII string\n");
4635 else if (lpnmh->code == TTN_GETDISPINFOW) {
4636 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
4638 FIXME("retrieving UNICODE string\n");
4649 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
4651 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4655 /* fill ps.rcPaint with a default rect */
4656 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
4658 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
4660 TRACE("psrect=(%d,%d)-(%d,%d)\n",
4661 ps.rcPaint.left, ps.rcPaint.top,
4662 ps.rcPaint.right, ps.rcPaint.bottom);
4664 TOOLBAR_Refresh (hwnd, hdc, &ps);
4665 if (!wParam) EndPaint (hwnd, &ps);
4672 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
4674 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4675 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4684 /* Resize deadlock check */
4685 if (infoPtr->bAutoSize) {
4686 infoPtr->bAutoSize = FALSE;
4690 /* FIXME: optimize to only update size if the new size doesn't */
4691 /* match the current size */
4693 flags = (INT) wParam;
4695 /* FIXME for flags =
4696 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
4699 TRACE("sizing toolbar!\n");
4701 if (flags == SIZE_RESTORED) {
4702 /* width and height don't apply */
4703 parent = GetParent (hwnd);
4704 GetClientRect(parent, &parent_rect);
4705 x = parent_rect.left;
4706 y = parent_rect.top;
4708 if (dwStyle & CCS_NORESIZE) {
4709 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
4712 * this sets the working width of the toolbar, and
4713 * Calc Toolbar will not adjust it, only the height
4715 infoPtr->nWidth = parent_rect.right - parent_rect.left;
4716 cy = infoPtr->nHeight;
4717 cx = infoPtr->nWidth;
4718 TOOLBAR_CalcToolbar (hwnd);
4719 infoPtr->nWidth = cx;
4720 infoPtr->nHeight = cy;
4723 infoPtr->nWidth = parent_rect.right - parent_rect.left;
4724 TOOLBAR_CalcToolbar (hwnd);
4725 cy = infoPtr->nHeight;
4726 cx = infoPtr->nWidth;
4728 if (dwStyle & CCS_NOMOVEY) {
4729 GetWindowRect(hwnd, &window_rect);
4730 ScreenToClient(parent, (LPPOINT)&window_rect.left);
4731 y = window_rect.top;
4735 if (dwStyle & CCS_NOPARENTALIGN) {
4736 uPosFlags |= SWP_NOMOVE;
4737 cy = infoPtr->nHeight;
4738 cx = infoPtr->nWidth;
4741 if (!(dwStyle & CCS_NODIVIDER))
4742 cy += GetSystemMetrics(SM_CYEDGE);
4744 if (dwStyle & WS_BORDER)
4747 cy += GetSystemMetrics(SM_CYEDGE);
4748 cx += GetSystemMetrics(SM_CYEDGE);
4751 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
4752 cx, cy, uPosFlags | SWP_NOZORDER);
4759 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
4761 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4763 if (nType == GWL_STYLE) {
4764 if (lpStyle->styleNew & TBSTYLE_LIST) {
4765 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
4768 infoPtr->dwDTFlags = DT_CENTER;
4770 TOOLBAR_CheckStyle (hwnd, lpStyle->styleNew);
4773 TOOLBAR_AutoSize (hwnd);
4775 InvalidateRect(hwnd, NULL, FALSE);
4782 static LRESULT WINAPI
4783 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4785 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n",
4786 hwnd, uMsg, /* SPY_GetMsgName(uMsg), */ wParam, lParam);
4788 if (!TOOLBAR_GetInfoPtr(hwnd) && (uMsg != WM_NCCREATE))
4789 return DefWindowProcA( hwnd, uMsg, wParam, lParam );
4794 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
4796 case TB_ADDBUTTONSA:
4797 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
4799 case TB_ADDBUTTONSW:
4800 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
4803 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
4806 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
4809 return TOOLBAR_AutoSize (hwnd);
4811 case TB_BUTTONCOUNT:
4812 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
4814 case TB_BUTTONSTRUCTSIZE:
4815 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
4817 case TB_CHANGEBITMAP:
4818 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
4820 case TB_CHECKBUTTON:
4821 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
4823 case TB_COMMANDTOINDEX:
4824 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
4827 return TOOLBAR_Customize (hwnd);
4829 case TB_DELETEBUTTON:
4830 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
4832 case TB_ENABLEBUTTON:
4833 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
4835 case TB_GETANCHORHIGHLIGHT:
4836 return TOOLBAR_GetAnchorHighlight (hwnd);
4839 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
4841 case TB_GETBITMAPFLAGS:
4842 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
4845 return TOOLBAR_GetButton (hwnd, wParam, lParam);
4847 case TB_GETBUTTONINFOA:
4848 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
4850 case TB_GETBUTTONINFOW:
4851 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
4853 case TB_GETBUTTONSIZE:
4854 return TOOLBAR_GetButtonSize (hwnd);
4856 case TB_GETBUTTONTEXTA:
4857 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
4859 case TB_GETBUTTONTEXTW:
4860 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
4862 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
4864 case TB_GETDISABLEDIMAGELIST:
4865 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
4867 case TB_GETEXTENDEDSTYLE:
4868 return TOOLBAR_GetExtendedStyle (hwnd);
4870 case TB_GETHOTIMAGELIST:
4871 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
4874 return TOOLBAR_GetHotItem (hwnd);
4876 case TB_GETIMAGELIST:
4877 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
4879 /* case TB_GETINSERTMARK: */ /* 4.71 */
4880 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
4882 case TB_GETITEMRECT:
4883 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
4886 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
4888 /* case TB_GETOBJECT: */ /* 4.71 */
4889 /* case TB_GETPADDING: */ /* 4.71 */
4892 return TOOLBAR_GetRect (hwnd, wParam, lParam);
4895 return TOOLBAR_GetRows (hwnd, wParam, lParam);
4898 return TOOLBAR_GetState (hwnd, wParam, lParam);
4901 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
4903 case TB_GETTEXTROWS:
4904 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
4906 case TB_GETTOOLTIPS:
4907 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
4909 case TB_GETUNICODEFORMAT:
4910 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
4912 case CCM_GETVERSION:
4913 return TOOLBAR_GetVersion (hwnd);
4916 return TOOLBAR_HideButton (hwnd, wParam, lParam);
4919 return TOOLBAR_HitTest (hwnd, wParam, lParam);
4921 case TB_INDETERMINATE:
4922 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
4924 case TB_INSERTBUTTONA:
4925 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
4927 case TB_INSERTBUTTONW:
4928 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
4930 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
4932 case TB_ISBUTTONCHECKED:
4933 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
4935 case TB_ISBUTTONENABLED:
4936 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
4938 case TB_ISBUTTONHIDDEN:
4939 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
4941 case TB_ISBUTTONHIGHLIGHTED:
4942 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
4944 case TB_ISBUTTONINDETERMINATE:
4945 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
4947 case TB_ISBUTTONPRESSED:
4948 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
4950 case TB_LOADIMAGES: /* 4.70 */
4951 FIXME("missing standard imagelists\n");
4954 /* case TB_MAPACCELERATORA: */ /* 4.71 */
4955 /* case TB_MAPACCELERATORW: */ /* 4.71 */
4956 /* case TB_MARKBUTTON: */ /* 4.71 */
4957 /* case TB_MOVEBUTTON: */ /* 4.71 */
4959 case TB_PRESSBUTTON:
4960 return TOOLBAR_PressButton (hwnd, wParam, lParam);
4962 /* case TB_REPLACEBITMAP: */
4964 case TB_SAVERESTOREA:
4965 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
4967 case TB_SAVERESTOREW:
4968 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
4970 case TB_SETANCHORHIGHLIGHT:
4971 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
4973 case TB_SETBITMAPSIZE:
4974 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
4976 case TB_SETBUTTONINFOA:
4977 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
4979 case TB_SETBUTTONINFOW:
4980 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
4982 case TB_SETBUTTONSIZE:
4983 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
4985 case TB_SETBUTTONWIDTH:
4986 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
4989 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
4991 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
4993 case TB_SETDISABLEDIMAGELIST:
4994 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
4996 case TB_SETDRAWTEXTFLAGS:
4997 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
4999 case TB_SETEXTENDEDSTYLE:
5000 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
5002 case TB_SETHOTIMAGELIST:
5003 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
5006 return TOOLBAR_SetHotItem (hwnd, wParam);
5008 case TB_SETIMAGELIST:
5009 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
5012 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
5014 /* case TB_SETINSERTMARK: */ /* 4.71 */
5016 case TB_SETINSERTMARKCOLOR:
5017 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
5019 case TB_SETMAXTEXTROWS:
5020 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
5022 /* case TB_SETPADDING: */ /* 4.71 */
5025 return TOOLBAR_SetParent (hwnd, wParam, lParam);
5028 return TOOLBAR_SetRows (hwnd, wParam, lParam);
5031 return TOOLBAR_SetState (hwnd, wParam, lParam);
5034 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
5036 case TB_SETTOOLTIPS:
5037 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
5039 case TB_SETUNICODEFORMAT:
5040 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
5042 case CCM_SETVERSION:
5043 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
5049 return TOOLBAR_Create (hwnd, wParam, lParam);
5052 return TOOLBAR_Destroy (hwnd, wParam, lParam);
5055 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
5058 return TOOLBAR_GetFont (hwnd, wParam, lParam);
5060 /* case WM_KEYDOWN: */
5061 /* case WM_KILLFOCUS: */
5063 case WM_LBUTTONDBLCLK:
5064 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
5066 case WM_LBUTTONDOWN:
5067 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
5070 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
5073 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
5076 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
5078 case WM_CAPTURECHANGED:
5079 return TOOLBAR_CaptureChanged(hwnd);
5082 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
5085 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
5088 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
5091 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
5094 return TOOLBAR_Notify (hwnd, wParam, lParam);
5096 /* case WM_NOTIFYFORMAT: */
5099 return TOOLBAR_Paint (hwnd, wParam);
5102 return TOOLBAR_Size (hwnd, wParam, lParam);
5104 case WM_STYLECHANGED:
5105 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
5107 /* case WM_SYSCOLORCHANGE: */
5109 /* case WM_WININICHANGE: */
5114 case WM_MEASUREITEM:
5116 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
5119 if (uMsg >= WM_USER)
5120 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
5121 uMsg, wParam, lParam);
5122 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
5129 TOOLBAR_Register (void)
5133 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
5134 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
5135 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
5136 wndClass.cbClsExtra = 0;
5137 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
5138 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
5139 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
5140 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
5142 RegisterClassA (&wndClass);
5147 TOOLBAR_Unregister (void)
5149 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);