4 * Copyright 1998,1999 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Differences between MSDN and actual native control operation:
22 * 1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
23 * to the right of the bitmap. Otherwise, this style is
24 * identical to TBSTYLE_FLAT."
25 * As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
26 * you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
27 * is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
28 * *not* imply TBSTYLE_FLAT as documented. (GA 8/2001)
32 * - Button wrapping (under construction).
40 * - TBN_DELETINGBUTTON
47 * - Tooltip support (almost complete).
48 * - Fix TOOLBAR_SetButtonInfo32A/W.
49 * - iString of -1 is undocumented
50 * - Customization dialog:
52 * - Minor buglet in 'available buttons' list:
53 * Buttons are not listed in M$-like order. M$ seems to use a single
54 * internal list to store the button information of both listboxes.
55 * - Drag list support.
58 * - Run tests using Waite Group Windows95 API Bible Volume 2.
59 * The second cdrom contains executables addstr.exe, btncount.exe,
60 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
61 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
62 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
63 * setparnt.exe, setrows.exe, toolwnd.exe.
64 * - Microsofts controlspy examples.
65 * - Charles Petzold's 'Programming Windows': gadgets.exe
75 #include "wine/unicode.h"
78 #include "imagelist.h"
80 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(toolbar
);
109 } IMLENTRY
, *PIMLENTRY
;
113 DWORD dwStructSize
; /* size of TBBUTTON struct */
114 INT nHeight
; /* height of the toolbar */
115 INT nWidth
; /* width of the toolbar */
121 INT nRows
; /* number of button rows */
122 INT nMaxTextRows
; /* maximum number of text rows */
123 INT cxMin
; /* minimum button width */
124 INT cxMax
; /* maximum button width */
125 INT nNumButtons
; /* number of buttons */
126 INT nNumBitmaps
; /* number of bitmaps */
127 INT nNumStrings
; /* number of strings */
129 BOOL bUnicode
; /* ASCII (FALSE) or Unicode (TRUE)? */
130 BOOL bCaptured
; /* mouse captured? */
133 INT nHotItem
; /* index of the "hot" item */
134 DWORD dwBaseCustDraw
; /* CDRF_ response (w/o TBCDRF_) from PREPAINT */
135 DWORD dwItemCustDraw
; /* CDRF_ response (w/o TBCDRF_) from ITEMPREP */
136 DWORD dwItemCDFlag
; /* TBCDRF_ flags from last ITEMPREPAINT */
137 SIZE szPadding
; /* padding values around button */
139 HFONT hFont
; /* text font */
140 HIMAGELIST himlInt
; /* image list created internally */
141 PIMLENTRY
*himlDef
; /* default image list array */
142 INT cimlDef
; /* default image list array count */
143 PIMLENTRY
*himlHot
; /* hot image list array */
144 INT cimlHot
; /* hot image list array count */
145 PIMLENTRY
*himlDis
; /* disabled image list array */
146 INT cimlDis
; /* disabled image list array count */
147 HWND hwndToolTip
; /* handle to tool tip control */
148 HWND hwndNotify
; /* handle to the window that gets notifications */
149 HWND hwndSelf
; /* my own handle */
150 BOOL bTransparent
; /* background transparency flag */
151 BOOL bBtnTranspnt
; /* button transparency flag */
152 BOOL bAutoSize
; /* auto size deadlock indicator */
153 BOOL bAnchor
; /* anchor highlight enabled */
154 BOOL bNtfUnicode
; /* TRUE if NOTIFYs use {W} */
155 BOOL bDoRedraw
; /* Redraw status */
156 DWORD dwExStyle
; /* extended toolbar style */
157 DWORD dwDTFlags
; /* DrawText flags */
159 COLORREF clrInsertMark
; /* insert mark color */
160 COLORREF clrBtnHighlight
; /* color for Flat Separator */
161 COLORREF clrBtnShadow
; /* color for Flag Separator */
162 RECT rcBound
; /* bounding rectangle */
165 TBUTTON_INFO
*buttons
; /* pointer to button array */
166 LPWSTR
*strings
; /* pointer to string array */
167 TBITMAP_INFO
*bitmaps
;
168 } TOOLBAR_INFO
, *PTOOLBAR_INFO
;
171 /* used by customization dialog */
174 PTOOLBAR_INFO tbInfo
;
176 } CUSTDLG_INFO
, *PCUSTDLG_INFO
;
184 } CUSTOMBUTTON
, *PCUSTOMBUTTON
;
193 #define SEPARATOR_WIDTH 8
195 #define BOTTOM_BORDER 2
196 #define DDARROW_WIDTH 11
197 #define ARROW_HEIGHT 3
199 /* gap between edge of button and image with TBSTYLE_LIST */
200 #define LIST_IMAGE_OFFSET 3
201 /* gap between bitmap and text (always present) */
202 #define LIST_TEXT_OFFSET 2
203 /* how wide to treat the bitmap if it isn't present */
204 #define LIST_IMAGE_ABSENT_WIDTH 2
206 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
207 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
208 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
210 /* Used to find undocumented extended styles */
211 #define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \
212 TBSTYLE_EX_UNDOC1 | \
213 TBSTYLE_EX_MIXEDBUTTONS | \
214 TBSTYLE_EX_HIDECLIPPEDBUTTONS)
216 #define GETIBITMAP(infoPtr, i) (infoPtr->iVersion >= 5 ? LOWORD(i) : i)
217 #define GETHIMLID(infoPtr, i) (infoPtr->iVersion >= 5 ? HIWORD(i) : 0)
218 #define GETDEFIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDef, infoPtr->cimlDef, id)
219 #define GETHOTIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlHot, infoPtr->cimlHot, id)
220 #define GETDISIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDis, infoPtr->cimlDis, id)
222 static BOOL
TOOLBAR_GetButtonInfo(TOOLBAR_INFO
*infoPtr
, NMTOOLBARW
*nmtb
);
223 static BOOL
TOOLBAR_IsButtonRemovable(TOOLBAR_INFO
*infoPtr
, int iItem
, PCUSTOMBUTTON btnInfo
);
224 static HIMAGELIST
TOOLBAR_GetImageList(PIMLENTRY
*pies
, INT cies
, INT id
);
225 static PIMLENTRY
TOOLBAR_GetImageListEntry(PIMLENTRY
*pies
, INT cies
, INT id
);
226 static VOID
TOOLBAR_DeleteImageList(PIMLENTRY
**pies
, INT
*cies
);
227 static HIMAGELIST
TOOLBAR_InsertImageList(PIMLENTRY
**pies
, INT
*cies
, HIMAGELIST himl
, INT id
);
230 TOOLBAR_NotifyFormat(TOOLBAR_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
);
234 TOOLBAR_GetText(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
)
236 LPWSTR lpText
= NULL
;
238 /* FIXME: iString == -1 is undocumented */
239 if ((HIWORD(btnPtr
->iString
) != 0) && (btnPtr
->iString
!= -1))
240 lpText
= (LPWSTR
)btnPtr
->iString
;
241 else if ((btnPtr
->iString
>= 0) && (btnPtr
->iString
< infoPtr
->nNumStrings
))
242 lpText
= infoPtr
->strings
[btnPtr
->iString
];
248 TOOLBAR_DumpButton(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*bP
, INT btn_num
, BOOL internal
)
250 if (TRACE_ON(toolbar
)){
251 TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08x\n",
252 btn_num
, bP
->idCommand
, GETIBITMAP(infoPtr
, bP
->iBitmap
),
253 bP
->fsState
, bP
->fsStyle
, bP
->dwData
, bP
->iString
);
254 TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr
,bP
)));
256 TRACE("button %d id %d, hot=%s, row=%d, rect=(%ld,%ld)-(%ld,%ld)\n",
257 btn_num
, bP
->idCommand
,
258 (bP
->bHot
) ? "TRUE":"FALSE", bP
->nRow
,
259 bP
->rect
.left
, bP
->rect
.top
,
260 bP
->rect
.right
, bP
->rect
.bottom
);
266 TOOLBAR_DumpToolbar(TOOLBAR_INFO
*iP
, INT line
)
268 if (TRACE_ON(toolbar
)) {
272 dwStyle
= GetWindowLongA (iP
->hwndSelf
, GWL_STYLE
);
273 TRACE("toolbar %p at line %d, exStyle=%08lx, buttons=%d, bitmaps=%d, strings=%d, style=%08lx\n",
275 iP
->dwExStyle
, iP
->nNumButtons
, iP
->nNumBitmaps
,
276 iP
->nNumStrings
, dwStyle
);
277 TRACE("toolbar %p at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p, redrawable=%s\n",
279 iP
->himlInt
, iP
->himlDef
, iP
->himlHot
, iP
->himlDis
,
280 (iP
->bDoRedraw
) ? "TRUE" : "FALSE");
281 for(i
=0; i
<iP
->nNumButtons
; i
++) {
282 TOOLBAR_DumpButton(iP
, &iP
->buttons
[i
], i
, TRUE
);
288 /***********************************************************************
291 * This function validates that the styles set are implemented and
292 * issues FIXME's warning of possible problems. In a perfect world this
293 * function should be null.
296 TOOLBAR_CheckStyle (HWND hwnd
, DWORD dwStyle
)
298 if (dwStyle
& TBSTYLE_ALTDRAG
)
299 FIXME("[%p] TBSTYLE_ALTDRAG not implemented\n", hwnd
);
300 if (dwStyle
& TBSTYLE_REGISTERDROP
)
301 FIXME("[%p] TBSTYLE_REGISTERDROP not implemented\n", hwnd
);
306 TOOLBAR_SendNotify (NMHDR
*nmhdr
, TOOLBAR_INFO
*infoPtr
, UINT code
)
308 if(!IsWindow(infoPtr
->hwndSelf
))
309 return 0; /* we have just been destroyed */
311 nmhdr
->idFrom
= GetDlgCtrlID (infoPtr
->hwndSelf
);
312 nmhdr
->hwndFrom
= infoPtr
->hwndSelf
;
315 TRACE("to window %p, code=%08x, %s\n", infoPtr
->hwndNotify
, code
,
316 (infoPtr
->bNtfUnicode
) ? "via Unicode" : "via ANSI");
318 if (infoPtr
->bNtfUnicode
)
319 return SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
320 (WPARAM
) nmhdr
->idFrom
, (LPARAM
)nmhdr
);
322 return SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
323 (WPARAM
) nmhdr
->idFrom
, (LPARAM
)nmhdr
);
326 /***********************************************************************
327 * TOOLBAR_GetBitmapIndex
329 * This function returns the bitmap index associated with a button.
330 * If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO
331 * is issued to retrieve the index.
334 TOOLBAR_GetBitmapIndex(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
)
336 INT ret
= btnPtr
->iBitmap
;
338 if (ret
== I_IMAGECALLBACK
) {
339 /* issue TBN_GETDISPINFO */
342 nmgd
.idCommand
= btnPtr
->idCommand
;
343 nmgd
.lParam
= btnPtr
->dwData
;
344 nmgd
.dwMask
= TBNF_IMAGE
;
345 TOOLBAR_SendNotify ((NMHDR
*) &nmgd
, infoPtr
,
346 (infoPtr
->bNtfUnicode
) ? TBN_GETDISPINFOW
:
348 if (nmgd
.dwMask
& TBNF_DI_SETITEM
) {
349 btnPtr
->iBitmap
= nmgd
.iImage
;
352 TRACE("TBN_GETDISPINFOA returned bitmap id %d, mask=%08lx, nNumBitmaps=%d\n",
353 ret
, nmgd
.dwMask
, infoPtr
->nNumBitmaps
);
356 if (ret
!= I_IMAGENONE
)
357 ret
= GETIBITMAP(infoPtr
, ret
);
364 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO
*infoPtr
, INT index
)
367 INT id
= GETHIMLID(infoPtr
, index
);
368 INT iBitmap
= GETIBITMAP(infoPtr
, index
);
370 if (((himl
= GETDEFIMAGELIST(infoPtr
, id
)) &&
371 iBitmap
>= 0 && iBitmap
< ImageList_GetImageCount(himl
)) ||
372 (index
== I_IMAGECALLBACK
))
379 /***********************************************************************
380 * TOOLBAR_DrawImageList
382 * This function validates the bitmap index (including I_IMAGECALLBACK
383 * functionality). It then draws the image via the ImageList_Draw
384 * function. It returns TRUE if the image was drawn, FALSE otherwise.
387 TOOLBAR_DrawImageList (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
, IMAGE_LIST_TYPE imagelist
,
388 HDC hdc
, UINT left
, UINT top
, UINT draw_flags
)
393 if (!TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
394 if (btnPtr
->iBitmap
== I_IMAGENONE
) return FALSE
;
395 ERR("index %d is not valid, max %d\n",
396 btnPtr
->iBitmap
, infoPtr
->nNumBitmaps
);
400 if ((index
= TOOLBAR_GetBitmapIndex(infoPtr
, btnPtr
)) < 0) {
401 if ((index
== I_IMAGECALLBACK
) ||
402 (index
== I_IMAGENONE
)) return FALSE
;
403 ERR("TBN_GETDISPINFO returned invalid index %d\n",
410 case IMAGE_LIST_DEFAULT
:
411 himl
= GETDEFIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
414 himl
= GETHOTIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
416 case IMAGE_LIST_DISABLED
:
417 himl
= GETDISIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
421 FIXME("Shouldn't reach here\n");
426 TRACE("no image list, returning FALSE\n");
430 TRACE("drawing index=%d, himl=%p, left=%d, top=%d, flags=%08x\n",
431 index
, himl
, left
, top
, draw_flags
);
433 ImageList_Draw (himl
, index
, hdc
, left
, top
, draw_flags
);
438 /***********************************************************************
439 * TOOLBAR_TestImageExist
441 * This function is similar to TOOLBAR_DrawImageList, except it does not
442 * draw the image. The I_IMAGECALLBACK functionality is implemented.
445 TOOLBAR_TestImageExist (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
, HIMAGELIST himl
)
449 if (!himl
) return FALSE
;
451 if (!TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
452 if (btnPtr
->iBitmap
== I_IMAGENONE
) return FALSE
;
453 ERR("index %d is not valid, max %d\n",
454 btnPtr
->iBitmap
, infoPtr
->nNumBitmaps
);
458 if ((index
= TOOLBAR_GetBitmapIndex(infoPtr
, btnPtr
)) < 0) {
459 if ((index
== I_IMAGECALLBACK
) ||
460 (index
== I_IMAGENONE
)) return FALSE
;
461 ERR("TBN_GETDISPINFO returned invalid index %d\n",
470 TOOLBAR_DrawFlatSeparator (LPRECT lpRect
, HDC hdc
, TOOLBAR_INFO
*infoPtr
)
473 COLORREF oldcolor
, newcolor
;
475 myrect
.left
= (lpRect
->left
+ lpRect
->right
) / 2 - 1;
476 myrect
.right
= myrect
.left
+ 1;
477 myrect
.top
= lpRect
->top
+ 2;
478 myrect
.bottom
= lpRect
->bottom
- 2;
480 newcolor
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
481 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
482 oldcolor
= SetBkColor (hdc
, newcolor
);
483 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
485 myrect
.left
= myrect
.right
;
486 myrect
.right
= myrect
.left
+ 1;
488 newcolor
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
489 comctl32_color
.clrBtnHighlight
: infoPtr
->clrBtnHighlight
;
490 SetBkColor (hdc
, newcolor
);
491 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
493 SetBkColor (hdc
, oldcolor
);
497 /***********************************************************************
498 * TOOLBAR_DrawDDFlatSeparator
500 * This function draws the separator that was flaged as TBSTYLE_DROPDOWN.
501 * In this case, the separator is a pixel high line of COLOR_BTNSHADOW,
502 * followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators
503 * are horizontal as opposed to the vertical separators for not dropdown
506 * FIXME: It is possible that the height of each line is really SM_CYBORDER.
509 TOOLBAR_DrawDDFlatSeparator (LPRECT lpRect
, HDC hdc
, TBUTTON_INFO
*btnPtr
, TOOLBAR_INFO
*infoPtr
)
512 COLORREF oldcolor
, newcolor
;
514 myrect
.left
= lpRect
->left
;
515 myrect
.right
= lpRect
->right
;
516 myrect
.top
= lpRect
->top
+ (lpRect
->bottom
- lpRect
->top
- 2)/2;
517 myrect
.bottom
= myrect
.top
+ 1;
519 InflateRect (&myrect
, -2, 0);
521 TRACE("rect=(%ld,%ld)-(%ld,%ld)\n",
522 myrect
.left
, myrect
.top
, myrect
.right
, myrect
.bottom
);
524 newcolor
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
525 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
526 oldcolor
= SetBkColor (hdc
, newcolor
);
527 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
529 myrect
.top
= myrect
.bottom
;
530 myrect
.bottom
= myrect
.top
+ 1;
532 newcolor
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
533 comctl32_color
.clrBtnHighlight
: infoPtr
->clrBtnHighlight
;
534 SetBkColor (hdc
, newcolor
);
535 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
537 SetBkColor (hdc
, oldcolor
);
542 TOOLBAR_DrawArrow (HDC hdc
, INT left
, INT top
, INT colorRef
)
547 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
548 hOldPen
= SelectObject ( hdc
, hPen
);
551 MoveToEx (hdc
, x
, y
, NULL
);
552 LineTo (hdc
, x
+5, y
++); x
++;
553 MoveToEx (hdc
, x
, y
, NULL
);
554 LineTo (hdc
, x
+3, y
++); x
++;
555 MoveToEx (hdc
, x
, y
, NULL
);
556 LineTo (hdc
, x
+1, y
++);
557 SelectObject( hdc
, hOldPen
);
558 DeleteObject( hPen
);
562 * Draw the text string for this button.
563 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
564 * is non-zero, so we can simply check himlDef to see if we have
568 TOOLBAR_DrawString (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
569 HDC hdc
, DWORD dwStyle
,
570 RECT
*rcText
, LPWSTR lpText
, NMTBCUSTOMDRAW
*tbcd
)
574 UINT state
= tbcd
->nmcd
.uItemState
;
578 TRACE("string=%s rect=(%ld,%ld)-(%ld,%ld)\n", debugstr_w(lpText
),
579 rcText
->left
, rcText
->top
, rcText
->right
, rcText
->bottom
);
581 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
582 if ((state
& CDIS_HOT
) && (infoPtr
->dwItemCDFlag
& TBCDRF_HILITEHOTTRACK
)) {
583 clrOld
= SetTextColor (hdc
, tbcd
->clrTextHighlight
);
585 else if (state
& CDIS_DISABLED
) {
586 clrOld
= SetTextColor (hdc
, tbcd
->clrBtnHighlight
);
587 OffsetRect (rcText
, 1, 1);
588 DrawTextW (hdc
, lpText
, -1, rcText
, infoPtr
->dwDTFlags
);
589 SetTextColor (hdc
, comctl32_color
.clr3dShadow
);
590 OffsetRect (rcText
, -1, -1);
592 else if (state
& CDIS_INDETERMINATE
) {
593 clrOld
= SetTextColor (hdc
, comctl32_color
.clr3dShadow
);
596 clrOld
= SetTextColor (hdc
, tbcd
->clrText
);
599 DrawTextW (hdc
, lpText
, -1, rcText
, infoPtr
->dwDTFlags
);
600 SetTextColor (hdc
, clrOld
);
601 SelectObject (hdc
, hOldFont
);
607 TOOLBAR_DrawPattern (HDC hdc
, LPRECT lpRect
)
609 HBRUSH hbr
= SelectObject (hdc
, COMCTL32_hPattern55AABrush
);
610 INT cx
= lpRect
->right
- lpRect
->left
;
611 INT cy
= lpRect
->bottom
- lpRect
->top
;
612 PatBlt (hdc
, lpRect
->left
, lpRect
->top
, cx
, cy
, 0x00FA0089);
613 SelectObject (hdc
, hbr
);
618 TOOLBAR_DrawMasked (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
619 HDC hdc
, INT x
, INT y
)
621 HIMAGELIST himl
= GETDEFIMAGELIST(infoPtr
, 0);
629 ImageList_GetIconSize(himl
, &cx
, &cy
);
631 /* create new dc's */
632 hdcMask
= CreateCompatibleDC (0);
634 /* create new bitmap */
635 hbmMask
= CreateBitmap (cx
, cy
, 1, 1, NULL
);
636 SelectObject (hdcMask
, hbmMask
);
638 /* copy the mask bitmap */
639 ImageList_DrawEx(himl
, btnPtr
->iBitmap
, hdcMask
, 0, 0, 0, 0, RGB(255, 255, 255), RGB(0, 0, 0), ILD_MASK
);
641 /* draw the new mask */
642 SelectObject (hdc
, GetSysColorBrush (COLOR_3DHILIGHT
));
643 BitBlt (hdc
, x
+1, y
+1, cx
, cy
, hdcMask
, 0, 0, 0xB8074A);
645 SelectObject (hdc
, GetSysColorBrush (COLOR_3DSHADOW
));
646 BitBlt (hdc
, x
, y
, cx
, cy
, hdcMask
, 0, 0, 0xB8074A);
648 DeleteObject (hbmMask
);
654 TOOLBAR_TranslateState(TBUTTON_INFO
*btnPtr
)
658 retstate
|= (btnPtr
->fsState
& TBSTATE_CHECKED
) ? CDIS_CHECKED
: 0;
659 retstate
|= (btnPtr
->fsState
& TBSTATE_PRESSED
) ? CDIS_SELECTED
: 0;
660 retstate
|= (btnPtr
->fsState
& TBSTATE_ENABLED
) ? 0 : CDIS_DISABLED
;
661 retstate
|= (btnPtr
->fsState
& TBSTATE_MARKED
) ? CDIS_MARKED
: 0;
662 retstate
|= (btnPtr
->bHot
) ? CDIS_HOT
: 0;
663 retstate
|= (btnPtr
->fsState
& TBSTATE_INDETERMINATE
) ? CDIS_INDETERMINATE
: 0;
664 /* FIXME: don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT */
665 /* don't test TBSTATE_HIDDEN */
671 TOOLBAR_DrawButton (HWND hwnd
, TBUTTON_INFO
*btnPtr
, HDC hdc
)
673 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
674 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
675 BOOL hasDropDownArrow
= TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
) &&
676 (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
);
677 RECT rc
, rcArrow
, rcBitmap
, rcText
, rcFill
;
678 LPWSTR lpText
= NULL
;
683 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
687 CopyRect (&rcFill
, &rc
);
688 CopyRect (&rcArrow
, &rc
);
689 CopyRect(&rcBitmap
, &rc
);
691 /* get a pointer to the text */
692 lpText
= TOOLBAR_GetText(infoPtr
, btnPtr
);
694 if (hasDropDownArrow
)
696 if (dwStyle
& TBSTYLE_FLAT
)
697 rc
.right
= max(rc
.left
, rc
.right
- DDARROW_WIDTH
);
699 rc
.right
= max(rc
.left
, rc
.right
- DDARROW_WIDTH
- 2);
700 rcArrow
.left
= rc
.right
;
703 /* copy text rect after adjusting for drop-down arrow
704 * so that text is centred in the rectangle not containing
706 CopyRect(&rcText
, &rc
);
708 /* Center the bitmap horizontally and vertically */
709 if (dwStyle
& TBSTYLE_LIST
)
710 rcBitmap
.left
+= LIST_IMAGE_OFFSET
;
712 rcBitmap
.left
+=(infoPtr
->nButtonWidth
- infoPtr
->nBitmapWidth
) / 2;
715 rcBitmap
.top
+=2; /* this looks to be the correct value from vmware comparison - cmm */
717 rcBitmap
.top
+=(infoPtr
->nButtonHeight
- infoPtr
->nBitmapHeight
) / 2;
719 TRACE("iBitmap: %d, start=(%ld,%ld) w=%d, h=%d\n",
720 btnPtr
->iBitmap
, rcBitmap
.left
, rcBitmap
.top
,
721 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
722 TRACE ("iString: %x\n", btnPtr
->iString
);
723 TRACE ("Stringtext: %s\n", debugstr_w(lpText
));
728 InflateRect (&rcText
, -3, -3);
730 if (GETDEFIMAGELIST(infoPtr
, 0) &&
731 TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
732 /* The following test looked like this before
733 * I changed it. IE4 "Links" toolbar would not
734 * draw correctly with the original code. - GA 8/01
735 * ((dwStyle & TBSTYLE_LIST) &&
736 * ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
737 * (btnPtr->iBitmap != I_IMAGENONE))
739 if (dwStyle
& TBSTYLE_LIST
) {
740 /* LIST style w/ ICON offset is by matching native. */
741 /* Matches IE4 "Links" bar. - GA 8/01 */
742 rcText
.left
+= (infoPtr
->nBitmapWidth
+ LIST_TEXT_OFFSET
);
745 rcText
.top
+= infoPtr
->nBitmapHeight
+ 1;
749 if (dwStyle
& TBSTYLE_LIST
) {
750 /* LIST style w/o ICON offset is by matching native. */
751 /* Matches IE4 "menu" bar. - GA 8/01 */
752 rcText
.left
+= LIST_IMAGE_ABSENT_WIDTH
+ LIST_TEXT_OFFSET
;
756 if (btnPtr
->fsState
& (TBSTATE_PRESSED
| TBSTATE_CHECKED
))
757 OffsetRect (&rcText
, 1, 1);
760 /* Initialize fields in all cases, because we use these later */
761 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
762 tbcd
.clrText
= comctl32_color
.clrBtnText
;
763 tbcd
.clrTextHighlight
= comctl32_color
.clrHighlightText
;
764 tbcd
.clrBtnFace
= comctl32_color
.clrBtnFace
;
765 tbcd
.clrBtnHighlight
= comctl32_color
.clrBtnHighlight
;
766 tbcd
.clrMark
= comctl32_color
.clrHighlight
;
767 tbcd
.clrHighlightHotTrack
= 0;
768 tbcd
.nStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
769 tbcd
.nHLStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
770 /* MSDN says that this is the text rectangle. */
771 /* But (why always a but) tracing of v5.7 of native shows */
772 /* that this is really a *relative* rectangle based on the */
773 /* the nmcd.rc. Also the left and top are always 0 ignoring*/
774 /* any bitmap that might be present. */
775 tbcd
.rcText
.left
= 0;
777 tbcd
.rcText
.right
= rcText
.right
- rc
.left
;
778 tbcd
.rcText
.bottom
= rcText
.bottom
- rc
.top
;
779 /* we use this state later on to decide how to draw the buttons */
780 /* NOTE: applications can and do alter this to customize their */
782 tbcd
.nmcd
.uItemState
= TOOLBAR_TranslateState(btnPtr
);
784 /* FIXME: what should these be set to ????? */
785 tbcd
.hbrMonoDither
= 0;
789 /* Issue Item Prepaint notify */
790 infoPtr
->dwItemCustDraw
= 0;
791 infoPtr
->dwItemCDFlag
= 0;
792 if (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYITEMDRAW
)
794 tbcd
.nmcd
.dwDrawStage
= CDDS_ITEMPREPAINT
;
797 tbcd
.nmcd
.dwItemSpec
= btnPtr
->idCommand
;
798 tbcd
.nmcd
.lItemlParam
= btnPtr
->dwData
;
799 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
800 infoPtr
->dwItemCustDraw
= ntfret
& 0xffff;
801 infoPtr
->dwItemCDFlag
= ntfret
& 0xffff0000;
802 if (infoPtr
->dwItemCustDraw
& CDRF_SKIPDEFAULT
)
804 /* save the only part of the rect that the user can change */
805 rcText
.right
= tbcd
.rcText
.right
+ rc
.left
;
806 rcText
.bottom
= tbcd
.rcText
.bottom
+ rc
.top
;
809 if (!infoPtr
->bBtnTranspnt
)
810 FillRect( hdc
, &rcFill
, GetSysColorBrush(COLOR_BTNFACE
));
813 if (btnPtr
->fsStyle
& TBSTYLE_SEP
) {
814 /* with the FLAT style, iBitmap is the width and has already */
815 /* been taken into consideration in calculating the width */
816 /* so now we need to draw the vertical separator */
817 /* empirical tests show that iBitmap can/will be non-zero */
818 /* when drawing the vertical bar... */
819 if ((dwStyle
& TBSTYLE_FLAT
) /* && (btnPtr->iBitmap == 0) */) {
820 if (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
)
821 TOOLBAR_DrawDDFlatSeparator (&rc
, hdc
, btnPtr
, infoPtr
);
823 TOOLBAR_DrawFlatSeparator (&rc
, hdc
, infoPtr
);
825 else if (btnPtr
->fsStyle
!= TBSTYLE_SEP
) {
826 FIXME("Draw some kind of separator: fsStyle=%x\n",
832 if ((dwStyle
& TBSTYLE_FLAT
) && (tbcd
.nmcd
.uItemState
& CDIS_HOT
))
834 if ( infoPtr
->dwItemCDFlag
& TBCDRF_HILITEHOTTRACK
)
838 oldclr
= SetBkColor(hdc
, tbcd
.clrHighlightHotTrack
);
839 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, 0);
840 if (hasDropDownArrow
)
841 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rcArrow
, NULL
, 0, 0);
842 SetBkColor(hdc
, oldclr
);
846 if (!(tbcd
.nmcd
.uItemState
& CDIS_DISABLED
) && !(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
848 DrawEdge (hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
849 if (hasDropDownArrow
)
850 DrawEdge (hdc
, &rcArrow
, BDR_RAISEDINNER
, BF_RECT
);
856 if (tbcd
.nmcd
.uItemState
& CDIS_DISABLED
) {
857 if (!(dwStyle
& TBSTYLE_FLAT
) && !(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
859 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
860 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
861 if (hasDropDownArrow
)
862 DrawEdge (hdc
, &rcArrow
, EDGE_RAISED
,
863 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
866 if (hasDropDownArrow
)
868 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
+1, rcArrow
.top
+1 + (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_3DHIGHLIGHT
);
869 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_3DSHADOW
);
872 if (!TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DISABLED
,
873 hdc
, rcBitmap
.left
, rcBitmap
.top
,
875 TOOLBAR_DrawMasked (infoPtr
, btnPtr
, hdc
, rcBitmap
.left
, rcBitmap
.top
);
877 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
878 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
882 /* pressed TBSTYLE_BUTTON */
883 if (tbcd
.nmcd
.uItemState
& CDIS_SELECTED
) {
884 offset
= (infoPtr
->dwItemCDFlag
& TBCDRF_NOOFFSET
) ? 0 : 1;
885 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
887 if (dwStyle
& TBSTYLE_FLAT
)
889 DrawEdge (hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
890 if (hasDropDownArrow
)
891 DrawEdge (hdc
, &rcArrow
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
895 DrawEdge (hdc
, &rc
, EDGE_SUNKEN
, BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
896 if (hasDropDownArrow
)
897 DrawEdge (hdc
, &rcArrow
, EDGE_SUNKEN
, BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
901 if (hasDropDownArrow
)
902 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
+ offset
, rcArrow
.top
+ offset
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_WINDOWFRAME
);
904 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
905 hdc
, rcBitmap
.left
+offset
, rcBitmap
.top
+offset
,
908 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
909 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
913 /* checked TBSTYLE_CHECK */
914 if ((tbcd
.nmcd
.uItemState
& CDIS_CHECKED
) &&
915 (btnPtr
->fsStyle
& TBSTYLE_CHECK
)) {
916 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
918 if (dwStyle
& TBSTYLE_FLAT
)
919 DrawEdge (hdc
, &rc
, BDR_SUNKENOUTER
,
920 BF_RECT
| BF_ADJUST
);
922 DrawEdge (hdc
, &rc
, EDGE_SUNKEN
,
923 BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
926 TOOLBAR_DrawPattern (hdc
, &rc
);
928 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
929 hdc
, rcBitmap
.left
+1, rcBitmap
.top
+1,
932 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
933 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
938 if (tbcd
.nmcd
.uItemState
& CDIS_INDETERMINATE
) {
939 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
940 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
941 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
943 TOOLBAR_DrawPattern (hdc
, &rc
);
944 TOOLBAR_DrawMasked (infoPtr
, btnPtr
, hdc
, rcBitmap
.left
, rcBitmap
.top
);
945 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
946 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
951 if (dwStyle
& TBSTYLE_FLAT
)
953 if (hasDropDownArrow
)
954 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_WINDOWFRAME
);
956 if (tbcd
.nmcd
.uItemState
& CDIS_HOT
) {
957 /* if hot, attempt to draw with hot image list, if fails,
958 use default image list */
959 if (!TOOLBAR_DrawImageList (infoPtr
, btnPtr
,
962 rcBitmap
.top
, ILD_NORMAL
))
963 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
964 hdc
, rcBitmap
.left
, rcBitmap
.top
,
968 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
969 hdc
, rcBitmap
.left
, rcBitmap
.top
,
974 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
975 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
976 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
978 if (hasDropDownArrow
)
980 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
981 DrawEdge (hdc
, &rcArrow
, EDGE_RAISED
,
982 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
983 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_WINDOWFRAME
);
986 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
987 hdc
, rcBitmap
.left
, rcBitmap
.top
,
992 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
993 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
996 if (infoPtr
->dwItemCustDraw
& CDRF_NOTIFYPOSTPAINT
)
998 tbcd
.nmcd
.dwDrawStage
= CDDS_ITEMPOSTPAINT
;
1001 tbcd
.nmcd
.dwItemSpec
= btnPtr
->idCommand
;
1002 tbcd
.nmcd
.uItemState
= TOOLBAR_TranslateState(btnPtr
);
1003 tbcd
.nmcd
.lItemlParam
= btnPtr
->dwData
;
1004 tbcd
.rcText
= rcText
;
1005 tbcd
.nStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
1006 tbcd
.nHLStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
1007 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1014 TOOLBAR_Refresh (HWND hwnd
, HDC hdc
, PAINTSTRUCT
* ps
)
1016 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1017 TBUTTON_INFO
*btnPtr
;
1018 INT i
, oldBKmode
= 0;
1019 RECT rcTemp
, rcClient
;
1020 NMTBCUSTOMDRAW tbcd
;
1023 /* if imagelist belongs to the app, it can be changed
1024 by the app after setting it */
1025 if (GETDEFIMAGELIST(infoPtr
, 0) != infoPtr
->himlInt
)
1027 infoPtr
->nNumBitmaps
= 0;
1028 for (i
= 0; i
< infoPtr
->cimlDef
; i
++)
1029 infoPtr
->nNumBitmaps
+= ImageList_GetImageCount(infoPtr
->himlDef
[i
]->himl
);
1032 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
1034 /* Send initial notify */
1035 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
1036 tbcd
.nmcd
.dwDrawStage
= CDDS_PREPAINT
;
1037 tbcd
.nmcd
.hdc
= hdc
;
1038 tbcd
.nmcd
.rc
= ps
->rcPaint
;
1039 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1040 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
1042 if (infoPtr
->bBtnTranspnt
)
1043 oldBKmode
= SetBkMode (hdc
, TRANSPARENT
);
1045 GetClientRect(hwnd
, &rcClient
);
1047 /* redraw necessary buttons */
1048 btnPtr
= infoPtr
->buttons
;
1049 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++)
1052 if (infoPtr
->dwExStyle
& TBSTYLE_EX_HIDECLIPPEDBUTTONS
)
1054 IntersectRect(&rcTemp
, &rcClient
, &btnPtr
->rect
);
1055 bDraw
= EqualRect(&rcTemp
, &btnPtr
->rect
);
1059 bDraw
&= IntersectRect(&rcTemp
, &(ps
->rcPaint
), &(btnPtr
->rect
));
1061 TOOLBAR_DrawButton (hwnd
, btnPtr
, hdc
);
1064 if (infoPtr
->bBtnTranspnt
&& (oldBKmode
!= TRANSPARENT
))
1065 SetBkMode (hdc
, oldBKmode
);
1067 if (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYPOSTPAINT
)
1069 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
1070 tbcd
.nmcd
.dwDrawStage
= CDDS_POSTPAINT
;
1071 tbcd
.nmcd
.hdc
= hdc
;
1072 tbcd
.nmcd
.rc
= ps
->rcPaint
;
1073 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1077 /***********************************************************************
1078 * TOOLBAR_MeasureString
1080 * This function gets the width and height of a string in pixels. This
1081 * is done first by using GetTextExtentPoint to get the basic width
1082 * and height. The DrawText is called with DT_CALCRECT to get the exact
1083 * width. The reason is because the text may have more than one "&" (or
1084 * prefix characters as M$ likes to call them). The prefix character
1085 * indicates where the underline goes, except for the string "&&" which
1086 * is reduced to a single "&". GetTextExtentPoint does not process these
1087 * only DrawText does. Note that the TBSTYLE_NOPREFIX is handled here.
1090 TOOLBAR_MeasureString(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
1091 HDC hdc
, LPSIZE lpSize
)
1098 if (!(btnPtr
->fsState
& TBSTATE_HIDDEN
) &&
1099 (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) ||
1100 (btnPtr
->fsStyle
& BTNS_SHOWTEXT
)) )
1102 LPWSTR lpText
= TOOLBAR_GetText(infoPtr
, btnPtr
);
1104 if(lpText
!= NULL
) {
1105 /* first get size of all the text */
1106 GetTextExtentPoint32W (hdc
, lpText
, strlenW (lpText
), lpSize
);
1108 /* feed above size into the rectangle for DrawText */
1109 myrect
.left
= myrect
.top
= 0;
1110 myrect
.right
= lpSize
->cx
;
1111 myrect
.bottom
= lpSize
->cy
;
1113 /* Use DrawText to get true size as drawn (less pesky "&") */
1114 DrawTextW (hdc
, lpText
, -1, &myrect
, DT_VCENTER
| DT_SINGLELINE
|
1115 DT_CALCRECT
| ((btnPtr
->fsStyle
& TBSTYLE_NOPREFIX
) ?
1118 /* feed back to caller */
1119 lpSize
->cx
= myrect
.right
;
1120 lpSize
->cy
= myrect
.bottom
;
1124 TRACE("string size %ld x %ld!\n", lpSize
->cx
, lpSize
->cy
);
1127 /***********************************************************************
1128 * TOOLBAR_CalcStrings
1130 * This function walks through each string and measures it and returns
1131 * the largest height and width to caller.
1134 TOOLBAR_CalcStrings (HWND hwnd
, LPSIZE lpSize
)
1136 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1137 TBUTTON_INFO
*btnPtr
;
1147 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
1149 btnPtr
= infoPtr
->buttons
;
1150 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1151 if(TOOLBAR_HasText(infoPtr
, btnPtr
))
1153 TOOLBAR_MeasureString(infoPtr
, btnPtr
, hdc
, &sz
);
1154 if (sz
.cx
> lpSize
->cx
)
1156 if (sz
.cy
> lpSize
->cy
)
1161 SelectObject (hdc
, hOldFont
);
1162 ReleaseDC (hwnd
, hdc
);
1164 TRACE("max string size %ld x %ld!\n", lpSize
->cx
, lpSize
->cy
);
1167 /***********************************************************************
1168 * TOOLBAR_WrapToolbar
1170 * This function walks through the buttons and separators in the
1171 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
1172 * wrapping should occur based on the width of the toolbar window.
1173 * It does *not* calculate button placement itself. That task
1174 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
1175 * the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE
1176 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
1178 * Note: TBSTYLE_WRAPABLE or TBSTYLE_EX_UNDOC1 can be used also to allow
1179 * vertical toolbar lists.
1183 TOOLBAR_WrapToolbar( HWND hwnd
, DWORD dwStyle
)
1185 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1186 TBUTTON_INFO
*btnPtr
;
1189 BOOL bWrap
, bButtonWrap
;
1191 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
1192 /* no layout is necessary. Applications may use this style */
1193 /* to perform their own layout on the toolbar. */
1194 if( !(dwStyle
& TBSTYLE_WRAPABLE
) &&
1195 !(infoPtr
->dwExStyle
& TBSTYLE_EX_UNDOC1
) ) return;
1197 btnPtr
= infoPtr
->buttons
;
1198 x
= infoPtr
->nIndent
;
1200 /* this can get the parents width, to know how far we can extend
1201 * this toolbar. We cannot use its height, as there may be multiple
1202 * toolbars in a rebar control
1204 GetClientRect( GetParent(hwnd
), &rc
);
1205 infoPtr
->nWidth
= rc
.right
- rc
.left
;
1206 bButtonWrap
= FALSE
;
1208 TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
1209 infoPtr
->nButtonWidth
, infoPtr
->nBitmapWidth
, infoPtr
->nWidth
,
1212 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++ )
1215 btnPtr
[i
].fsState
&= ~TBSTATE_WRAP
;
1217 if (btnPtr
[i
].fsState
& TBSTATE_HIDDEN
)
1220 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1221 /* it is the actual width of the separator. This is used for */
1222 /* custom controls in toolbars. */
1224 /* TBSTYLE_DROPDOWN separators are treated as buttons for */
1225 /* width. - GA 8/01 */
1226 if ((btnPtr
[i
].fsStyle
& TBSTYLE_SEP
) &&
1227 !(btnPtr
[i
].fsStyle
& TBSTYLE_DROPDOWN
))
1228 cx
= (btnPtr
[i
].iBitmap
> 0) ?
1229 btnPtr
[i
].iBitmap
: SEPARATOR_WIDTH
;
1231 cx
= infoPtr
->nButtonWidth
;
1233 /* Two or more adjacent separators form a separator group. */
1234 /* The first separator in a group should be wrapped to the */
1235 /* next row if the previous wrapping is on a button. */
1237 (btnPtr
[i
].fsStyle
& TBSTYLE_SEP
) &&
1238 (i
+ 1 < infoPtr
->nNumButtons
) &&
1239 (btnPtr
[i
+ 1].fsStyle
& TBSTYLE_SEP
) )
1241 TRACE("wrap point 1 btn %d style %02x\n", i
, btnPtr
[i
].fsStyle
);
1242 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1243 x
= infoPtr
->nIndent
;
1245 bButtonWrap
= FALSE
;
1249 /* The layout makes sure the bitmap is visible, but not the button. */
1250 /* Test added to also wrap after a button that starts a row but */
1251 /* is bigger than the area. - GA 8/01 */
1252 if (( x
+ cx
- (infoPtr
->nButtonWidth
- infoPtr
->nBitmapWidth
) / 2
1253 > infoPtr
->nWidth
) ||
1254 ((x
== infoPtr
->nIndent
) && (cx
> infoPtr
->nWidth
)))
1256 BOOL bFound
= FALSE
;
1258 /* If the current button is a separator and not hidden, */
1259 /* go to the next until it reaches a non separator. */
1260 /* Wrap the last separator if it is before a button. */
1261 while( ( ((btnPtr
[i
].fsStyle
& TBSTYLE_SEP
) &&
1262 !(btnPtr
[i
].fsStyle
& TBSTYLE_DROPDOWN
)) ||
1263 (btnPtr
[i
].fsState
& TBSTATE_HIDDEN
) ) &&
1264 i
< infoPtr
->nNumButtons
)
1270 if( bFound
&& i
< infoPtr
->nNumButtons
)
1273 TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
1274 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1275 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1276 x
= infoPtr
->nIndent
;
1277 bButtonWrap
= FALSE
;
1280 else if ( i
>= infoPtr
->nNumButtons
)
1283 /* If the current button is not a separator, find the last */
1284 /* separator and wrap it. */
1285 for ( j
= i
- 1; j
>= 0 && !(btnPtr
[j
].fsState
& TBSTATE_WRAP
); j
--)
1287 if ((btnPtr
[j
].fsStyle
& TBSTYLE_SEP
) &&
1288 !(btnPtr
[j
].fsState
& TBSTATE_HIDDEN
))
1292 TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
1293 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1294 x
= infoPtr
->nIndent
;
1295 btnPtr
[j
].fsState
|= TBSTATE_WRAP
;
1296 bButtonWrap
= FALSE
;
1301 /* If no separator available for wrapping, wrap one of */
1302 /* non-hidden previous button. */
1306 j
>= 0 && !(btnPtr
[j
].fsState
& TBSTATE_WRAP
); j
--)
1308 if (btnPtr
[j
].fsState
& TBSTATE_HIDDEN
)
1313 TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
1314 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1315 x
= infoPtr
->nIndent
;
1316 btnPtr
[j
].fsState
|= TBSTATE_WRAP
;
1322 /* If all above failed, wrap the current button. */
1325 TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
1326 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1327 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1329 x
= infoPtr
->nIndent
;
1330 if (btnPtr
[i
].fsStyle
& TBSTYLE_SEP
)
1331 bButtonWrap
= FALSE
;
1337 TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
1338 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1345 /***********************************************************************
1346 * TOOLBAR_CalcToolbar
1348 * This function calculates button and separator placement. It first
1349 * calculates the button sizes, gets the toolbar window width and then
1350 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
1351 * on. It assigns a new location to each item and sends this location to
1352 * the tooltip window if appropriate. Finally, it updates the rcBound
1353 * rect and calculates the new required toolbar window height.
1357 TOOLBAR_CalcToolbar (HWND hwnd
)
1359 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
1360 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1361 TBUTTON_INFO
*btnPtr
;
1362 INT i
, nRows
, nSepRows
;
1366 BOOL usesBitmaps
= FALSE
;
1367 BOOL hasDropDownArrows
= TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
);
1369 TOOLBAR_CalcStrings (hwnd
, &sizeString
);
1371 for (i
= 0; i
< infoPtr
->nNumButtons
&& !usesBitmaps
; i
++)
1373 if (TOOLBAR_IsValidBitmapIndex(infoPtr
,infoPtr
->buttons
[i
].iBitmap
))
1376 if (dwStyle
& TBSTYLE_LIST
)
1378 infoPtr
->nButtonHeight
= max((usesBitmaps
) ? infoPtr
->nBitmapHeight
:
1379 0, sizeString
.cy
) + infoPtr
->szPadding
.cy
;
1380 infoPtr
->nButtonWidth
= ((usesBitmaps
) ? infoPtr
->nBitmapWidth
:
1381 0) + sizeString
.cx
+ 6;
1382 TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n",
1383 infoPtr
->nButtonWidth
, infoPtr
->nButtonHeight
, usesBitmaps
,
1384 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
1385 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
1388 if (sizeString
.cy
> 0)
1391 infoPtr
->nButtonHeight
= sizeString
.cy
+
1392 2 + /* this is the space to separate text from bitmap */
1393 infoPtr
->nBitmapHeight
+ 6;
1395 infoPtr
->nButtonHeight
= sizeString
.cy
+ 6;
1397 else if (infoPtr
->nButtonHeight
< infoPtr
->nBitmapHeight
+ 6)
1398 infoPtr
->nButtonHeight
= infoPtr
->nBitmapHeight
+ 6;
1400 if (sizeString
.cx
> infoPtr
->nBitmapWidth
)
1401 infoPtr
->nButtonWidth
= sizeString
.cx
+ 6;
1402 else if (infoPtr
->nButtonWidth
< infoPtr
->nBitmapWidth
+ 6)
1403 infoPtr
->nButtonWidth
= infoPtr
->nBitmapWidth
+ 6;
1406 if ( infoPtr
->cxMin
>= 0 && infoPtr
->nButtonWidth
< infoPtr
->cxMin
)
1407 infoPtr
->nButtonWidth
= infoPtr
->cxMin
;
1408 if ( infoPtr
->cxMax
> 0 && infoPtr
->nButtonWidth
> infoPtr
->cxMax
)
1409 infoPtr
->nButtonWidth
= infoPtr
->cxMax
;
1411 TOOLBAR_WrapToolbar( hwnd
, dwStyle
);
1413 x
= infoPtr
->nIndent
;
1417 * We will set the height below, and we set the width on entry
1418 * so we do not reset them here..
1421 GetClientRect( hwnd
, &rc
);
1422 /* get initial values for toolbar */
1423 infoPtr
->nWidth
= rc
.right
- rc
.left
;
1424 infoPtr
->nHeight
= rc
.bottom
- rc
.top
;
1427 /* from above, minimum is a button, and possible text */
1428 cx
= infoPtr
->nButtonWidth
;
1430 /* cannot use just ButtonHeight, we may have no buttons! */
1431 if (infoPtr
->nNumButtons
> 0)
1432 infoPtr
->nHeight
= infoPtr
->nButtonHeight
;
1434 cy
= infoPtr
->nHeight
;
1436 nRows
= nSepRows
= 0;
1438 infoPtr
->rcBound
.top
= y
;
1439 infoPtr
->rcBound
.left
= x
;
1440 infoPtr
->rcBound
.bottom
= y
+ cy
;
1441 infoPtr
->rcBound
.right
= x
;
1443 btnPtr
= infoPtr
->buttons
;
1445 /* do not base height/width on parent, if the parent is a */
1446 /* rebar control it could have multiple rows of toolbars */
1447 /* GetClientRect( GetParent(hwnd), &rc ); */
1448 /* cx = rc.right - rc.left; */
1449 /* cy = rc.bottom - rc.top; */
1451 TRACE("cy=%d\n", cy
);
1453 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++ )
1456 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
1458 SetRectEmpty (&btnPtr
->rect
);
1462 cy
= infoPtr
->nHeight
;
1464 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1465 /* it is the actual width of the separator. This is used for */
1466 /* custom controls in toolbars. */
1467 if (btnPtr
->fsStyle
& TBSTYLE_SEP
) {
1468 if (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
) {
1469 cy
= (btnPtr
->iBitmap
> 0) ?
1470 btnPtr
->iBitmap
: SEPARATOR_WIDTH
;
1471 cx
= infoPtr
->nButtonWidth
;
1474 cx
= (btnPtr
->iBitmap
> 0) ?
1475 btnPtr
->iBitmap
: SEPARATOR_WIDTH
;
1479 if ((infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) ||
1480 (btnPtr
->fsStyle
& TBSTYLE_AUTOSIZE
))
1487 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
1489 TOOLBAR_MeasureString(infoPtr
, btnPtr
, hdc
, &sz
);
1491 SelectObject (hdc
, hOldFont
);
1492 ReleaseDC (hwnd
, hdc
);
1495 sz
.cx
+= 2*LIST_TEXT_OFFSET
;
1496 cx
= sz
.cx
+ 2*LIST_IMAGE_OFFSET
;
1497 if (TOOLBAR_TestImageExist (infoPtr
, btnPtr
, GETDEFIMAGELIST(infoPtr
,0)))
1499 if (dwStyle
& TBSTYLE_LIST
)
1500 cx
+= infoPtr
->nBitmapWidth
;
1501 else if (cx
< (infoPtr
->nBitmapWidth
+7))
1502 cx
= infoPtr
->nBitmapWidth
+7;
1504 else if (dwStyle
& TBSTYLE_LIST
)
1505 cx
+= LIST_IMAGE_ABSENT_WIDTH
;
1508 cx
= infoPtr
->nButtonWidth
;
1510 if (hasDropDownArrows
&& (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
))
1511 cx
+= DDARROW_WIDTH
;
1513 if (btnPtr
->fsState
& TBSTATE_WRAP
)
1516 SetRect (&btnPtr
->rect
, x
, y
, x
+ cx
, y
+ cy
);
1518 if (infoPtr
->rcBound
.left
> x
)
1519 infoPtr
->rcBound
.left
= x
;
1520 if (infoPtr
->rcBound
.right
< x
+ cx
)
1521 infoPtr
->rcBound
.right
= x
+ cx
;
1522 if (infoPtr
->rcBound
.bottom
< y
+ cy
)
1523 infoPtr
->rcBound
.bottom
= y
+ cy
;
1525 /* Set the toolTip only for non-hidden, non-separator button */
1526 if (infoPtr
->hwndToolTip
&& !(btnPtr
->fsStyle
& TBSTYLE_SEP
))
1530 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
1531 ti
.cbSize
= sizeof(TTTOOLINFOA
);
1533 ti
.uId
= btnPtr
->idCommand
;
1534 ti
.rect
= btnPtr
->rect
;
1535 SendMessageA (infoPtr
->hwndToolTip
, TTM_NEWTOOLRECTA
,
1539 /* btnPtr->nRow is zero based. The space between the rows is */
1540 /* also considered as a row. */
1541 btnPtr
->nRow
= nRows
+ nSepRows
;
1543 TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n",
1544 i
, btnPtr
->fsStyle
, bWrap
, nRows
, nSepRows
, btnPtr
->nRow
,
1549 if ( !(btnPtr
->fsStyle
& TBSTYLE_SEP
) )
1553 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1554 /* it is the actual width of the separator. This is used for */
1555 /* custom controls in toolbars. */
1556 if ( !(btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
))
1557 y
+= cy
+ ( (btnPtr
->iBitmap
> 0 ) ?
1558 btnPtr
->iBitmap
: SEPARATOR_WIDTH
) * 2 /3;
1562 /* nSepRows is used to calculate the extra height follwoing */
1566 x
= infoPtr
->nIndent
;
1568 /* Increment row number unless this is the last button */
1569 /* and it has Wrap set. */
1570 if (i
!= infoPtr
->nNumButtons
-1)
1577 /* infoPtr->nRows is the number of rows on the toolbar */
1578 infoPtr
->nRows
= nRows
+ nSepRows
+ 1;
1581 /********************************************************************
1582 * The following while interesting, does not match the values *
1583 * created above for the button rectangles, nor the rcBound rect. *
1584 * We will comment it out and remove it later. *
1586 * The problem showed up as heights in the pager control that was *
1588 ********************************************************************/
1590 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
1592 infoPtr
->nHeight
= TOP_BORDER
+ (nRows
+ 1) * infoPtr
->nButtonHeight
+
1593 nSepRows
* (SEPARATOR_WIDTH
* 2 / 3) +
1594 nSepRows
* (infoPtr
->nBitmapHeight
+ 1) +
1598 infoPtr
->nHeight
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
1600 TRACE("toolbar height %d, button width %d\n", infoPtr
->nHeight
, infoPtr
->nButtonWidth
);
1605 TOOLBAR_InternalHitTest (HWND hwnd
, LPPOINT lpPt
)
1607 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1608 TBUTTON_INFO
*btnPtr
;
1611 btnPtr
= infoPtr
->buttons
;
1612 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1613 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
1616 if (btnPtr
->fsStyle
& TBSTYLE_SEP
) {
1617 if (PtInRect (&btnPtr
->rect
, *lpPt
)) {
1618 TRACE(" ON SEPARATOR %d!\n", i
);
1623 if (PtInRect (&btnPtr
->rect
, *lpPt
)) {
1624 TRACE(" ON BUTTON %d!\n", i
);
1630 TRACE(" NOWHERE!\n");
1636 TOOLBAR_GetButtonIndex (TOOLBAR_INFO
*infoPtr
, INT idCommand
, BOOL CommandIsIndex
)
1638 TBUTTON_INFO
*btnPtr
;
1641 if (CommandIsIndex
) {
1642 TRACE("command is really index command=%d\n", idCommand
);
1643 if (idCommand
>= infoPtr
->nNumButtons
) return -1;
1646 btnPtr
= infoPtr
->buttons
;
1647 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1648 if (btnPtr
->idCommand
== idCommand
) {
1649 TRACE("command=%d index=%d\n", idCommand
, i
);
1653 TRACE("no index found for command=%d\n", idCommand
);
1659 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO
*infoPtr
, INT nIndex
)
1661 TBUTTON_INFO
*btnPtr
;
1664 if ((nIndex
< 0) || (nIndex
> infoPtr
->nNumButtons
))
1667 /* check index button */
1668 btnPtr
= &infoPtr
->buttons
[nIndex
];
1669 if ((btnPtr
->fsStyle
& TBSTYLE_CHECKGROUP
) == TBSTYLE_CHECKGROUP
) {
1670 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1674 /* check previous buttons */
1675 nRunIndex
= nIndex
- 1;
1676 while (nRunIndex
>= 0) {
1677 btnPtr
= &infoPtr
->buttons
[nRunIndex
];
1678 if ((btnPtr
->fsStyle
& TBSTYLE_CHECKGROUP
) == TBSTYLE_CHECKGROUP
) {
1679 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1687 /* check next buttons */
1688 nRunIndex
= nIndex
+ 1;
1689 while (nRunIndex
< infoPtr
->nNumButtons
) {
1690 btnPtr
= &infoPtr
->buttons
[nRunIndex
];
1691 if ((btnPtr
->fsStyle
& TBSTYLE_CHECKGROUP
) == TBSTYLE_CHECKGROUP
) {
1692 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1705 TOOLBAR_RelayEvent (HWND hwndTip
, HWND hwndMsg
, UINT uMsg
,
1706 WPARAM wParam
, LPARAM lParam
)
1712 msg
.wParam
= wParam
;
1713 msg
.lParam
= lParam
;
1714 msg
.time
= GetMessageTime ();
1715 msg
.pt
.x
= LOWORD(GetMessagePos ());
1716 msg
.pt
.y
= HIWORD(GetMessagePos ());
1718 SendMessageA (hwndTip
, TTM_RELAYEVENT
, 0, (LPARAM
)&msg
);
1722 /***********************************************************************
1723 * TOOLBAR_CustomizeDialogProc
1724 * This function implements the toolbar customization dialog.
1726 static INT_PTR CALLBACK
1727 TOOLBAR_CustomizeDialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1729 PCUSTDLG_INFO custInfo
= (PCUSTDLG_INFO
)GetWindowLongA (hwnd
, DWL_USER
);
1730 PCUSTOMBUTTON btnInfo
;
1732 TOOLBAR_INFO
*infoPtr
= custInfo
? custInfo
->tbInfo
: NULL
;
1737 custInfo
= (PCUSTDLG_INFO
)lParam
;
1738 SetWindowLongA (hwnd
, DWL_USER
, (DWORD
)custInfo
);
1746 infoPtr
= custInfo
->tbInfo
;
1748 /* send TBN_QUERYINSERT notification */
1749 nmtb
.iItem
= custInfo
->tbInfo
->nNumButtons
;
1751 if (!TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_QUERYINSERT
))
1754 /* UNDOCUMENTED: dialog hwnd immediately follows NMHDR */
1755 nmtb
.iItem
= (int)hwnd
;
1756 /* Send TBN_INITCUSTOMIZE notification */
1757 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_INITCUSTOMIZE
) ==
1760 TRACE("TBNRF_HIDEHELP requested\n");
1761 ShowWindow(GetDlgItem(hwnd
, IDC_HELP_BTN
), SW_HIDE
);
1764 /* add items to 'toolbar buttons' list and check if removable */
1765 for (i
= 0; i
< custInfo
->tbInfo
->nNumButtons
; i
++)
1767 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1768 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1769 btnInfo
->btn
.fsStyle
= TBSTYLE_SEP
;
1770 btnInfo
->bVirtual
= FALSE
;
1771 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1773 /* send TBN_QUERYDELETE notification */
1774 btnInfo
->bRemovable
= TOOLBAR_IsButtonRemovable(infoPtr
, i
, btnInfo
);
1776 index
= (int)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_ADDSTRING
, 0, 0);
1777 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1780 /* insert separator button into 'available buttons' list */
1781 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1782 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1783 btnInfo
->btn
.fsStyle
= TBSTYLE_SEP
;
1784 btnInfo
->bVirtual
= FALSE
;
1785 btnInfo
->bRemovable
= TRUE
;
1786 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1787 index
= (int)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, (LPARAM
)btnInfo
);
1788 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1790 /* insert all buttons into dsa */
1793 /* send TBN_GETBUTTONINFO notification */
1796 nmtb
.pszText
= Buffer
;
1799 /* Clear previous button's text */
1800 ZeroMemory(nmtb
.pszText
, nmtb
.cchText
* sizeof(WCHAR
));
1802 if (!TOOLBAR_GetButtonInfo(infoPtr
, &nmtb
))
1805 TRACE("WM_INITDIALOG style: %x iItem(%d) idCommand(%d) iString(%d) %s\n",
1806 nmtb
.tbButton
.fsStyle
, i
,
1807 nmtb
.tbButton
.idCommand
,
1808 nmtb
.tbButton
.iString
,
1809 nmtb
.tbButton
.iString
>= 0 ? debugstr_w(infoPtr
->strings
[nmtb
.tbButton
.iString
])
1812 /* insert button into the apropriate list */
1813 index
= TOOLBAR_GetButtonIndex (custInfo
->tbInfo
, nmtb
.tbButton
.idCommand
, FALSE
);
1816 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1817 btnInfo
->bVirtual
= FALSE
;
1818 btnInfo
->bRemovable
= TRUE
;
1820 index
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, 0);
1821 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
,
1822 LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1826 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
,
1827 IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1830 memcpy (&btnInfo
->btn
, &nmtb
.tbButton
, sizeof(TBBUTTON
));
1831 if (!(nmtb
.tbButton
.fsStyle
& TBSTYLE_SEP
))
1833 if (lstrlenW(nmtb
.pszText
))
1834 lstrcpyW(btnInfo
->text
, nmtb
.pszText
);
1835 else if (nmtb
.tbButton
.iString
>= 0 &&
1836 nmtb
.tbButton
.iString
< infoPtr
->nNumStrings
)
1838 lstrcpyW(btnInfo
->text
,
1839 infoPtr
->strings
[nmtb
.tbButton
.iString
]);
1844 /* select first item in the 'available' list */
1845 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, 0, 0);
1847 /* append 'virtual' separator button to the 'toolbar buttons' list */
1848 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1849 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1850 btnInfo
->btn
.fsStyle
= TBSTYLE_SEP
;
1851 btnInfo
->bVirtual
= TRUE
;
1852 btnInfo
->bRemovable
= FALSE
;
1853 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1854 index
= (int)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_ADDSTRING
, 0, (LPARAM
)btnInfo
);
1855 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1857 /* select last item in the 'toolbar' list */
1858 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
, 0);
1859 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETTOPINDEX
, index
, 0);
1861 /* set focus and disable buttons */
1862 PostMessageA (hwnd
, WM_USER
, 0, 0);
1867 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1868 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1869 EnableWindow (GetDlgItem (hwnd
,IDC_REMOVE_BTN
), FALSE
);
1870 SetFocus (GetDlgItem (hwnd
, IDC_TOOLBARBTN_LBOX
));
1874 EndDialog(hwnd
, FALSE
);
1878 switch (LOWORD(wParam
))
1880 case IDC_TOOLBARBTN_LBOX
:
1881 if (HIWORD(wParam
) == LBN_SELCHANGE
)
1883 PCUSTOMBUTTON btnInfo
;
1888 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1889 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1891 /* send TBN_QUERYINSERT notification */
1893 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1896 /* get list box item */
1897 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1899 if (index
== (count
- 1))
1901 /* last item (virtual separator) */
1902 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1903 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1905 else if (index
== (count
- 2))
1907 /* second last item (last non-virtual item) */
1908 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1909 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1911 else if (index
== 0)
1914 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1915 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1919 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1920 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1923 EnableWindow (GetDlgItem (hwnd
,IDC_REMOVE_BTN
), btnInfo
->bRemovable
);
1927 case IDC_MOVEUP_BTN
:
1929 PCUSTOMBUTTON btnInfo
;
1933 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1934 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1935 TRACE("Move up: index %d\n", index
);
1937 /* send TBN_QUERYINSERT notification */
1940 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1943 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1945 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1946 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
-1, 0);
1947 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
-1, (LPARAM
)btnInfo
);
1948 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
-1 , 0);
1951 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1952 else if (index
>= (count
- 3))
1953 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1955 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
1956 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
-1, (LPARAM
)&(btnInfo
->btn
));
1961 case IDC_MOVEDN_BTN
: /* move down */
1963 PCUSTOMBUTTON btnInfo
;
1967 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1968 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1969 TRACE("Move up: index %d\n", index
);
1971 /* send TBN_QUERYINSERT notification */
1973 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1976 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1978 /* move button down */
1979 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1980 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
+1, 0);
1981 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
+1, (LPARAM
)btnInfo
);
1982 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
+1 , 0);
1985 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1986 else if (index
>= (count
- 3))
1987 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1989 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
1990 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
+1, (LPARAM
)&(btnInfo
->btn
));
1995 case IDC_REMOVE_BTN
: /* remove button */
1997 PCUSTOMBUTTON btnInfo
;
2000 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
2002 if (LB_ERR
== index
)
2005 TRACE("Remove: index %d\n", index
);
2007 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
,
2008 LB_GETITEMDATA
, index
, 0);
2010 /* send TBN_QUERYDELETE notification */
2011 if (TOOLBAR_IsButtonRemovable(infoPtr
, index
, btnInfo
))
2013 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
2014 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
2015 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
, 0);
2017 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
2019 /* insert into 'available button' list */
2020 if (!(btnInfo
->btn
.fsStyle
& TBSTYLE_SEP
))
2022 index
= (int)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, 0);
2023 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
2031 TOOLBAR_SendNotify(&nmtb
.hdr
, infoPtr
, TBN_CUSTHELP
);
2034 TOOLBAR_SendNotify(&nmtb
.hdr
, infoPtr
, TBN_RESET
);
2037 case IDOK
: /* Add button */
2042 count
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2043 index
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCURSEL
, 0, 0);
2044 TRACE("Add: index %d\n", index
);
2046 /* send TBN_QUERYINSERT notification */
2048 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
2051 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
2055 /* remove from 'available buttons' list */
2056 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_DELETESTRING
, index
, 0);
2057 if (index
== count
-1)
2058 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, index
-1 , 0);
2060 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, index
, 0);
2064 PCUSTOMBUTTON btnNew
;
2066 /* duplicate 'separator' button */
2067 btnNew
= (PCUSTOMBUTTON
)Alloc (sizeof(CUSTOMBUTTON
));
2068 memcpy (btnNew
, btnInfo
, sizeof(CUSTOMBUTTON
));
2072 /* insert into 'toolbar button' list */
2073 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
2074 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
, 0);
2075 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
2077 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
, (LPARAM
)&(btnInfo
->btn
));
2083 EndDialog(hwnd
, FALSE
);
2093 /* delete items from 'toolbar buttons' listbox*/
2094 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2095 for (i
= 0; i
< count
; i
++)
2097 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, i
, 0);
2099 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, 0, 0);
2101 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_RESETCONTENT
, 0, 0);
2104 /* delete items from 'available buttons' listbox*/
2105 count
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2106 for (i
= 0; i
< count
; i
++)
2108 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETITEMDATA
, i
, 0);
2110 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, i
, 0);
2112 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_RESETCONTENT
, 0, 0);
2117 if (wParam
== IDC_AVAILBTN_LBOX
|| wParam
== IDC_TOOLBARBTN_LBOX
)
2119 LPDRAWITEMSTRUCT lpdis
= (LPDRAWITEMSTRUCT
)lParam
;
2120 DWORD dwStyle
= GetWindowLongA (infoPtr
->hwndSelf
, GWL_STYLE
);
2125 COLORREF oldText
= 0;
2129 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, wParam
, LB_GETITEMDATA
, (WPARAM
)lpdis
->itemID
, 0);
2130 if (btnInfo
== NULL
)
2132 FIXME("btnInfo invalid!\n");
2136 /* set colors and select objects */
2137 oldBk
= SetBkColor (lpdis
->hDC
, (lpdis
->itemState
& ODS_FOCUS
)?comctl32_color
.clrHighlight
:comctl32_color
.clrWindow
);
2138 if (btnInfo
->bVirtual
)
2139 oldText
= SetTextColor (lpdis
->hDC
, comctl32_color
.clrGrayText
);
2141 oldText
= SetTextColor (lpdis
->hDC
, (lpdis
->itemState
& ODS_FOCUS
)?comctl32_color
.clrHighlightText
:comctl32_color
.clrWindowText
);
2142 hPen
= CreatePen( PS_SOLID
, 1,
2143 GetSysColor( (lpdis
->itemState
& ODS_SELECTED
)?COLOR_HIGHLIGHT
:COLOR_WINDOW
));
2144 hOldPen
= SelectObject (lpdis
->hDC
, hPen
);
2145 hOldBrush
= SelectObject (lpdis
->hDC
, GetSysColorBrush ((lpdis
->itemState
& ODS_FOCUS
)?COLOR_HIGHLIGHT
:COLOR_WINDOW
));
2147 /* fill background rectangle */
2148 Rectangle (lpdis
->hDC
, lpdis
->rcItem
.left
, lpdis
->rcItem
.top
,
2149 lpdis
->rcItem
.right
, lpdis
->rcItem
.bottom
);
2151 /* calculate button and text rectangles */
2152 CopyRect (&rcButton
, &lpdis
->rcItem
);
2153 InflateRect (&rcButton
, -1, -1);
2154 CopyRect (&rcText
, &rcButton
);
2155 rcButton
.right
= rcButton
.left
+ custInfo
->tbInfo
->nBitmapWidth
+ 6;
2156 rcText
.left
= rcButton
.right
+ 2;
2158 /* draw focus rectangle */
2159 if (lpdis
->itemState
& ODS_FOCUS
)
2160 DrawFocusRect (lpdis
->hDC
, &lpdis
->rcItem
);
2163 if (!(dwStyle
& TBSTYLE_FLAT
))
2164 DrawEdge (lpdis
->hDC
, &rcButton
, EDGE_RAISED
, BF_RECT
|BF_MIDDLE
|BF_SOFT
);
2166 /* draw image and text */
2167 if ((btnInfo
->btn
.fsStyle
& TBSTYLE_SEP
) == 0) {
2168 HIMAGELIST himl
= GETDEFIMAGELIST(infoPtr
, GETHIMLID(infoPtr
,
2169 btnInfo
->btn
.iBitmap
));
2170 ImageList_Draw (himl
, GETIBITMAP(infoPtr
, btnInfo
->btn
.iBitmap
),
2171 lpdis
->hDC
, rcButton
.left
+3, rcButton
.top
+3, ILD_NORMAL
);
2173 DrawTextW (lpdis
->hDC
, btnInfo
->text
, -1, &rcText
,
2174 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
2176 /* delete objects and reset colors */
2177 SelectObject (lpdis
->hDC
, hOldBrush
);
2178 SelectObject (lpdis
->hDC
, hOldPen
);
2179 SetBkColor (lpdis
->hDC
, oldBk
);
2180 SetTextColor (lpdis
->hDC
, oldText
);
2181 DeleteObject( hPen
);
2186 case WM_MEASUREITEM
:
2187 if (wParam
== IDC_AVAILBTN_LBOX
|| wParam
== IDC_TOOLBARBTN_LBOX
)
2189 MEASUREITEMSTRUCT
*lpmis
= (MEASUREITEMSTRUCT
*)lParam
;
2191 if (custInfo
&& custInfo
->tbInfo
)
2192 lpmis
->itemHeight
= custInfo
->tbInfo
->nBitmapHeight
+ 8;
2194 lpmis
->itemHeight
= 15 + 8; /* default height */
2206 /***********************************************************************
2207 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
2211 TOOLBAR_AddBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2213 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2214 LPTBADDBITMAP lpAddBmp
= (LPTBADDBITMAP
)lParam
;
2215 INT nIndex
= 0, nButtons
, nCount
;
2219 TRACE("hwnd=%p wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2223 if (lpAddBmp
->hInst
== HINST_COMMCTRL
)
2225 if ((lpAddBmp
->nID
& ~1) == IDB_STD_SMALL_COLOR
)
2227 else if ((lpAddBmp
->nID
& ~1) == IDB_VIEW_SMALL_COLOR
)
2229 else if ((lpAddBmp
->nID
& ~1) == IDB_HIST_SMALL_COLOR
)
2234 TRACE ("adding %d internal bitmaps!\n", nButtons
);
2236 /* Windows resize all the buttons to the size of a newly added standard image */
2237 if (lpAddBmp
->nID
& 1)
2240 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
2241 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
2243 SendMessageA (hwnd
, TB_SETBITMAPSIZE
, 0,
2244 MAKELPARAM((WORD
)24, (WORD
)24));
2245 SendMessageA (hwnd
, TB_SETBUTTONSIZE
, 0,
2246 MAKELPARAM((WORD
)31, (WORD
)30));
2251 SendMessageA (hwnd
, TB_SETBITMAPSIZE
, 0,
2252 MAKELPARAM((WORD
)16, (WORD
)16));
2253 SendMessageA (hwnd
, TB_SETBUTTONSIZE
, 0,
2254 MAKELPARAM((WORD
)22, (WORD
)22));
2257 TOOLBAR_CalcToolbar (hwnd
);
2261 nButtons
= (INT
)wParam
;
2265 TRACE ("adding %d bitmaps!\n", nButtons
);
2268 if (!infoPtr
->cimlDef
) {
2269 /* create new default image list */
2270 TRACE ("creating default image list!\n");
2272 himlDef
= ImageList_Create (infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
,
2273 ILC_COLOR
| ILC_MASK
, nButtons
, 2);
2274 TOOLBAR_InsertImageList(&infoPtr
->himlDef
, &infoPtr
->cimlDef
, himlDef
, 0);
2275 infoPtr
->himlInt
= himlDef
;
2278 himlDef
= GETDEFIMAGELIST(infoPtr
, 0);
2282 WARN("No default image list available\n");
2286 nCount
= ImageList_GetImageCount(himlDef
);
2288 /* Add bitmaps to the default image list */
2289 if (lpAddBmp
->hInst
== NULL
)
2292 HBITMAP hOldBitmapBitmap
, hOldBitmapLoad
;
2293 HDC hdcImage
, hdcBitmap
;
2295 /* copy the bitmap before adding it so that the user's bitmap
2296 * doesn't get modified.
2298 GetObjectA ((HBITMAP
)lpAddBmp
->nID
, sizeof(BITMAP
), (LPVOID
)&bmp
);
2300 hdcImage
= CreateCompatibleDC(0);
2301 hdcBitmap
= CreateCompatibleDC(0);
2303 /* create new bitmap */
2304 hbmLoad
= CreateBitmap (bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
, bmp
.bmBitsPixel
, NULL
);
2305 hOldBitmapBitmap
= SelectObject(hdcBitmap
, (HBITMAP
)lpAddBmp
->nID
);
2306 hOldBitmapLoad
= SelectObject(hdcImage
, hbmLoad
);
2308 /* Copy the user's image */
2309 BitBlt (hdcImage
, 0, 0, bmp
.bmWidth
, bmp
.bmHeight
,
2310 hdcBitmap
, 0, 0, SRCCOPY
);
2312 SelectObject (hdcImage
, hOldBitmapLoad
);
2313 SelectObject (hdcBitmap
, hOldBitmapBitmap
);
2314 DeleteDC (hdcImage
);
2315 DeleteDC (hdcBitmap
);
2317 nIndex
= ImageList_AddMasked (himlDef
, hbmLoad
, comctl32_color
.clrBtnFace
);
2318 DeleteObject (hbmLoad
);
2320 else if (lpAddBmp
->hInst
== HINST_COMMCTRL
)
2322 /* Add system bitmaps */
2323 switch (lpAddBmp
->nID
)
2325 case IDB_STD_SMALL_COLOR
:
2326 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2327 MAKEINTRESOURCEA(IDB_STD_SMALL
));
2328 nIndex
= ImageList_AddMasked (himlDef
,
2329 hbmLoad
, comctl32_color
.clrBtnFace
);
2330 DeleteObject (hbmLoad
);
2333 case IDB_STD_LARGE_COLOR
:
2334 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2335 MAKEINTRESOURCEA(IDB_STD_LARGE
));
2336 nIndex
= ImageList_AddMasked (himlDef
,
2337 hbmLoad
, comctl32_color
.clrBtnFace
);
2338 DeleteObject (hbmLoad
);
2341 case IDB_VIEW_SMALL_COLOR
:
2342 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2343 MAKEINTRESOURCEA(IDB_VIEW_SMALL
));
2344 nIndex
= ImageList_AddMasked (himlDef
,
2345 hbmLoad
, comctl32_color
.clrBtnFace
);
2346 DeleteObject (hbmLoad
);
2349 case IDB_VIEW_LARGE_COLOR
:
2350 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2351 MAKEINTRESOURCEA(IDB_VIEW_LARGE
));
2352 nIndex
= ImageList_AddMasked (himlDef
,
2353 hbmLoad
, comctl32_color
.clrBtnFace
);
2354 DeleteObject (hbmLoad
);
2357 case IDB_HIST_SMALL_COLOR
:
2358 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2359 MAKEINTRESOURCEA(IDB_HIST_SMALL
));
2360 nIndex
= ImageList_AddMasked (himlDef
,
2361 hbmLoad
, comctl32_color
.clrBtnFace
);
2362 DeleteObject (hbmLoad
);
2365 case IDB_HIST_LARGE_COLOR
:
2366 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2367 MAKEINTRESOURCEA(IDB_HIST_LARGE
));
2368 nIndex
= ImageList_AddMasked (himlDef
,
2369 hbmLoad
, comctl32_color
.clrBtnFace
);
2370 DeleteObject (hbmLoad
);
2374 nIndex
= ImageList_GetImageCount (himlDef
);
2375 ERR ("invalid imagelist!\n");
2381 hbmLoad
= LoadBitmapA (lpAddBmp
->hInst
, (LPSTR
)lpAddBmp
->nID
);
2382 nIndex
= ImageList_AddMasked (himlDef
, hbmLoad
, comctl32_color
.clrBtnFace
);
2383 DeleteObject (hbmLoad
);
2386 TRACE("Number of bitmap infos: %d\n", infoPtr
->nNumBitmapInfos
);
2388 if (infoPtr
->nNumBitmapInfos
== 0)
2390 infoPtr
->bitmaps
= Alloc(sizeof(TBITMAP_INFO
));
2394 TBITMAP_INFO
*oldBitmaps
= infoPtr
->bitmaps
;
2395 infoPtr
->bitmaps
= Alloc((infoPtr
->nNumBitmapInfos
+ 1) * sizeof(TBITMAP_INFO
));
2396 memcpy(&infoPtr
->bitmaps
[0], &oldBitmaps
[0], infoPtr
->nNumBitmapInfos
);
2399 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].nButtons
= nButtons
;
2400 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].hInst
= lpAddBmp
->hInst
;
2401 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].nID
= lpAddBmp
->nID
;
2403 infoPtr
->nNumBitmapInfos
++;
2404 TRACE("Number of bitmap infos: %d\n", infoPtr
->nNumBitmapInfos
);
2408 INT imagecount
= ImageList_GetImageCount(himlDef
);
2410 if (infoPtr
->nNumBitmaps
+ nButtons
!= imagecount
)
2412 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",
2413 infoPtr
->nNumBitmaps
, nCount
, imagecount
- nCount
,
2414 infoPtr
->nNumBitmaps
+nButtons
,imagecount
);
2416 infoPtr
->nNumBitmaps
= imagecount
;
2419 infoPtr
->nNumBitmaps
+= nButtons
;
2422 InvalidateRect(hwnd
, NULL
, FALSE
);
2429 TOOLBAR_AddButtonsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2431 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2432 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
2433 INT nOldButtons
, nNewButtons
, nAddButtons
, nCount
;
2435 TRACE("adding %d buttons!\n", wParam
);
2437 nAddButtons
= (UINT
)wParam
;
2438 nOldButtons
= infoPtr
->nNumButtons
;
2439 nNewButtons
= nOldButtons
+ nAddButtons
;
2441 if (infoPtr
->nNumButtons
== 0) {
2443 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2446 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2448 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2449 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2450 nOldButtons
* sizeof(TBUTTON_INFO
));
2454 infoPtr
->nNumButtons
= nNewButtons
;
2456 /* insert new button data */
2457 for (nCount
= 0; nCount
< nAddButtons
; nCount
++) {
2458 TBUTTON_INFO
*btnPtr
= &infoPtr
->buttons
[nOldButtons
+nCount
];
2459 btnPtr
->iBitmap
= lpTbb
[nCount
].iBitmap
;
2460 btnPtr
->idCommand
= lpTbb
[nCount
].idCommand
;
2461 btnPtr
->fsState
= lpTbb
[nCount
].fsState
;
2462 btnPtr
->fsStyle
= lpTbb
[nCount
].fsStyle
;
2463 btnPtr
->dwData
= lpTbb
[nCount
].dwData
;
2464 btnPtr
->iString
= lpTbb
[nCount
].iString
;
2465 btnPtr
->bHot
= FALSE
;
2467 if ((infoPtr
->hwndToolTip
) && !(btnPtr
->fsStyle
& TBSTYLE_SEP
)) {
2470 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
2471 ti
.cbSize
= sizeof (TTTOOLINFOA
);
2473 ti
.uId
= btnPtr
->idCommand
;
2475 ti
.lpszText
= LPSTR_TEXTCALLBACKA
;
2477 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
,
2482 TOOLBAR_CalcToolbar (hwnd
);
2484 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
2486 InvalidateRect(hwnd
, NULL
, FALSE
);
2493 TOOLBAR_AddButtonsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2495 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2496 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
2497 INT nOldButtons
, nNewButtons
, nAddButtons
, nCount
;
2499 TRACE("adding %d buttons!\n", wParam
);
2501 nAddButtons
= (UINT
)wParam
;
2502 nOldButtons
= infoPtr
->nNumButtons
;
2503 nNewButtons
= nOldButtons
+ nAddButtons
;
2505 if (infoPtr
->nNumButtons
== 0) {
2507 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2510 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2512 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2513 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2514 nOldButtons
* sizeof(TBUTTON_INFO
));
2518 infoPtr
->nNumButtons
= nNewButtons
;
2520 /* insert new button data */
2521 for (nCount
= 0; nCount
< nAddButtons
; nCount
++) {
2522 TBUTTON_INFO
*btnPtr
= &infoPtr
->buttons
[nOldButtons
+nCount
];
2523 btnPtr
->iBitmap
= lpTbb
[nCount
].iBitmap
;
2524 btnPtr
->idCommand
= lpTbb
[nCount
].idCommand
;
2525 btnPtr
->fsState
= lpTbb
[nCount
].fsState
;
2526 btnPtr
->fsStyle
= lpTbb
[nCount
].fsStyle
;
2527 btnPtr
->dwData
= lpTbb
[nCount
].dwData
;
2528 btnPtr
->iString
= lpTbb
[nCount
].iString
;
2529 btnPtr
->bHot
= FALSE
;
2531 if ((infoPtr
->hwndToolTip
) && !(btnPtr
->fsStyle
& TBSTYLE_SEP
)) {
2534 ZeroMemory (&ti
, sizeof(TTTOOLINFOW
));
2535 ti
.cbSize
= sizeof (TTTOOLINFOW
);
2537 ti
.uId
= btnPtr
->idCommand
;
2539 ti
.lpszText
= LPSTR_TEXTCALLBACKW
;
2542 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
,
2547 TOOLBAR_CalcToolbar (hwnd
);
2549 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
2551 InvalidateRect(hwnd
, NULL
, FALSE
);
2558 TOOLBAR_AddStringA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2560 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2563 if ((wParam
) && (HIWORD(lParam
) == 0)) {
2566 TRACE("adding string from resource!\n");
2568 len
= LoadStringA ((HINSTANCE
)wParam
, (UINT
)lParam
,
2571 TRACE("len=%d \"%s\"\n", len
, szString
);
2572 nIndex
= infoPtr
->nNumStrings
;
2573 if (infoPtr
->nNumStrings
== 0) {
2575 Alloc (sizeof(LPWSTR
));
2578 LPWSTR
*oldStrings
= infoPtr
->strings
;
2580 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2581 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2582 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2586 /*Alloc zeros out the allocated memory*/
2587 Str_SetPtrAtoW (&infoPtr
->strings
[infoPtr
->nNumStrings
], szString
);
2588 infoPtr
->nNumStrings
++;
2591 LPSTR p
= (LPSTR
)lParam
;
2596 TRACE("adding string(s) from array!\n");
2598 nIndex
= infoPtr
->nNumStrings
;
2601 TRACE("len=%d \"%s\"\n", len
, p
);
2603 if (infoPtr
->nNumStrings
== 0) {
2605 Alloc (sizeof(LPWSTR
));
2608 LPWSTR
*oldStrings
= infoPtr
->strings
;
2610 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2611 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2612 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2616 Str_SetPtrAtoW (&infoPtr
->strings
[infoPtr
->nNumStrings
], p
);
2617 infoPtr
->nNumStrings
++;
2628 TOOLBAR_AddStringW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2630 #define MAX_RESOURCE_STRING_LENGTH 512
2631 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2634 if ((wParam
) && (HIWORD(lParam
) == 0)) {
2635 WCHAR szString
[MAX_RESOURCE_STRING_LENGTH
];
2637 TRACE("adding string from resource!\n");
2639 len
= LoadStringW ((HINSTANCE
)wParam
, (UINT
)lParam
,
2640 szString
, MAX_RESOURCE_STRING_LENGTH
);
2642 TRACE("len=%d %s\n", len
, debugstr_w(szString
));
2643 TRACE("First char: 0x%x\n", *szString
);
2644 if (szString
[0] == L
'|')
2646 PWSTR p
= szString
+ 1;
2648 nIndex
= infoPtr
->nNumStrings
;
2649 while (*p
!= L
'|' && *p
!= L
'\0') {
2652 if (infoPtr
->nNumStrings
== 0) {
2653 infoPtr
->strings
= Alloc (sizeof(LPWSTR
));
2657 LPWSTR
*oldStrings
= infoPtr
->strings
;
2658 infoPtr
->strings
= Alloc(sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2659 memcpy(&infoPtr
->strings
[0], &oldStrings
[0],
2660 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2664 np
=strchrW (p
, '|');
2672 TRACE("len=%d %s\n", len
, debugstr_w(p
));
2673 infoPtr
->strings
[infoPtr
->nNumStrings
] =
2674 Alloc (sizeof(WCHAR
)*(len
+1));
2675 lstrcpynW (infoPtr
->strings
[infoPtr
->nNumStrings
], p
, len
+1);
2676 infoPtr
->nNumStrings
++;
2683 nIndex
= infoPtr
->nNumStrings
;
2684 if (infoPtr
->nNumStrings
== 0) {
2686 Alloc (sizeof(LPWSTR
));
2689 LPWSTR
*oldStrings
= infoPtr
->strings
;
2691 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2692 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2693 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2697 Str_SetPtrW (&infoPtr
->strings
[infoPtr
->nNumStrings
], szString
);
2698 infoPtr
->nNumStrings
++;
2702 LPWSTR p
= (LPWSTR
)lParam
;
2707 TRACE("adding string(s) from array!\n");
2708 nIndex
= infoPtr
->nNumStrings
;
2712 TRACE("len=%d %s\n", len
, debugstr_w(p
));
2713 if (infoPtr
->nNumStrings
== 0) {
2715 Alloc (sizeof(LPWSTR
));
2718 LPWSTR
*oldStrings
= infoPtr
->strings
;
2720 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2721 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2722 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2726 Str_SetPtrW (&infoPtr
->strings
[infoPtr
->nNumStrings
], p
);
2727 infoPtr
->nNumStrings
++;
2738 TOOLBAR_AutoSize (HWND hwnd
)
2740 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2741 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2747 UINT uPosFlags
= SWP_NOZORDER
;
2749 TRACE("resize forced, style=%lx!\n", dwStyle
);
2751 parent
= GetParent (hwnd
);
2752 GetClientRect(parent
, &parent_rect
);
2754 x
= parent_rect
.left
;
2755 y
= parent_rect
.top
;
2757 /* FIXME: we should be able to early out if nothing */
2758 /* has changed with nWidth != parent_rect width */
2760 if (dwStyle
& CCS_NORESIZE
) {
2761 uPosFlags
|= (SWP_NOSIZE
| SWP_NOMOVE
);
2764 TOOLBAR_CalcToolbar (hwnd
);
2767 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
2768 TOOLBAR_CalcToolbar (hwnd
);
2769 InvalidateRect( hwnd
, NULL
, TRUE
);
2770 cy
= infoPtr
->nHeight
;
2771 cx
= infoPtr
->nWidth
;
2773 if ((dwStyle
& CCS_BOTTOM
) == CCS_NOMOVEY
) {
2774 GetWindowRect(hwnd
, &window_rect
);
2775 ScreenToClient(parent
, (LPPOINT
)&window_rect
.left
);
2776 y
= window_rect
.top
;
2778 if ((dwStyle
& CCS_BOTTOM
) == CCS_BOTTOM
) {
2779 GetWindowRect(hwnd
, &window_rect
);
2780 y
= parent_rect
.bottom
- ( window_rect
.bottom
- window_rect
.top
);
2784 if (dwStyle
& CCS_NOPARENTALIGN
)
2785 uPosFlags
|= SWP_NOMOVE
;
2787 if (!(dwStyle
& CCS_NODIVIDER
))
2788 cy
+= GetSystemMetrics(SM_CYEDGE
);
2790 if (dwStyle
& WS_BORDER
)
2793 cy
+= GetSystemMetrics(SM_CYEDGE
);
2794 cx
+= GetSystemMetrics(SM_CYEDGE
);
2797 infoPtr
->bAutoSize
= TRUE
;
2798 SetWindowPos (hwnd
, HWND_TOP
, x
, y
, cx
, cy
, uPosFlags
);
2799 /* The following line makes sure that the infoPtr->bAutoSize is turned off
2800 * after the setwindowpos calls */
2801 infoPtr
->bAutoSize
= FALSE
;
2808 TOOLBAR_ButtonCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2810 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2812 return infoPtr
->nNumButtons
;
2817 TOOLBAR_ButtonStructSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2819 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2821 if (infoPtr
== NULL
) {
2822 ERR("(%p, 0x%x, 0x%lx)\n", hwnd
, wParam
, lParam
);
2823 ERR("infoPtr == NULL!\n");
2827 infoPtr
->dwStructSize
= (DWORD
)wParam
;
2834 TOOLBAR_ChangeBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2836 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2837 TBUTTON_INFO
*btnPtr
;
2840 TRACE("button %d, iBitmap now %d\n", wParam
, LOWORD(lParam
));
2842 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2846 btnPtr
= &infoPtr
->buttons
[nIndex
];
2847 btnPtr
->iBitmap
= LOWORD(lParam
);
2849 /* we HAVE to erase the background, the new bitmap could be */
2851 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
2858 TOOLBAR_CheckButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2860 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2861 TBUTTON_INFO
*btnPtr
;
2864 BOOL bChecked
= FALSE
;
2866 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2870 btnPtr
= &infoPtr
->buttons
[nIndex
];
2872 if (!(btnPtr
->fsStyle
& TBSTYLE_CHECK
))
2875 bChecked
= (btnPtr
->fsState
& TBSTATE_CHECKED
) ? TRUE
: FALSE
;
2877 if (LOWORD(lParam
) == FALSE
)
2878 btnPtr
->fsState
&= ~TBSTATE_CHECKED
;
2880 if (btnPtr
->fsStyle
& TBSTYLE_GROUP
) {
2882 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr
, nIndex
);
2883 if (nOldIndex
== nIndex
)
2885 if (nOldIndex
!= -1)
2886 infoPtr
->buttons
[nOldIndex
].fsState
&= ~TBSTATE_CHECKED
;
2888 btnPtr
->fsState
|= TBSTATE_CHECKED
;
2891 if( bChecked
!= LOWORD(lParam
) )
2893 if (nOldIndex
!= -1)
2895 InvalidateRect(hwnd
, &infoPtr
->buttons
[nOldIndex
].rect
,
2896 TOOLBAR_HasText(infoPtr
, &infoPtr
->buttons
[nOldIndex
]));
2898 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
2901 /* FIXME: Send a WM_NOTIFY?? */
2908 TOOLBAR_CommandToIndex (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2910 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2912 return TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2917 TOOLBAR_Customize (HWND hwnd
)
2919 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2920 CUSTDLG_INFO custInfo
;
2926 custInfo
.tbInfo
= infoPtr
;
2927 custInfo
.tbHwnd
= hwnd
;
2929 /* send TBN_BEGINADJUST notification */
2930 TOOLBAR_SendNotify ((NMHDR
*) &nmhdr
, infoPtr
,
2933 if (!(hRes
= FindResourceA (COMCTL32_hModule
,
2934 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE
),
2938 if(!(template = (LPVOID
)LoadResource (COMCTL32_hModule
, hRes
)))
2941 ret
= DialogBoxIndirectParamA ((HINSTANCE
)GetWindowLongA(hwnd
, GWL_HINSTANCE
),
2942 (LPDLGTEMPLATEA
)template,
2944 TOOLBAR_CustomizeDialogProc
,
2947 /* send TBN_ENDADJUST notification */
2948 TOOLBAR_SendNotify ((NMHDR
*) &nmhdr
, infoPtr
,
2956 TOOLBAR_DeleteButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2958 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2959 INT nIndex
= (INT
)wParam
;
2961 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
2964 if ((infoPtr
->hwndToolTip
) &&
2965 !(infoPtr
->buttons
[nIndex
].fsStyle
& TBSTYLE_SEP
)) {
2968 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
2969 ti
.cbSize
= sizeof (TTTOOLINFOA
);
2971 ti
.uId
= infoPtr
->buttons
[nIndex
].idCommand
;
2973 SendMessageA (infoPtr
->hwndToolTip
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
2976 if (infoPtr
->nNumButtons
== 1) {
2977 TRACE(" simple delete!\n");
2978 Free (infoPtr
->buttons
);
2979 infoPtr
->buttons
= NULL
;
2980 infoPtr
->nNumButtons
= 0;
2983 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2984 TRACE("complex delete! [nIndex=%d]\n", nIndex
);
2986 infoPtr
->nNumButtons
--;
2987 infoPtr
->buttons
= Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
2989 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2990 nIndex
* sizeof(TBUTTON_INFO
));
2993 if (nIndex
< infoPtr
->nNumButtons
) {
2994 memcpy (&infoPtr
->buttons
[nIndex
], &oldButtons
[nIndex
+1],
2995 (infoPtr
->nNumButtons
- nIndex
) * sizeof(TBUTTON_INFO
));
3001 TOOLBAR_CalcToolbar (hwnd
);
3003 InvalidateRect (hwnd
, NULL
, TRUE
);
3010 TOOLBAR_EnableButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3012 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3013 TBUTTON_INFO
*btnPtr
;
3017 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3021 btnPtr
= &infoPtr
->buttons
[nIndex
];
3023 bState
= btnPtr
->fsState
& TBSTATE_ENABLED
;
3025 /* update the toolbar button state */
3026 if(LOWORD(lParam
) == FALSE
) {
3027 btnPtr
->fsState
&= ~(TBSTATE_ENABLED
| TBSTATE_PRESSED
);
3029 btnPtr
->fsState
|= TBSTATE_ENABLED
;
3032 /* redraw the button only if the state of the button changed */
3033 if(bState
!= (btnPtr
->fsState
& TBSTATE_ENABLED
))
3035 InvalidateRect(hwnd
, &btnPtr
->rect
,
3036 TOOLBAR_HasText(infoPtr
, btnPtr
));
3043 static inline LRESULT
3044 TOOLBAR_GetAnchorHighlight (HWND hwnd
)
3046 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3048 return infoPtr
->bAnchor
;
3053 TOOLBAR_GetBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3055 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3058 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3062 return infoPtr
->buttons
[nIndex
].iBitmap
;
3066 static inline LRESULT
3067 TOOLBAR_GetBitmapFlags (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3069 return (GetDeviceCaps (0, LOGPIXELSX
) >= 120) ? TBBF_LARGE
: 0;
3074 TOOLBAR_GetButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3076 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3077 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3078 INT nIndex
= (INT
)wParam
;
3079 TBUTTON_INFO
*btnPtr
;
3081 if (infoPtr
== NULL
)
3087 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3090 btnPtr
= &infoPtr
->buttons
[nIndex
];
3091 lpTbb
->iBitmap
= btnPtr
->iBitmap
;
3092 lpTbb
->idCommand
= btnPtr
->idCommand
;
3093 lpTbb
->fsState
= btnPtr
->fsState
;
3094 lpTbb
->fsStyle
= btnPtr
->fsStyle
;
3095 lpTbb
->bReserved
[0] = 0;
3096 lpTbb
->bReserved
[1] = 0;
3097 lpTbb
->dwData
= btnPtr
->dwData
;
3098 lpTbb
->iString
= btnPtr
->iString
;
3105 TOOLBAR_GetButtonInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3107 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3108 LPTBBUTTONINFOA lpTbInfo
= (LPTBBUTTONINFOA
)lParam
;
3109 TBUTTON_INFO
*btnPtr
;
3112 if (infoPtr
== NULL
)
3114 if (lpTbInfo
== NULL
)
3116 if (lpTbInfo
->cbSize
< sizeof(TBBUTTONINFOA
))
3119 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
3120 lpTbInfo
->dwMask
& 0x80000000);
3124 if (!(btnPtr
= &infoPtr
->buttons
[nIndex
])) return -1;
3126 if (lpTbInfo
->dwMask
& TBIF_COMMAND
)
3127 lpTbInfo
->idCommand
= btnPtr
->idCommand
;
3128 if (lpTbInfo
->dwMask
& TBIF_IMAGE
)
3129 lpTbInfo
->iImage
= btnPtr
->iBitmap
;
3130 if (lpTbInfo
->dwMask
& TBIF_LPARAM
)
3131 lpTbInfo
->lParam
= btnPtr
->dwData
;
3132 if (lpTbInfo
->dwMask
& TBIF_SIZE
)
3133 lpTbInfo
->cx
= (WORD
)(btnPtr
->rect
.right
- btnPtr
->rect
.left
);
3134 if (lpTbInfo
->dwMask
& TBIF_STATE
)
3135 lpTbInfo
->fsState
= btnPtr
->fsState
;
3136 if (lpTbInfo
->dwMask
& TBIF_STYLE
)
3137 lpTbInfo
->fsStyle
= btnPtr
->fsStyle
;
3138 if (lpTbInfo
->dwMask
& TBIF_TEXT
) {
3139 LPWSTR lpText
= TOOLBAR_GetText(infoPtr
,btnPtr
);
3140 Str_GetPtrWtoA (lpText
, lpTbInfo
->pszText
,lpTbInfo
->cchText
);
3147 TOOLBAR_GetButtonInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3149 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3150 LPTBBUTTONINFOW lpTbInfo
= (LPTBBUTTONINFOW
)lParam
;
3151 TBUTTON_INFO
*btnPtr
;
3154 if (infoPtr
== NULL
)
3156 if (lpTbInfo
== NULL
)
3158 if (lpTbInfo
->cbSize
< sizeof(TBBUTTONINFOW
))
3161 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
3162 lpTbInfo
->dwMask
& 0x80000000);
3166 btnPtr
= &infoPtr
->buttons
[nIndex
];
3171 if (lpTbInfo
->dwMask
& TBIF_COMMAND
)
3172 lpTbInfo
->idCommand
= btnPtr
->idCommand
;
3173 if (lpTbInfo
->dwMask
& TBIF_IMAGE
)
3174 lpTbInfo
->iImage
= btnPtr
->iBitmap
;
3175 if (lpTbInfo
->dwMask
& TBIF_LPARAM
)
3176 lpTbInfo
->lParam
= btnPtr
->dwData
;
3177 if (lpTbInfo
->dwMask
& TBIF_SIZE
)
3178 lpTbInfo
->cx
= (WORD
)(btnPtr
->rect
.right
- btnPtr
->rect
.left
);
3179 if (lpTbInfo
->dwMask
& TBIF_STATE
)
3180 lpTbInfo
->fsState
= btnPtr
->fsState
;
3181 if (lpTbInfo
->dwMask
& TBIF_STYLE
)
3182 lpTbInfo
->fsStyle
= btnPtr
->fsStyle
;
3183 if (lpTbInfo
->dwMask
& TBIF_TEXT
) {
3184 LPWSTR lpText
= TOOLBAR_GetText(infoPtr
,btnPtr
);
3185 Str_GetPtrW (lpText
,lpTbInfo
->pszText
,lpTbInfo
->cchText
);
3193 TOOLBAR_GetButtonSize (HWND hwnd
)
3195 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3197 if (infoPtr
->nNumButtons
> 0)
3198 return MAKELONG((WORD
)infoPtr
->nButtonWidth
,
3199 (WORD
)infoPtr
->nButtonHeight
);
3201 return MAKELONG(8,7);
3206 TOOLBAR_GetButtonTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3208 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3215 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3219 lpText
= TOOLBAR_GetText(infoPtr
,&infoPtr
->buttons
[nIndex
]);
3221 return WideCharToMultiByte( CP_ACP
, 0, lpText
, -1,
3222 (LPSTR
)lParam
, 0x7fffffff, NULL
, NULL
) - 1;
3227 TOOLBAR_GetButtonTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3229 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3236 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3240 lpText
= TOOLBAR_GetText(infoPtr
,&infoPtr
->buttons
[nIndex
]);
3242 strcpyW ((LPWSTR
)lParam
, lpText
);
3244 return strlenW (lpText
);
3249 TOOLBAR_GetDisabledImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3251 return (LRESULT
)GETDISIMAGELIST(TOOLBAR_GetInfoPtr (hwnd
), 0);
3255 inline static LRESULT
3256 TOOLBAR_GetExtendedStyle (HWND hwnd
)
3258 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3262 return infoPtr
->dwExStyle
;
3267 TOOLBAR_GetHotImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3269 return (LRESULT
)GETHOTIMAGELIST(TOOLBAR_GetInfoPtr (hwnd
), 0);
3274 TOOLBAR_GetHotItem (HWND hwnd
)
3276 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3278 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_FLAT
))
3281 if (infoPtr
->nHotItem
< 0)
3284 return (LRESULT
)infoPtr
->nHotItem
;
3289 TOOLBAR_GetDefImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3291 return (LRESULT
) GETDEFIMAGELIST(TOOLBAR_GetInfoPtr(hwnd
), 0);
3295 /* << TOOLBAR_GetInsertMark >> */
3296 /* << TOOLBAR_GetInsertMarkColor >> */
3300 TOOLBAR_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3302 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3303 TBUTTON_INFO
*btnPtr
;
3307 if (infoPtr
== NULL
)
3309 nIndex
= (INT
)wParam
;
3310 btnPtr
= &infoPtr
->buttons
[nIndex
];
3311 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3313 lpRect
= (LPRECT
)lParam
;
3316 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
3319 lpRect
->left
= btnPtr
->rect
.left
;
3320 lpRect
->right
= btnPtr
->rect
.right
;
3321 lpRect
->bottom
= btnPtr
->rect
.bottom
;
3322 lpRect
->top
= btnPtr
->rect
.top
;
3329 TOOLBAR_GetMaxSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3331 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3332 LPSIZE lpSize
= (LPSIZE
)lParam
;
3337 lpSize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
3338 lpSize
->cy
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
3340 TRACE("maximum size %ld x %ld\n",
3341 infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
,
3342 infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
);
3348 /* << TOOLBAR_GetObject >> */
3352 TOOLBAR_GetPadding (HWND hwnd
)
3354 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3357 oldPad
= MAKELONG(infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
3358 return (LRESULT
) oldPad
;
3363 TOOLBAR_GetRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3365 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3366 TBUTTON_INFO
*btnPtr
;
3370 if (infoPtr
== NULL
)
3372 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3373 btnPtr
= &infoPtr
->buttons
[nIndex
];
3374 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3376 lpRect
= (LPRECT
)lParam
;
3380 lpRect
->left
= btnPtr
->rect
.left
;
3381 lpRect
->right
= btnPtr
->rect
.right
;
3382 lpRect
->bottom
= btnPtr
->rect
.bottom
;
3383 lpRect
->top
= btnPtr
->rect
.top
;
3390 TOOLBAR_GetRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3392 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3394 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_WRAPABLE
)
3395 return infoPtr
->nRows
;
3402 TOOLBAR_GetState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3404 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3407 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3411 return infoPtr
->buttons
[nIndex
].fsState
;
3416 TOOLBAR_GetStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3418 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3421 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3425 return infoPtr
->buttons
[nIndex
].fsStyle
;
3430 TOOLBAR_GetTextRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3432 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3434 if (infoPtr
== NULL
)
3437 return infoPtr
->nMaxTextRows
;
3442 TOOLBAR_GetToolTips (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3444 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3446 if (infoPtr
== NULL
)
3448 return (LRESULT
)infoPtr
->hwndToolTip
;
3453 TOOLBAR_GetUnicodeFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3455 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3457 TRACE("%s hwnd=%p stub!\n",
3458 infoPtr
->bUnicode
? "TRUE" : "FALSE", hwnd
);
3460 return infoPtr
->bUnicode
;
3464 inline static LRESULT
3465 TOOLBAR_GetVersion (HWND hwnd
)
3467 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3468 return infoPtr
->iVersion
;
3473 TOOLBAR_HideButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3475 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3476 TBUTTON_INFO
*btnPtr
;
3481 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3485 btnPtr
= &infoPtr
->buttons
[nIndex
];
3486 if (LOWORD(lParam
) == FALSE
)
3487 btnPtr
->fsState
&= ~TBSTATE_HIDDEN
;
3489 btnPtr
->fsState
|= TBSTATE_HIDDEN
;
3491 TOOLBAR_CalcToolbar (hwnd
);
3493 InvalidateRect (hwnd
, NULL
, TRUE
);
3499 inline static LRESULT
3500 TOOLBAR_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3502 return TOOLBAR_InternalHitTest (hwnd
, (LPPOINT
)lParam
);
3507 TOOLBAR_Indeterminate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3509 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3510 TBUTTON_INFO
*btnPtr
;
3513 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3517 btnPtr
= &infoPtr
->buttons
[nIndex
];
3518 if (LOWORD(lParam
) == FALSE
)
3519 btnPtr
->fsState
&= ~TBSTATE_INDETERMINATE
;
3521 btnPtr
->fsState
|= TBSTATE_INDETERMINATE
;
3523 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
3530 TOOLBAR_InsertButtonA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3532 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3533 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3534 INT nIndex
= (INT
)wParam
;
3535 TBUTTON_INFO
*oldButtons
;
3540 TOOLBAR_DumpButton(infoPtr
, (TBUTTON_INFO
*)lpTbb
, nIndex
, FALSE
);
3543 /* EPP: this seems to be an undocumented call (from my IE4)
3544 * I assume in that case that:
3545 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3546 * - index of insertion is at the end of existing buttons
3547 * I only see this happen with nIndex == -1, but it could have a special
3548 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3550 nIndex
= infoPtr
->nNumButtons
;
3552 } else if (nIndex
< 0)
3555 /* If the string passed is not an index, assume address of string
3556 and do our own AddString */
3557 if ((HIWORD(lpTbb
->iString
) != 0) && (lpTbb
->iString
!= -1)) {
3561 TRACE("string %s passed instead of index, adding string\n",
3562 debugstr_a((LPSTR
)lpTbb
->iString
));
3563 len
= strlen((LPSTR
)lpTbb
->iString
) + 2;
3565 strcpy(ptr
, (LPSTR
)lpTbb
->iString
);
3566 ptr
[len
- 1] = 0; /* ended by two '\0' */
3567 lpTbb
->iString
= TOOLBAR_AddStringA(hwnd
, 0, (LPARAM
)ptr
);
3571 TRACE("inserting button index=%d\n", nIndex
);
3572 if (nIndex
> infoPtr
->nNumButtons
) {
3573 nIndex
= infoPtr
->nNumButtons
;
3574 TRACE("adjust index=%d\n", nIndex
);
3577 oldButtons
= infoPtr
->buttons
;
3578 infoPtr
->nNumButtons
++;
3579 infoPtr
->buttons
= Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
3580 /* pre insert copy */
3582 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
3583 nIndex
* sizeof(TBUTTON_INFO
));
3586 /* insert new button */
3587 infoPtr
->buttons
[nIndex
].iBitmap
= lpTbb
->iBitmap
;
3588 infoPtr
->buttons
[nIndex
].idCommand
= lpTbb
->idCommand
;
3589 infoPtr
->buttons
[nIndex
].fsState
= lpTbb
->fsState
;
3590 infoPtr
->buttons
[nIndex
].fsStyle
= lpTbb
->fsStyle
;
3591 infoPtr
->buttons
[nIndex
].dwData
= lpTbb
->dwData
;
3592 /* if passed string and not index, then add string */
3593 if(HIWORD(lpTbb
->iString
) && lpTbb
->iString
!=-1) {
3594 Str_SetPtrAtoW ((LPWSTR
*)&infoPtr
->buttons
[nIndex
].iString
, (LPCSTR
)lpTbb
->iString
);
3597 infoPtr
->buttons
[nIndex
].iString
= lpTbb
->iString
;
3599 if ((infoPtr
->hwndToolTip
) && !(lpTbb
->fsStyle
& TBSTYLE_SEP
)) {
3602 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
3603 ti
.cbSize
= sizeof (TTTOOLINFOA
);
3605 ti
.uId
= lpTbb
->idCommand
;
3607 ti
.lpszText
= LPSTR_TEXTCALLBACKA
;
3609 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
,
3613 /* post insert copy */
3614 if (nIndex
< infoPtr
->nNumButtons
- 1) {
3615 memcpy (&infoPtr
->buttons
[nIndex
+1], &oldButtons
[nIndex
],
3616 (infoPtr
->nNumButtons
- nIndex
- 1) * sizeof(TBUTTON_INFO
));
3621 TOOLBAR_CalcToolbar (hwnd
);
3623 InvalidateRect (hwnd
, NULL
, TRUE
);
3630 TOOLBAR_InsertButtonW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3632 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3633 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3634 INT nIndex
= (INT
)wParam
;
3635 TBUTTON_INFO
*oldButtons
;
3640 TOOLBAR_DumpButton(infoPtr
, (TBUTTON_INFO
*)lpTbb
, nIndex
, FALSE
);
3643 /* EPP: this seems to be an undocumented call (from my IE4)
3644 * I assume in that case that:
3645 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3646 * - index of insertion is at the end of existing buttons
3647 * I only see this happen with nIndex == -1, but it could have a special
3648 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3650 nIndex
= infoPtr
->nNumButtons
;
3652 } else if (nIndex
< 0)
3655 /* If the string passed is not an index, assume address of string
3656 and do our own AddString */
3657 if ((HIWORD(lpTbb
->iString
) != 0) && (lpTbb
->iString
!= -1)) {
3661 TRACE("string %s passed instead of index, adding string\n",
3662 debugstr_w((LPWSTR
)lpTbb
->iString
));
3663 len
= strlenW((LPWSTR
)lpTbb
->iString
) + 2;
3664 ptr
= Alloc(len
*sizeof(WCHAR
));
3665 strcpyW(ptr
, (LPWSTR
)lpTbb
->iString
);
3666 ptr
[len
- 1] = 0; /* ended by two '\0' */
3667 lpTbb
->iString
= TOOLBAR_AddStringW(hwnd
, 0, (LPARAM
)ptr
);
3671 TRACE("inserting button index=%d\n", nIndex
);
3672 if (nIndex
> infoPtr
->nNumButtons
) {
3673 nIndex
= infoPtr
->nNumButtons
;
3674 TRACE("adjust index=%d\n", nIndex
);
3677 oldButtons
= infoPtr
->buttons
;
3678 infoPtr
->nNumButtons
++;
3679 infoPtr
->buttons
= Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
3680 /* pre insert copy */
3682 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
3683 nIndex
* sizeof(TBUTTON_INFO
));
3686 /* insert new button */
3687 infoPtr
->buttons
[nIndex
].iBitmap
= lpTbb
->iBitmap
;
3688 infoPtr
->buttons
[nIndex
].idCommand
= lpTbb
->idCommand
;
3689 infoPtr
->buttons
[nIndex
].fsState
= lpTbb
->fsState
;
3690 infoPtr
->buttons
[nIndex
].fsStyle
= lpTbb
->fsStyle
;
3691 infoPtr
->buttons
[nIndex
].dwData
= lpTbb
->dwData
;
3692 /* if passed string and not index, then add string */
3693 if(HIWORD(lpTbb
->iString
) && lpTbb
->iString
!=-1) {
3694 Str_SetPtrW ((LPWSTR
*)&infoPtr
->buttons
[nIndex
].iString
, (LPWSTR
)lpTbb
->iString
);
3697 infoPtr
->buttons
[nIndex
].iString
= lpTbb
->iString
;
3699 if ((infoPtr
->hwndToolTip
) && !(lpTbb
->fsStyle
& TBSTYLE_SEP
)) {
3702 ZeroMemory (&ti
, sizeof(TTTOOLINFOW
));
3703 ti
.cbSize
= sizeof (TTTOOLINFOW
);
3705 ti
.uId
= lpTbb
->idCommand
;
3707 ti
.lpszText
= LPSTR_TEXTCALLBACKW
;
3709 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
,
3713 /* post insert copy */
3714 if (nIndex
< infoPtr
->nNumButtons
- 1) {
3715 memcpy (&infoPtr
->buttons
[nIndex
+1], &oldButtons
[nIndex
],
3716 (infoPtr
->nNumButtons
- nIndex
- 1) * sizeof(TBUTTON_INFO
));
3721 TOOLBAR_CalcToolbar (hwnd
);
3723 InvalidateRect (hwnd
, NULL
, TRUE
);
3729 /* << TOOLBAR_InsertMarkHitTest >> */
3733 TOOLBAR_IsButtonChecked (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3735 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3738 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3742 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_CHECKED
);
3747 TOOLBAR_IsButtonEnabled (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3749 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3752 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3756 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_ENABLED
);
3761 TOOLBAR_IsButtonHidden (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3763 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3766 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3770 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_HIDDEN
);
3775 TOOLBAR_IsButtonHighlighted (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3777 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3780 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3784 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_MARKED
);
3789 TOOLBAR_IsButtonIndeterminate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3791 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3794 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3798 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_INDETERMINATE
);
3803 TOOLBAR_IsButtonPressed (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3805 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3808 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3812 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_PRESSED
);
3816 /* << TOOLBAR_LoadImages >> */
3817 /* << TOOLBAR_MapAccelerator >> */
3818 /* << TOOLBAR_MarkButton >> */
3819 /* << TOOLBAR_MoveButton >> */
3823 TOOLBAR_PressButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3825 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3826 TBUTTON_INFO
*btnPtr
;
3829 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3833 btnPtr
= &infoPtr
->buttons
[nIndex
];
3834 if (LOWORD(lParam
) == FALSE
)
3835 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
3837 btnPtr
->fsState
|= TBSTATE_PRESSED
;
3839 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
3844 /* FIXME: there might still be some confusion her between number of buttons
3845 * and number of bitmaps */
3847 TOOLBAR_ReplaceBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3849 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3850 LPTBREPLACEBITMAP lpReplace
= (LPTBREPLACEBITMAP
) lParam
;
3852 int i
= 0, nOldButtons
= 0, pos
= 0;
3853 int nOldBitmaps
, nNewBitmaps
;
3854 HIMAGELIST himlDef
= 0;
3856 TRACE("hInstOld %p nIDOld %x hInstNew %p nIDNew %x nButtons %x\n",
3857 lpReplace
->hInstOld
, lpReplace
->nIDOld
, lpReplace
->hInstNew
, lpReplace
->nIDNew
,
3858 lpReplace
->nButtons
);
3860 if (lpReplace
->hInstOld
== HINST_COMMCTRL
)
3862 FIXME("changing standard bitmaps not implemented\n");
3865 else if (lpReplace
->hInstOld
!= 0)
3867 FIXME("resources not in the current module not implemented\n");
3872 hBitmap
= (HBITMAP
) lpReplace
->nIDNew
;
3875 TRACE("To be replaced hInstOld %p nIDOld %x\n", lpReplace
->hInstOld
, lpReplace
->nIDOld
);
3876 for (i
= 0; i
< infoPtr
->nNumBitmapInfos
; i
++) {
3877 TBITMAP_INFO
*tbi
= &infoPtr
->bitmaps
[i
];
3878 TRACE("tbimapinfo %d hInstOld %p nIDOld %x\n", i
, tbi
->hInst
, tbi
->nID
);
3879 if (tbi
->hInst
== lpReplace
->hInstOld
&& tbi
->nID
== lpReplace
->nIDOld
)
3881 TRACE("Found: nButtons %d hInst %p nID %x\n", tbi
->nButtons
, tbi
->hInst
, tbi
->nID
);
3882 nOldButtons
= tbi
->nButtons
;
3883 tbi
->nButtons
= lpReplace
->nButtons
;
3884 tbi
->hInst
= lpReplace
->hInstNew
;
3885 tbi
->nID
= lpReplace
->nIDNew
;
3886 TRACE("tbimapinfo changed %d hInstOld %p nIDOld %x\n", i
, tbi
->hInst
, tbi
->nID
);
3889 pos
+= tbi
->nButtons
;
3892 if (nOldButtons
== 0)
3894 WARN("No hinst/bitmap found! hInst %p nID %x\n", lpReplace
->hInstOld
, lpReplace
->nIDOld
);
3898 himlDef
= GETDEFIMAGELIST(infoPtr
, 0); /* fixme: correct? */
3899 nOldBitmaps
= ImageList_GetImageCount(himlDef
);
3901 /* ImageList_Replace(GETDEFIMAGELIST(), pos, hBitmap, NULL); */
3903 for (i
= pos
+ nOldBitmaps
- 1; i
>= pos
; i
--)
3904 ImageList_Remove(himlDef
, i
);
3908 HBITMAP hOldBitmapBitmap
, hOldBitmapLoad
, hbmLoad
;
3909 HDC hdcImage
, hdcBitmap
;
3911 /* copy the bitmap before adding it so that the user's bitmap
3912 * doesn't get modified.
3914 GetObjectA (hBitmap
, sizeof(BITMAP
), (LPVOID
)&bmp
);
3916 hdcImage
= CreateCompatibleDC(0);
3917 hdcBitmap
= CreateCompatibleDC(0);
3919 /* create new bitmap */
3920 hbmLoad
= CreateBitmap (bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
, bmp
.bmBitsPixel
, NULL
);
3921 hOldBitmapBitmap
= SelectObject(hdcBitmap
, hBitmap
);
3922 hOldBitmapLoad
= SelectObject(hdcImage
, hbmLoad
);
3924 /* Copy the user's image */
3925 BitBlt (hdcImage
, 0, 0, bmp
.bmWidth
, bmp
.bmHeight
,
3926 hdcBitmap
, 0, 0, SRCCOPY
);
3928 SelectObject (hdcImage
, hOldBitmapLoad
);
3929 SelectObject (hdcBitmap
, hOldBitmapBitmap
);
3930 DeleteDC (hdcImage
);
3931 DeleteDC (hdcBitmap
);
3933 ImageList_AddMasked (himlDef
, hbmLoad
, comctl32_color
.clrBtnFace
);
3934 nNewBitmaps
= ImageList_GetImageCount(himlDef
);
3935 DeleteObject (hbmLoad
);
3938 infoPtr
->nNumBitmaps
= infoPtr
->nNumBitmaps
- nOldBitmaps
+ nNewBitmaps
;
3940 TRACE(" pos %d %d old bitmaps replaced by %d new ones.\n",
3941 pos
, nOldBitmaps
, nNewBitmaps
);
3943 InvalidateRect(hwnd
, NULL
, FALSE
);
3949 TOOLBAR_SaveRestoreA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3952 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3953 LPTBSAVEPARAMSA lpSave
= (LPTBSAVEPARAMSA
)lParam
;
3955 if (lpSave
== NULL
) return 0;
3958 /* save toolbar information */
3959 FIXME("save to \"%s\" \"%s\"\n",
3960 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3965 /* restore toolbar information */
3967 FIXME("restore from \"%s\" \"%s\"\n",
3968 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3979 TOOLBAR_SaveRestoreW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3982 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3983 LPTBSAVEPARAMSW lpSave
= (LPTBSAVEPARAMSW
)lParam
;
3989 /* save toolbar information */
3990 FIXME("save to \"%s\" \"%s\"\n",
3991 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3996 /* restore toolbar information */
3998 FIXME("restore from \"%s\" \"%s\"\n",
3999 lpSave
->pszSubKey
, lpSave
->pszValueName
);
4010 TOOLBAR_SetAnchorHighlight (HWND hwnd
, WPARAM wParam
)
4012 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4013 BOOL bOldAnchor
= infoPtr
->bAnchor
;
4015 infoPtr
->bAnchor
= (BOOL
)wParam
;
4017 return (LRESULT
)bOldAnchor
;
4022 TOOLBAR_SetBitmapSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4024 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4025 HIMAGELIST himlDef
= GETDEFIMAGELIST(infoPtr
, 0);
4027 if ((LOWORD(lParam
) <= 0) || (HIWORD(lParam
)<=0))
4030 if (infoPtr
->nNumButtons
> 0)
4031 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
4032 infoPtr
->nNumButtons
,
4033 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
,
4034 LOWORD(lParam
), HIWORD(lParam
));
4036 infoPtr
->nBitmapWidth
= (INT
)LOWORD(lParam
);
4037 infoPtr
->nBitmapHeight
= (INT
)HIWORD(lParam
);
4040 /* uses image list internals directly */
4042 himlDef
->cx
= infoPtr
->nBitmapWidth
;
4043 himlDef
->cy
= infoPtr
->nBitmapHeight
;
4051 TOOLBAR_SetButtonInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4053 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4054 LPTBBUTTONINFOA lptbbi
= (LPTBBUTTONINFOA
)lParam
;
4055 TBUTTON_INFO
*btnPtr
;
4060 if (lptbbi
->cbSize
< sizeof(TBBUTTONINFOA
))
4063 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
4064 lptbbi
->dwMask
& 0x80000000);
4068 btnPtr
= &infoPtr
->buttons
[nIndex
];
4069 if (lptbbi
->dwMask
& TBIF_COMMAND
)
4070 btnPtr
->idCommand
= lptbbi
->idCommand
;
4071 if (lptbbi
->dwMask
& TBIF_IMAGE
)
4072 btnPtr
->iBitmap
= lptbbi
->iImage
;
4073 if (lptbbi
->dwMask
& TBIF_LPARAM
)
4074 btnPtr
->dwData
= lptbbi
->lParam
;
4075 /* if (lptbbi->dwMask & TBIF_SIZE) */
4076 /* btnPtr->cx = lptbbi->cx; */
4077 if (lptbbi
->dwMask
& TBIF_STATE
)
4078 btnPtr
->fsState
= lptbbi
->fsState
;
4079 if (lptbbi
->dwMask
& TBIF_STYLE
)
4080 btnPtr
->fsStyle
= lptbbi
->fsStyle
;
4082 if ((lptbbi
->dwMask
& TBIF_TEXT
) && ((INT
)lptbbi
->pszText
!= -1)) {
4083 if ((HIWORD(btnPtr
->iString
) == 0) || (btnPtr
->iString
== -1))
4084 /* iString is index, zero it to make Str_SetPtr succeed */
4087 Str_SetPtrAtoW ((LPWSTR
*)&btnPtr
->iString
, lptbbi
->pszText
);
4094 TOOLBAR_SetButtonInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4096 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4097 LPTBBUTTONINFOW lptbbi
= (LPTBBUTTONINFOW
)lParam
;
4098 TBUTTON_INFO
*btnPtr
;
4103 if (lptbbi
->cbSize
< sizeof(TBBUTTONINFOW
))
4106 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
4107 lptbbi
->dwMask
& 0x80000000);
4111 btnPtr
= &infoPtr
->buttons
[nIndex
];
4112 if (lptbbi
->dwMask
& TBIF_COMMAND
)
4113 btnPtr
->idCommand
= lptbbi
->idCommand
;
4114 if (lptbbi
->dwMask
& TBIF_IMAGE
)
4115 btnPtr
->iBitmap
= lptbbi
->iImage
;
4116 if (lptbbi
->dwMask
& TBIF_LPARAM
)
4117 btnPtr
->dwData
= lptbbi
->lParam
;
4118 /* if (lptbbi->dwMask & TBIF_SIZE) */
4119 /* btnPtr->cx = lptbbi->cx; */
4120 if (lptbbi
->dwMask
& TBIF_STATE
)
4121 btnPtr
->fsState
= lptbbi
->fsState
;
4122 if (lptbbi
->dwMask
& TBIF_STYLE
)
4123 btnPtr
->fsStyle
= lptbbi
->fsStyle
;
4125 if ((lptbbi
->dwMask
& TBIF_TEXT
) && ((INT
)lptbbi
->pszText
!= -1)) {
4126 if ((HIWORD(btnPtr
->iString
) == 0) || (btnPtr
->iString
== -1))
4127 /* iString is index, zero it to make Str_SetPtr succeed */
4129 Str_SetPtrW ((LPWSTR
*)&btnPtr
->iString
, lptbbi
->pszText
);
4136 TOOLBAR_SetButtonSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4138 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4139 INT cx
= LOWORD(lParam
), cy
= HIWORD(lParam
);
4141 if ((cx
< 0) || (cy
< 0))
4143 ERR("invalid parameter 0x%08lx\n", (DWORD
)lParam
);
4147 /* The documentation claims you can only change the button size before
4148 * any button has been added. But this is wrong.
4149 * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding
4150 * it to the toolbar, and it checks that the return value is nonzero - mjm
4151 * Further testing shows that we must actually perform the change too.
4154 * The documentation also does not mention that if 0 is supplied for
4155 * either size, the system changes it to the default of 24 wide and
4156 * 22 high. Demonstarted in ControlSpy Toolbar. GLA 3/02
4158 infoPtr
->nButtonWidth
= (cx
) ? cx
: 24;
4159 infoPtr
->nButtonHeight
= (cy
) ? cy
: 22;
4165 TOOLBAR_SetButtonWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4167 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4169 if (infoPtr
== NULL
) {
4170 TRACE("Toolbar not initialized yet?????\n");
4174 /* if setting to current values, ignore */
4175 if ((infoPtr
->cxMin
== (INT
)LOWORD(lParam
)) &&
4176 (infoPtr
->cxMax
== (INT
)HIWORD(lParam
))) {
4177 TRACE("matches current width, min=%d, max=%d, no recalc\n",
4178 infoPtr
->cxMin
, infoPtr
->cxMax
);
4182 /* save new values */
4183 infoPtr
->cxMin
= (INT
)LOWORD(lParam
);
4184 infoPtr
->cxMax
= (INT
)HIWORD(lParam
);
4186 /* if both values are 0 then we are done */
4188 TRACE("setting both min and max to 0, norecalc\n");
4192 /* otherwise we need to recalc the toolbar and in some cases
4193 recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
4194 which doesn't actually draw - GA). */
4195 TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n",
4196 infoPtr
->nNumButtons
, infoPtr
->cxMin
, infoPtr
->cxMax
);
4198 TOOLBAR_CalcToolbar (hwnd
);
4200 InvalidateRect (hwnd
, NULL
, TRUE
);
4207 TOOLBAR_SetCmdId (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4209 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4210 INT nIndex
= (INT
)wParam
;
4212 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
4215 infoPtr
->buttons
[nIndex
].idCommand
= (INT
)lParam
;
4217 if (infoPtr
->hwndToolTip
) {
4219 FIXME("change tool tip!\n");
4228 TOOLBAR_SetDisabledImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4230 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4231 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4232 HIMAGELIST himlTemp
;
4235 if (infoPtr
->iVersion
>= 5)
4238 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlDis
,
4239 &infoPtr
->cimlDis
, himl
, id
);
4241 /* FIXME: redraw ? */
4243 return (LRESULT
)himlTemp
;
4248 TOOLBAR_SetDrawTextFlags (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4250 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4253 dwTemp
= infoPtr
->dwDTFlags
;
4254 infoPtr
->dwDTFlags
=
4255 (infoPtr
->dwDTFlags
& (DWORD
)wParam
) | (DWORD
)lParam
;
4257 return (LRESULT
)dwTemp
;
4261 TOOLBAR_SetExtendedStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4263 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4266 dwTemp
= infoPtr
->dwExStyle
;
4267 infoPtr
->dwExStyle
|= (DWORD
)lParam
;
4269 TRACE("new style 0x%08lx\n", infoPtr
->dwExStyle
);
4271 if (infoPtr
->dwExStyle
& ~TBSTYLE_EX_ALL
)
4272 FIXME("Unknown Toolbar Extended Style 0x%08lx. Please report.\n",
4273 (infoPtr
->dwExStyle
& ~TBSTYLE_EX_ALL
));
4275 TOOLBAR_CalcToolbar (hwnd
);
4277 TOOLBAR_AutoSize(hwnd
);
4279 InvalidateRect(hwnd
, NULL
, FALSE
);
4281 return (LRESULT
)dwTemp
;
4286 TOOLBAR_SetHotImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4288 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4289 HIMAGELIST himlTemp
;
4290 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4293 if (infoPtr
->iVersion
>= 5)
4296 TRACE("hwnd = %p, himl = %p, id = %d\n", hwnd
, himl
, id
);
4298 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlHot
,
4299 &infoPtr
->cimlHot
, himl
, id
);
4301 /* FIXME: redraw ? */
4303 return (LRESULT
)himlTemp
;
4308 TOOLBAR_SetHotItem (HWND hwnd
, WPARAM wParam
)
4310 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4311 INT nOldHotItem
= infoPtr
->nHotItem
;
4312 TBUTTON_INFO
*btnPtr
;
4314 if ((INT
) wParam
< 0 || (INT
)wParam
> infoPtr
->nNumButtons
)
4317 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_FLAT
)
4320 infoPtr
->nHotItem
= (INT
)wParam
;
4321 if ((INT
)wParam
>=0)
4323 btnPtr
= &infoPtr
->buttons
[(INT
)wParam
];
4324 btnPtr
->bHot
= TRUE
;
4325 InvalidateRect (hwnd
, &btnPtr
->rect
,
4326 TOOLBAR_HasText(infoPtr
, btnPtr
));
4330 btnPtr
= &infoPtr
->buttons
[nOldHotItem
];
4331 btnPtr
->bHot
= FALSE
;
4332 InvalidateRect (hwnd
, &btnPtr
->rect
,
4333 TOOLBAR_HasText(infoPtr
, btnPtr
));
4337 if (nOldHotItem
< 0)
4340 return (LRESULT
)nOldHotItem
;
4345 TOOLBAR_SetImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4347 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4348 HIMAGELIST himlTemp
;
4349 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4352 if (infoPtr
->iVersion
>= 5)
4355 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlDef
,
4356 &infoPtr
->cimlDef
, himl
, id
);
4358 infoPtr
->nNumBitmaps
= 0;
4359 for (i
= 0; i
< infoPtr
->cimlDef
; i
++)
4360 infoPtr
->nNumBitmaps
+= ImageList_GetImageCount(infoPtr
->himlDef
[i
]->himl
);
4362 ImageList_GetIconSize(himl
, &infoPtr
->nBitmapWidth
,
4363 &infoPtr
->nBitmapHeight
);
4364 TRACE("hwnd %p, new himl=%08x, count=%d, bitmap w=%d, h=%d\n",
4365 hwnd
, (INT
)infoPtr
->himlDef
, infoPtr
->nNumBitmaps
,
4366 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
4368 /* FIXME: redraw ? */
4369 InvalidateRect(hwnd
, NULL
, TRUE
);
4371 return (LRESULT
)himlTemp
;
4376 TOOLBAR_SetIndent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4378 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4380 infoPtr
->nIndent
= (INT
)wParam
;
4384 /* process only on indent changing */
4385 if(infoPtr
->nIndent
!= (INT
)wParam
)
4387 infoPtr
->nIndent
= (INT
)wParam
;
4388 TOOLBAR_CalcToolbar (hwnd
);
4389 InvalidateRect(hwnd
, NULL
, FALSE
);
4396 /* << TOOLBAR_SetInsertMark >> */
4400 TOOLBAR_SetInsertMarkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4402 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4404 infoPtr
->clrInsertMark
= (COLORREF
)lParam
;
4406 /* FIXME : redraw ??*/
4413 TOOLBAR_SetMaxTextRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4415 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4417 if (infoPtr
== NULL
)
4420 infoPtr
->nMaxTextRows
= (INT
)wParam
;
4427 TOOLBAR_SetPadding (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4429 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4432 oldPad
= MAKELONG(infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
4433 infoPtr
->szPadding
.cx
= LOWORD((DWORD
)lParam
);
4434 infoPtr
->szPadding
.cy
= HIWORD((DWORD
)lParam
);
4435 FIXME("stub - nothing done with values, cx=%ld, cy=%ld\n",
4436 infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
4437 return (LRESULT
) oldPad
;
4442 TOOLBAR_SetParent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4444 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4449 if (infoPtr
== NULL
)
4451 hwndOldNotify
= infoPtr
->hwndNotify
;
4452 infoPtr
->hwndNotify
= (HWND
)wParam
;
4454 return (LRESULT
)hwndOldNotify
;
4459 TOOLBAR_SetRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4461 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4462 LPRECT lprc
= (LPRECT
)lParam
;
4466 if (LOWORD(wParam
) > 1) {
4467 FIXME("multiple rows not supported!\n");
4470 if(infoPtr
->nRows
!= LOWORD(wParam
))
4472 infoPtr
->nRows
= LOWORD(wParam
);
4474 /* recalculate toolbar */
4475 TOOLBAR_CalcToolbar (hwnd
);
4477 /* repaint toolbar */
4478 InvalidateRect(hwnd
, NULL
, FALSE
);
4481 /* return bounding rectangle */
4483 lprc
->left
= infoPtr
->rcBound
.left
;
4484 lprc
->right
= infoPtr
->rcBound
.right
;
4485 lprc
->top
= infoPtr
->rcBound
.top
;
4486 lprc
->bottom
= infoPtr
->rcBound
.bottom
;
4494 TOOLBAR_SetState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4496 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4497 TBUTTON_INFO
*btnPtr
;
4500 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
4504 btnPtr
= &infoPtr
->buttons
[nIndex
];
4506 /* if hidden state has changed the invalidate entire window and recalc */
4507 if ((btnPtr
->fsState
& TBSTATE_HIDDEN
) != (LOWORD(lParam
) & TBSTATE_HIDDEN
)) {
4508 btnPtr
->fsState
= LOWORD(lParam
);
4509 TOOLBAR_CalcToolbar (hwnd
);
4510 InvalidateRect(hwnd
, 0, TOOLBAR_HasText(infoPtr
, btnPtr
));
4514 /* process state changing if current state doesn't match new state */
4515 if(btnPtr
->fsState
!= LOWORD(lParam
))
4517 btnPtr
->fsState
= LOWORD(lParam
);
4518 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
4527 TOOLBAR_SetStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4529 SetWindowLongW(hwnd
, GWL_STYLE
, lParam
);
4535 inline static LRESULT
4536 TOOLBAR_SetToolTips (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4538 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4540 if (infoPtr
== NULL
)
4542 infoPtr
->hwndToolTip
= (HWND
)wParam
;
4548 TOOLBAR_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4550 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4553 TRACE("%s hwnd=%p stub!\n",
4554 ((BOOL
)wParam
) ? "TRUE" : "FALSE", hwnd
);
4556 bTemp
= infoPtr
->bUnicode
;
4557 infoPtr
->bUnicode
= (BOOL
)wParam
;
4564 TOOLBAR_GetColorScheme (HWND hwnd
, LPCOLORSCHEME lParam
)
4566 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4568 lParam
->clrBtnHighlight
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
4569 comctl32_color
.clrBtnHighlight
:
4570 infoPtr
->clrBtnHighlight
;
4571 lParam
->clrBtnShadow
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
4572 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
4578 TOOLBAR_SetColorScheme (HWND hwnd
, LPCOLORSCHEME lParam
)
4580 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4582 TRACE("new colors Hl=%lx Shd=%lx, old colors Hl=%lx Shd=%lx\n",
4583 lParam
->clrBtnHighlight
, lParam
->clrBtnShadow
,
4584 infoPtr
->clrBtnHighlight
, infoPtr
->clrBtnShadow
);
4586 infoPtr
->clrBtnHighlight
= lParam
->clrBtnHighlight
;
4587 infoPtr
->clrBtnShadow
= lParam
->clrBtnShadow
;
4588 InvalidateRect(hwnd
, 0, 0);
4594 TOOLBAR_SetVersion (HWND hwnd
, INT iVersion
)
4596 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4597 INT iOldVersion
= infoPtr
->iVersion
;
4599 infoPtr
->iVersion
= iVersion
;
4601 if (infoPtr
->iVersion
>= 5)
4602 TOOLBAR_SetUnicodeFormat(hwnd
, (WPARAM
)TRUE
, (LPARAM
)0);
4608 /*********************************************************************/
4610 /* This is undocumented and appears to be a "Super" TB_SETHOTITEM */
4611 /* without the restriction of TBSTYLE_FLAT. This implementation is */
4612 /* based on relay traces of the native control and IE 5.5 */
4614 /*********************************************************************/
4616 TOOLBAR_Unkwn45E (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4618 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4619 INT nOldHotItem
= infoPtr
->nHotItem
;
4620 TBUTTON_INFO
*btnPtr
;
4622 NMTBHOTITEM nmhotitem
;
4624 if ((INT
) wParam
< 0 || (INT
)wParam
> infoPtr
->nNumButtons
)
4627 infoPtr
->nHotItem
= (INT
)wParam
;
4628 if (nOldHotItem
!= infoPtr
->nHotItem
) {
4629 nmhotitem
.dwFlags
= (DWORD
)lParam
;
4630 if ( !(nmhotitem
.dwFlags
& HICF_ENTERING
) )
4631 nmhotitem
.idOld
= (nOldHotItem
>= 0) ?
4632 infoPtr
->buttons
[nOldHotItem
].idCommand
: 0;
4633 if ( !(nmhotitem
.dwFlags
& HICF_LEAVING
) )
4634 nmhotitem
.idNew
= (infoPtr
->nHotItem
>= 0) ?
4635 infoPtr
->buttons
[infoPtr
->nHotItem
].idCommand
: 0;
4636 no_hi
= TOOLBAR_SendNotify((NMHDR
*)&nmhotitem
, infoPtr
, TBN_HOTITEMCHANGE
);
4638 if ((INT
)wParam
>=0) {
4639 btnPtr
= &infoPtr
->buttons
[(INT
)wParam
];
4640 btnPtr
->bHot
= (no_hi
) ? FALSE
: TRUE
;
4641 InvalidateRect (hwnd
, &btnPtr
->rect
,
4642 TOOLBAR_HasText(infoPtr
, btnPtr
));
4644 if (nOldHotItem
>=0) {
4645 btnPtr
= &infoPtr
->buttons
[nOldHotItem
];
4646 btnPtr
->bHot
= FALSE
;
4647 InvalidateRect (hwnd
, &btnPtr
->rect
,
4648 TOOLBAR_HasText(infoPtr
, btnPtr
));
4651 TRACE("old item=%d, new item=%d, flags=%08lx, notify=%d\n",
4652 nOldHotItem
, infoPtr
->nHotItem
, (DWORD
)lParam
, no_hi
);
4654 if (nOldHotItem
< 0)
4657 return (LRESULT
)nOldHotItem
;
4662 TOOLBAR_Unkwn463 (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4664 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4665 LPSIZE lpsize
= (LPSIZE
)lParam
;
4671 * Testing shows the following:
4672 * wParam = 0 adjust cx value
4673 * = 1 set cy value to max size.
4674 * lParam pointer to SIZE structure
4677 TRACE("[0463] wParam %d, lParam 0x%08lx -> 0x%08lx 0x%08lx\n",
4678 wParam
, lParam
, lpsize
->cx
, lpsize
->cy
);
4682 if (lpsize
->cx
== -1) {
4683 /* **** this is wrong, native measures each button and sets it */
4684 lpsize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
4686 else if(HIWORD(lpsize
->cx
)) {
4688 HWND hwndParent
= GetParent(hwnd
);
4690 InvalidateRect(hwnd
, 0, 1);
4691 GetWindowRect(hwnd
, &rc
);
4692 MapWindowPoints(0, hwndParent
, (LPPOINT
)&rc
, 2);
4693 TRACE("mapped to (%ld,%ld)-(%ld,%ld)\n",
4694 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4695 lpsize
->cx
= max(rc
.right
-rc
.left
,
4696 infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
);
4699 lpsize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
4703 lpsize
->cy
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
4704 /* lpsize->cy = infoPtr->nHeight; */
4707 ERR("Unknown wParam %d for Toolbar message [0463]. Please report\n",
4711 TRACE("[0463] set to -> 0x%08lx 0x%08lx\n",
4712 lpsize
->cx
, lpsize
->cy
);
4718 TOOLBAR_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4720 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4721 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
4724 /* initialize info structure */
4725 infoPtr
->nButtonHeight
= 22;
4726 infoPtr
->nButtonWidth
= 24;
4727 infoPtr
->nBitmapHeight
= 15;
4728 infoPtr
->nBitmapWidth
= 16;
4730 infoPtr
->nHeight
= infoPtr
->nButtonHeight
+ TOP_BORDER
+ BOTTOM_BORDER
;
4731 infoPtr
->nMaxTextRows
= 1;
4732 infoPtr
->cxMin
= -1;
4733 infoPtr
->cxMax
= -1;
4734 infoPtr
->nNumBitmaps
= 0;
4735 infoPtr
->nNumStrings
= 0;
4737 infoPtr
->bCaptured
= FALSE
;
4738 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
4739 infoPtr
->nButtonDown
= -1;
4740 infoPtr
->nOldHit
= -1;
4741 infoPtr
->nHotItem
= -2; /* It has to be initially different from nOldHit */
4742 infoPtr
->hwndNotify
= ((LPCREATESTRUCTW
)lParam
)->hwndParent
;
4743 infoPtr
->bTransparent
= (dwStyle
& TBSTYLE_TRANSPARENT
);
4744 infoPtr
->bBtnTranspnt
= (dwStyle
& (TBSTYLE_FLAT
| TBSTYLE_LIST
));
4745 infoPtr
->dwDTFlags
= (dwStyle
& TBSTYLE_LIST
) ? DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
: DT_CENTER
;
4746 infoPtr
->bAnchor
= FALSE
; /* no anchor highlighting */
4747 infoPtr
->iVersion
= 0;
4748 infoPtr
->hwndSelf
= hwnd
;
4749 infoPtr
->bDoRedraw
= TRUE
;
4750 infoPtr
->clrBtnHighlight
= CLR_DEFAULT
;
4751 infoPtr
->clrBtnShadow
= CLR_DEFAULT
;
4752 infoPtr
->szPadding
.cx
= 7;
4753 infoPtr
->szPadding
.cy
= 6;
4754 TOOLBAR_NotifyFormat(infoPtr
, (WPARAM
)hwnd
, (LPARAM
)NF_REQUERY
);
4756 SystemParametersInfoA (SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0);
4757 infoPtr
->hFont
= infoPtr
->hDefaultFont
= CreateFontIndirectA (&logFont
);
4759 if (dwStyle
& TBSTYLE_TOOLTIPS
) {
4760 /* Create tooltip control */
4761 infoPtr
->hwndToolTip
=
4762 CreateWindowExA (0, TOOLTIPS_CLASSA
, NULL
, 0,
4763 CW_USEDEFAULT
, CW_USEDEFAULT
,
4764 CW_USEDEFAULT
, CW_USEDEFAULT
,
4767 /* Send NM_TOOLTIPSCREATED notification */
4768 if (infoPtr
->hwndToolTip
) {
4769 NMTOOLTIPSCREATED nmttc
;
4771 nmttc
.hwndToolTips
= infoPtr
->hwndToolTip
;
4773 TOOLBAR_SendNotify ((NMHDR
*) &nmttc
, infoPtr
,
4774 NM_TOOLTIPSCREATED
);
4778 TOOLBAR_CheckStyle (hwnd
, dwStyle
);
4780 TOOLBAR_CalcToolbar(hwnd
);
4787 TOOLBAR_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4789 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4791 /* delete tooltip control */
4792 if (infoPtr
->hwndToolTip
)
4793 DestroyWindow (infoPtr
->hwndToolTip
);
4795 /* delete button data */
4796 if (infoPtr
->buttons
)
4797 Free (infoPtr
->buttons
);
4799 /* delete strings */
4800 if (infoPtr
->strings
) {
4802 for (i
= 0; i
< infoPtr
->nNumStrings
; i
++)
4803 if (infoPtr
->strings
[i
])
4804 Free (infoPtr
->strings
[i
]);
4806 Free (infoPtr
->strings
);
4809 /* destroy internal image list */
4810 if (infoPtr
->himlInt
)
4811 ImageList_Destroy (infoPtr
->himlInt
);
4813 TOOLBAR_DeleteImageList(&infoPtr
->himlDef
, &infoPtr
->cimlDef
);
4814 TOOLBAR_DeleteImageList(&infoPtr
->himlDis
, &infoPtr
->cimlDis
);
4815 TOOLBAR_DeleteImageList(&infoPtr
->himlHot
, &infoPtr
->cimlHot
);
4817 /* delete default font */
4819 DeleteObject (infoPtr
->hDefaultFont
);
4821 /* free toolbar info data */
4823 SetWindowLongA (hwnd
, 0, 0);
4830 TOOLBAR_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4832 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4833 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
4834 NMTBCUSTOMDRAW tbcd
;
4838 if (dwStyle
& TBSTYLE_CUSTOMERASE
) {
4839 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
4840 tbcd
.nmcd
.dwDrawStage
= CDDS_PREERASE
;
4841 tbcd
.nmcd
.hdc
= (HDC
)wParam
;
4842 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
4843 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
4845 /* FIXME: in general the return flags *can* be or'ed together */
4846 switch (infoPtr
->dwBaseCustDraw
)
4848 case CDRF_DODEFAULT
:
4850 case CDRF_SKIPDEFAULT
:
4853 FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4858 /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up
4859 * to my parent for processing.
4861 if (infoPtr
->bTransparent
) {
4863 HDC hdc
= (HDC
)wParam
;
4868 parent
= GetParent(hwnd
);
4869 MapWindowPoints(hwnd
, parent
, &pt
, 1);
4870 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
4871 ret
= SendMessageA (parent
, WM_ERASEBKGND
, wParam
, lParam
);
4872 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
4875 ret
= DefWindowProcA (hwnd
, WM_ERASEBKGND
, wParam
, lParam
);
4877 if ((dwStyle
& TBSTYLE_CUSTOMERASE
) &&
4878 (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYPOSTERASE
)) {
4879 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
4880 tbcd
.nmcd
.dwDrawStage
= CDDS_POSTERASE
;
4881 tbcd
.nmcd
.hdc
= (HDC
)wParam
;
4882 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
4883 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
4884 switch (infoPtr
->dwBaseCustDraw
)
4886 case CDRF_DODEFAULT
:
4888 case CDRF_SKIPDEFAULT
:
4891 FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4900 TOOLBAR_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4902 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4904 return (LRESULT
)infoPtr
->hFont
;
4909 TOOLBAR_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4911 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4912 TBUTTON_INFO
*btnPtr
;
4916 pt
.x
= (INT
)LOWORD(lParam
);
4917 pt
.y
= (INT
)HIWORD(lParam
);
4918 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
4921 btnPtr
= &infoPtr
->buttons
[nHit
];
4922 if (!(btnPtr
->fsState
& TBSTATE_ENABLED
))
4925 infoPtr
->bCaptured
= TRUE
;
4926 infoPtr
->nButtonDown
= nHit
;
4928 btnPtr
->fsState
|= TBSTATE_PRESSED
;
4930 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
4933 else if (GetWindowLongA (hwnd
, GWL_STYLE
) & CCS_ADJUSTABLE
)
4934 TOOLBAR_Customize (hwnd
);
4941 TOOLBAR_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4943 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4944 TBUTTON_INFO
*btnPtr
;
4949 if (infoPtr
->hwndToolTip
)
4950 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
4951 WM_LBUTTONDOWN
, wParam
, lParam
);
4953 pt
.x
= (INT
)LOWORD(lParam
);
4954 pt
.y
= (INT
)HIWORD(lParam
);
4955 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
4959 btnPtr
= &infoPtr
->buttons
[nHit
];
4960 infoPtr
->nOldHit
= nHit
;
4962 CopyRect(&arrowRect
, &btnPtr
->rect
);
4963 arrowRect
.left
= max(btnPtr
->rect
.left
, btnPtr
->rect
.right
- DDARROW_WIDTH
);
4965 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
4966 if ((btnPtr
->fsState
& TBSTATE_ENABLED
) && (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
) &&
4967 ((TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
) && PtInRect(&arrowRect
, pt
)) ||
4968 (!TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
))))
4972 * this time we must force a Redraw, so the btn is
4973 * painted down before CaptureChanged repaints it up
4975 RedrawWindow(hwnd
,&btnPtr
->rect
,0,
4976 RDW_ERASE
|RDW_INVALIDATE
|RDW_UPDATENOW
);
4978 nmtb
.iItem
= btnPtr
->idCommand
;
4979 memset(&nmtb
.tbButton
, 0, sizeof(TBBUTTON
));
4982 memset(&nmtb
.rcButton
, 0, sizeof(RECT
));
4983 res
= TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
4985 if (res
!= TBDDRET_TREATPRESSED
)
4986 /* ??? guess (GA) */
4988 /* otherwise drop through and process as pushed */
4990 /* SetCapture (hwnd); */
4991 infoPtr
->bCaptured
= TRUE
;
4992 infoPtr
->nButtonDown
= nHit
;
4994 btnPtr
->fsState
|= TBSTATE_PRESSED
;
4995 btnPtr
->bHot
= FALSE
;
4997 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
4998 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
5002 /* native issues the TBN_BEGINDRAG here */
5003 nmtb
.iItem
= btnPtr
->idCommand
;
5004 nmtb
.tbButton
.iBitmap
= btnPtr
->iBitmap
;
5005 nmtb
.tbButton
.idCommand
= btnPtr
->idCommand
;
5006 nmtb
.tbButton
.fsState
= btnPtr
->fsState
;
5007 nmtb
.tbButton
.fsStyle
= btnPtr
->fsStyle
;
5008 nmtb
.tbButton
.dwData
= btnPtr
->dwData
;
5009 nmtb
.tbButton
.iString
= btnPtr
->iString
;
5010 nmtb
.cchText
= 0; /* !!! not correct */
5011 nmtb
.pszText
= 0; /* !!! not correct */
5012 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
5020 TOOLBAR_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5022 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5023 TBUTTON_INFO
*btnPtr
;
5027 BOOL bSendMessage
= TRUE
;
5032 if (infoPtr
->hwndToolTip
)
5033 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
5034 WM_LBUTTONUP
, wParam
, lParam
);
5036 pt
.x
= (INT
)LOWORD(lParam
);
5037 pt
.y
= (INT
)HIWORD(lParam
);
5038 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
5040 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
5041 /* if the cursor is still inside of the toolbar */
5042 if((infoPtr
->nHotItem
>= 0) && (nHit
!= -1))
5043 infoPtr
->buttons
[infoPtr
->nHotItem
].bHot
= TRUE
;
5045 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5046 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5048 if (btnPtr
->fsStyle
& TBSTYLE_CHECK
) {
5049 if (btnPtr
->fsStyle
& TBSTYLE_GROUP
) {
5050 nOldIndex
= TOOLBAR_GetCheckedGroupButtonIndex (infoPtr
,
5052 if (nOldIndex
== nHit
)
5053 bSendMessage
= FALSE
;
5054 if ((nOldIndex
!= nHit
) &&
5056 infoPtr
->buttons
[nOldIndex
].fsState
&= ~TBSTATE_CHECKED
;
5057 btnPtr
->fsState
|= TBSTATE_CHECKED
;
5060 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
5061 btnPtr
->fsState
&= ~TBSTATE_CHECKED
;
5063 btnPtr
->fsState
|= TBSTATE_CHECKED
;
5067 if (nOldIndex
!= -1)
5069 InvalidateRect(hwnd
, &infoPtr
->buttons
[nOldIndex
].rect
,
5070 TOOLBAR_HasText(infoPtr
, &infoPtr
->buttons
[nOldIndex
]));
5074 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
5075 * that resets bCaptured and btn TBSTATE_PRESSED flags,
5076 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
5078 if ((infoPtr
->bCaptured
) && (infoPtr
->nButtonDown
>= 0))
5080 infoPtr
->nButtonDown
= -1;
5082 /* Issue NM_RELEASEDCAPTURE to parent to let him know it is released */
5083 TOOLBAR_SendNotify ((NMHDR
*) &hdr
, infoPtr
,
5084 NM_RELEASEDCAPTURE
);
5086 /* native issues TBN_ENDDRAG here, if _LBUTTONDOWN issued the
5089 nmtb
.iItem
= btnPtr
->idCommand
;
5090 nmtb
.tbButton
.iBitmap
= btnPtr
->iBitmap
;
5091 nmtb
.tbButton
.idCommand
= btnPtr
->idCommand
;
5092 nmtb
.tbButton
.fsState
= btnPtr
->fsState
;
5093 nmtb
.tbButton
.fsStyle
= btnPtr
->fsStyle
;
5094 nmtb
.tbButton
.dwData
= btnPtr
->dwData
;
5095 nmtb
.tbButton
.iString
= btnPtr
->iString
;
5096 nmtb
.cchText
= 0; /* !!! not correct */
5097 nmtb
.pszText
= 0; /* !!! not correct */
5098 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
5101 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
5103 SendMessageA (infoPtr
->hwndNotify
, WM_COMMAND
,
5104 MAKEWPARAM(infoPtr
->buttons
[nHit
].idCommand
, 0), (LPARAM
)hwnd
);
5106 /* !!! Undocumented - toolbar at 4.71 level and above sends
5107 * either NMRCLICK or NM_CLICK with the NMMOUSE structure.
5108 * Only NM_RCLICK is documented.
5110 nmmouse
.dwItemSpec
= btnPtr
->idCommand
;
5111 nmmouse
.dwItemData
= btnPtr
->dwData
;
5112 TOOLBAR_SendNotify ((NMHDR
*) &nmmouse
, infoPtr
, NM_CLICK
);
5118 TOOLBAR_CaptureChanged(HWND hwnd
)
5120 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5121 TBUTTON_INFO
*btnPtr
;
5123 infoPtr
->bCaptured
= FALSE
;
5125 if (infoPtr
->nButtonDown
>= 0)
5127 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5128 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5130 infoPtr
->nOldHit
= -1;
5132 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
5133 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
5140 TOOLBAR_MouseLeave (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5142 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5143 TBUTTON_INFO
*hotBtnPtr
, *btnPtr
;
5146 if (infoPtr
->nOldHit
< 0)
5149 hotBtnPtr
= &infoPtr
->buttons
[infoPtr
->nOldHit
];
5151 /* Redraw the button if the last button we were over is the hot button and it
5153 if((infoPtr
->nOldHit
== infoPtr
->nHotItem
) && (hotBtnPtr
->fsState
& TBSTATE_ENABLED
))
5155 hotBtnPtr
->bHot
= FALSE
;
5156 rc1
= hotBtnPtr
->rect
;
5157 InflateRect (&rc1
, 1, 1);
5158 InvalidateRect (hwnd
, &rc1
, TOOLBAR_HasText(infoPtr
,
5162 /* If the last button we were over is depressed then make it not */
5163 /* depressed and redraw it */
5164 if(infoPtr
->nOldHit
== infoPtr
->nButtonDown
)
5166 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5168 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5170 rc1
= hotBtnPtr
->rect
;
5171 InflateRect (&rc1
, 1, 1);
5172 InvalidateRect (hwnd
, &rc1
, TRUE
);
5175 infoPtr
->nOldHit
= -1; /* reset the old hit index as we've left the toolbar */
5176 infoPtr
->nHotItem
= -2; /* It has to be initially different from nOldHit */
5182 TOOLBAR_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5184 TBUTTON_INFO
*btnPtr
= NULL
, *oldBtnPtr
= NULL
;
5185 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5188 TRACKMOUSEEVENT trackinfo
;
5189 NMTBHOTITEM nmhotitem
;
5191 /* fill in the TRACKMOUSEEVENT struct */
5192 trackinfo
.cbSize
= sizeof(TRACKMOUSEEVENT
);
5193 trackinfo
.dwFlags
= TME_QUERY
;
5194 trackinfo
.hwndTrack
= hwnd
;
5195 trackinfo
.dwHoverTime
= HOVER_DEFAULT
;
5197 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
5198 _TrackMouseEvent(&trackinfo
);
5200 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
5201 if(!(trackinfo
.dwFlags
& TME_LEAVE
)) {
5202 trackinfo
.dwFlags
= TME_LEAVE
; /* notify upon leaving */
5204 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
5205 /* and can properly deactivate the hot toolbar button */
5206 _TrackMouseEvent(&trackinfo
);
5209 if (infoPtr
->hwndToolTip
)
5210 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
5211 WM_MOUSEMOVE
, wParam
, lParam
);
5213 pt
.x
= (INT
)LOWORD(lParam
);
5214 pt
.y
= (INT
)HIWORD(lParam
);
5216 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
5218 if (infoPtr
->nOldHit
!= nHit
)
5220 /* Remove the effect of an old hot button if the button was
5221 drawn with the hot button effect */
5222 if(infoPtr
->nOldHit
>= 0 && infoPtr
->nOldHit
== infoPtr
->nHotItem
)
5224 oldBtnPtr
= &infoPtr
->buttons
[infoPtr
->nOldHit
];
5225 oldBtnPtr
->bHot
= FALSE
;
5228 /* It's not a separator or in nowhere. It's a hot button. */
5231 btnPtr
= &infoPtr
->buttons
[nHit
];
5233 infoPtr
->nHotItem
= nHit
;
5235 btnPtr
->bHot
= TRUE
;
5238 nmhotitem
.dwFlags
= HICF_MOUSE
;
5240 nmhotitem
.idOld
= oldBtnPtr
->idCommand
;
5242 nmhotitem
.dwFlags
|= HICF_ENTERING
;
5244 nmhotitem
.idNew
= btnPtr
->idCommand
;
5246 nmhotitem
.dwFlags
|= HICF_LEAVING
;
5247 TOOLBAR_SendNotify((NMHDR
*)&nmhotitem
, infoPtr
, TBN_HOTITEMCHANGE
);
5249 /* now invalidate the old and new buttons so they will be painted */
5251 InvalidateRect (hwnd
, &oldBtnPtr
->rect
,
5252 TOOLBAR_HasText(infoPtr
, oldBtnPtr
));
5254 InvalidateRect(hwnd
, &btnPtr
->rect
,
5255 TOOLBAR_HasText(infoPtr
, btnPtr
));
5257 if (infoPtr
->bCaptured
) {
5258 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5259 if (infoPtr
->nOldHit
== infoPtr
->nButtonDown
) {
5260 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5261 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
5263 else if (nHit
== infoPtr
->nButtonDown
) {
5264 btnPtr
->fsState
|= TBSTATE_PRESSED
;
5265 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
5268 infoPtr
->nOldHit
= nHit
;
5274 inline static LRESULT
5275 TOOLBAR_NCActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5277 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
5278 return DefWindowProcA (hwnd
, WM_NCACTIVATE
, wParam
, lParam
);
5280 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
5284 inline static LRESULT
5285 TOOLBAR_NCCalcSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5287 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & CCS_NODIVIDER
))
5288 ((LPRECT
)lParam
)->top
+= GetSystemMetrics(SM_CYEDGE
);
5290 return DefWindowProcA (hwnd
, WM_NCCALCSIZE
, wParam
, lParam
);
5295 TOOLBAR_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5297 TOOLBAR_INFO
*infoPtr
;
5298 LPCREATESTRUCTA cs
= (LPCREATESTRUCTA
)lParam
;
5301 /* allocate memory for info structure */
5302 infoPtr
= (TOOLBAR_INFO
*)Alloc (sizeof(TOOLBAR_INFO
));
5303 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
5306 infoPtr
->dwStructSize
= sizeof(TBBUTTON
);
5309 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
5310 if (!GetWindowLongA (hwnd
, GWL_HINSTANCE
)) {
5311 HINSTANCE hInst
= (HINSTANCE
)GetWindowLongA (GetParent (hwnd
), GWL_HINSTANCE
);
5312 SetWindowLongA (hwnd
, GWL_HINSTANCE
, (DWORD
)hInst
);
5315 /* native control does:
5316 * Get a lot of colors and brushes
5318 * SystemParametersInfoA(0x1f, 0x3c, adr1, 0)
5319 * CreateFontIndirectA(adr1)
5320 * CreateBitmap(0x27, 0x24, 1, 1, 0)
5321 * hdc = GetDC(toolbar)
5322 * GetSystemMetrics(0x48)
5323 * fnt2=CreateFontA(0xe, 0, 0, 0, 0x190, 0, 0, 0, 0, 2,
5324 * 0, 0, 0, 0, "MARLETT")
5325 * oldfnt = SelectObject(hdc, fnt2)
5326 * GetCharWidthA(hdc, 0x36, 0x36, adr2)
5327 * GetTextMetricsA(hdc, adr3)
5328 * SelectObject(hdc, oldfnt)
5329 * DeleteObject(fnt2)
5331 * InvalidateRect(toolbar, 0, 1)
5332 * SetWindowLongA(toolbar, 0, addr)
5333 * SetWindowLongA(toolbar, -16, xxx) **sometimes**
5336 * ie 1 0x56000a4c 0x46000a4c 0x56008a4d
5337 * ie 2 0x4600094c 0x4600094c 0x4600894d
5338 * ie 3 0x56000b4c 0x46000b4c 0x56008b4d
5339 * rebar 0x50008844 0x40008844 0x50008845
5340 * pager 0x50000844 0x40000844 0x50008845
5341 * IC35mgr 0x5400084e **nochange**
5342 * on entry to _NCCREATE 0x5400084e
5343 * rowlist 0x5400004e **nochange**
5344 * on entry to _NCCREATE 0x5400004e
5348 /* I think the code below is a bug, but it is the way that the native
5349 * controls seem to work. The effect is that if the user of TBSTYLE_FLAT
5350 * forgets to specify TBSTYLE_TRANSPARENT but does specify either
5351 * CCS_TOP or CCS_BOTTOM (_NOMOVEY and _TOP), then the control
5352 * does *not* set TBSTYLE_TRANSPARENT even though it should!!!!
5353 * Some how, the only cases of this seem to be MFC programs.
5355 * Note also that the addition of _TRANSPARENT occurs *only* here. It
5356 * does not occur in the WM_STYLECHANGING routine.
5357 * (Guy Albertelli 9/2001)
5360 if ((cs
->style
& TBSTYLE_FLAT
) && !(cs
->style
& TBSTYLE_TRANSPARENT
))
5361 styleadd
|= TBSTYLE_TRANSPARENT
;
5362 if (!(cs
->style
& (CCS_TOP
| CCS_NOMOVEY
))) {
5363 styleadd
|= CCS_TOP
; /* default to top */
5364 SetWindowLongA (hwnd
, GWL_STYLE
, cs
->style
| styleadd
);
5367 return DefWindowProcA (hwnd
, WM_NCCREATE
, wParam
, lParam
);
5372 TOOLBAR_NCPaint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5374 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
5378 if (dwStyle
& WS_MINIMIZE
)
5379 return 0; /* Nothing to do */
5381 DefWindowProcA (hwnd
, WM_NCPAINT
, wParam
, lParam
);
5383 if (!(hdc
= GetDCEx (hwnd
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
5386 if (!(dwStyle
& CCS_NODIVIDER
))
5388 GetWindowRect (hwnd
, &rcWindow
);
5389 OffsetRect (&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
5390 if( dwStyle
& WS_BORDER
)
5391 OffsetRect (&rcWindow
, 1, 1);
5392 DrawEdge (hdc
, &rcWindow
, EDGE_ETCHED
, BF_TOP
);
5395 ReleaseDC( hwnd
, hdc
);
5401 inline static LRESULT
5402 TOOLBAR_Notify (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5404 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5405 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
5407 if (lpnmh
->code
== PGN_CALCSIZE
) {
5408 LPNMPGCALCSIZE lppgc
= (LPNMPGCALCSIZE
)lParam
;
5410 if (lppgc
->dwFlag
== PGF_CALCWIDTH
) {
5411 lppgc
->iWidth
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
5412 TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
5416 lppgc
->iHeight
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
5417 TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
5423 if (lpnmh
->code
== PGN_SCROLL
) {
5424 LPNMPGSCROLL lppgs
= (LPNMPGSCROLL
)lParam
;
5426 lppgs
->iScroll
= (lppgs
->iDir
& (PGF_SCROLLLEFT
| PGF_SCROLLRIGHT
)) ?
5427 infoPtr
->nButtonWidth
: infoPtr
->nButtonHeight
;
5428 TRACE("processed PGN_SCROLL, returning scroll=%d, dir=%d\n",
5429 lppgs
->iScroll
, lppgs
->iDir
);
5434 TRACE("passing WM_NOTIFY!\n");
5436 if ((infoPtr
->hwndToolTip
) && (lpnmh
->hwndFrom
== infoPtr
->hwndToolTip
)) {
5437 if (infoPtr
->bNtfUnicode
)
5438 return SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
5441 return SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
5445 if (lpnmh
->code
== TTN_GETDISPINFOA
) {
5446 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
5448 FIXME("retrieving ASCII string\n");
5451 else if (lpnmh
->code
== TTN_GETDISPINFOW
) {
5452 LPNMTTDISPINFOW lpdi
= (LPNMTTDISPINFOW
)lParam
;
5454 FIXME("retrieving UNICODE string\n");
5465 TOOLBAR_NotifyFormatFake(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5467 /* remove this routine when Toolbar is improved to pass infoPtr
5468 * around instead of hwnd.
5470 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
5471 return TOOLBAR_NotifyFormat(infoPtr
, wParam
, lParam
);
5476 TOOLBAR_NotifyFormat(TOOLBAR_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
5480 if (lParam
== NF_REQUERY
) {
5481 i
= SendMessageA(infoPtr
->hwndNotify
,
5482 WM_NOTIFYFORMAT
, (WPARAM
)infoPtr
->hwndSelf
, NF_QUERY
);
5483 if ((i
< NFR_ANSI
) || (i
> NFR_UNICODE
)) {
5484 ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n",
5488 infoPtr
->bNtfUnicode
= (i
== NFR_UNICODE
) ? 1 : 0;
5491 return (LRESULT
)((infoPtr
->bUnicode
) ? NFR_UNICODE
: NFR_ANSI
);
5496 TOOLBAR_Paint (HWND hwnd
, WPARAM wParam
)
5498 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
5502 /* fill ps.rcPaint with a default rect */
5503 memcpy(&(ps
.rcPaint
), &(infoPtr
->rcBound
), sizeof(infoPtr
->rcBound
));
5505 hdc
= wParam
==0 ? BeginPaint(hwnd
, &ps
) : (HDC
)wParam
;
5507 TRACE("psrect=(%ld,%ld)-(%ld,%ld)\n",
5508 ps
.rcPaint
.left
, ps
.rcPaint
.top
,
5509 ps
.rcPaint
.right
, ps
.rcPaint
.bottom
);
5511 TOOLBAR_Refresh (hwnd
, hdc
, &ps
);
5512 if (!wParam
) EndPaint (hwnd
, &ps
);
5519 TOOLBAR_SetRedraw (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5520 /*****************************************************
5523 * Handles the WM_SETREDRAW message.
5526 * According to testing V4.71 of COMCTL32 returns the
5527 * *previous* status of the redraw flag (either 0 or 1)
5528 * instead of the MSDN documented value of 0 if handled.
5529 * (For laughs see the "consistency" with same function
5532 *****************************************************/
5534 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5535 BOOL oldredraw
= infoPtr
->bDoRedraw
;
5537 TRACE("set to %s\n",
5538 (wParam
) ? "TRUE" : "FALSE");
5539 infoPtr
->bDoRedraw
= (BOOL
) wParam
;
5541 InvalidateRect (infoPtr
->hwndSelf
, 0, TRUE
);
5543 return (oldredraw
) ? 1 : 0;
5548 TOOLBAR_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5550 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5551 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
5560 /* Resize deadlock check */
5561 if (infoPtr
->bAutoSize
) {
5562 infoPtr
->bAutoSize
= FALSE
;
5566 /* FIXME: optimize to only update size if the new size doesn't */
5567 /* match the current size */
5569 flags
= (INT
) wParam
;
5571 /* FIXME for flags =
5572 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
5575 TRACE("sizing toolbar!\n");
5577 if (flags
== SIZE_RESTORED
) {
5578 /* width and height don't apply */
5579 parent
= GetParent (hwnd
);
5580 GetClientRect(parent
, &parent_rect
);
5581 x
= parent_rect
.left
;
5582 y
= parent_rect
.top
;
5584 if (dwStyle
& CCS_NORESIZE
) {
5585 uPosFlags
|= (SWP_NOSIZE
| SWP_NOMOVE
);
5588 * this sets the working width of the toolbar, and
5589 * Calc Toolbar will not adjust it, only the height
5591 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
5592 cy
= infoPtr
->nHeight
;
5593 cx
= infoPtr
->nWidth
;
5594 TOOLBAR_CalcToolbar (hwnd
);
5595 infoPtr
->nWidth
= cx
;
5596 infoPtr
->nHeight
= cy
;
5599 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
5600 TOOLBAR_CalcToolbar (hwnd
);
5601 cy
= infoPtr
->nHeight
;
5602 cx
= infoPtr
->nWidth
;
5604 if ((dwStyle
& CCS_BOTTOM
) == CCS_NOMOVEY
) {
5605 GetWindowRect(hwnd
, &window_rect
);
5606 ScreenToClient(parent
, (LPPOINT
)&window_rect
.left
);
5607 y
= window_rect
.top
;
5609 if ((dwStyle
& CCS_BOTTOM
) == CCS_BOTTOM
) {
5610 GetWindowRect(hwnd
, &window_rect
);
5611 y
= parent_rect
.bottom
-
5612 ( window_rect
.bottom
- window_rect
.top
);
5616 if (dwStyle
& CCS_NOPARENTALIGN
) {
5617 uPosFlags
|= SWP_NOMOVE
;
5618 cy
= infoPtr
->nHeight
;
5619 cx
= infoPtr
->nWidth
;
5622 if (!(dwStyle
& CCS_NODIVIDER
))
5623 cy
+= GetSystemMetrics(SM_CYEDGE
);
5625 if (dwStyle
& WS_BORDER
)
5628 cy
+= GetSystemMetrics(SM_CYEDGE
);
5629 cx
+= GetSystemMetrics(SM_CYEDGE
);
5632 SetWindowPos (hwnd
, 0, x
, y
, cx
, cy
, uPosFlags
| SWP_NOZORDER
);
5639 TOOLBAR_StyleChanged (HWND hwnd
, INT nType
, LPSTYLESTRUCT lpStyle
)
5641 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5643 if (nType
== GWL_STYLE
) {
5644 if (lpStyle
->styleNew
& TBSTYLE_LIST
) {
5645 infoPtr
->dwDTFlags
= DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
;
5648 infoPtr
->dwDTFlags
= DT_CENTER
;
5650 infoPtr
->bTransparent
= (lpStyle
->styleNew
& TBSTYLE_TRANSPARENT
);
5651 infoPtr
->bBtnTranspnt
= (lpStyle
->styleNew
&
5652 (TBSTYLE_FLAT
| TBSTYLE_LIST
));
5653 TOOLBAR_CheckStyle (hwnd
, lpStyle
->styleNew
);
5655 TRACE("new style 0x%08lx\n", lpStyle
->styleNew
);
5658 TOOLBAR_CalcToolbar(hwnd
);
5660 TOOLBAR_AutoSize (hwnd
);
5662 InvalidateRect(hwnd
, NULL
, FALSE
);
5669 TOOLBAR_SysColorChange (HWND hwnd
)
5671 COMCTL32_RefreshSysColors();
5678 static LRESULT WINAPI
5679 ToolbarWindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
5681 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5683 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n",
5684 hwnd
, uMsg
, /* SPY_GetMsgName(uMsg), */ wParam
, lParam
);
5686 if (!TOOLBAR_GetInfoPtr(hwnd
) && (uMsg
!= WM_NCCREATE
))
5687 return DefWindowProcA( hwnd
, uMsg
, wParam
, lParam
);
5692 return TOOLBAR_AddBitmap (hwnd
, wParam
, lParam
);
5694 case TB_ADDBUTTONSA
:
5695 return TOOLBAR_AddButtonsA (hwnd
, wParam
, lParam
);
5697 case TB_ADDBUTTONSW
:
5698 return TOOLBAR_AddButtonsW (hwnd
, wParam
, lParam
);
5701 return TOOLBAR_AddStringA (hwnd
, wParam
, lParam
);
5704 return TOOLBAR_AddStringW (hwnd
, wParam
, lParam
);
5707 return TOOLBAR_AutoSize (hwnd
);
5709 case TB_BUTTONCOUNT
:
5710 return TOOLBAR_ButtonCount (hwnd
, wParam
, lParam
);
5712 case TB_BUTTONSTRUCTSIZE
:
5713 return TOOLBAR_ButtonStructSize (hwnd
, wParam
, lParam
);
5715 case TB_CHANGEBITMAP
:
5716 return TOOLBAR_ChangeBitmap (hwnd
, wParam
, lParam
);
5718 case TB_CHECKBUTTON
:
5719 return TOOLBAR_CheckButton (hwnd
, wParam
, lParam
);
5721 case TB_COMMANDTOINDEX
:
5722 return TOOLBAR_CommandToIndex (hwnd
, wParam
, lParam
);
5725 return TOOLBAR_Customize (hwnd
);
5727 case TB_DELETEBUTTON
:
5728 return TOOLBAR_DeleteButton (hwnd
, wParam
, lParam
);
5730 case TB_ENABLEBUTTON
:
5731 return TOOLBAR_EnableButton (hwnd
, wParam
, lParam
);
5733 case TB_GETANCHORHIGHLIGHT
:
5734 return TOOLBAR_GetAnchorHighlight (hwnd
);
5737 return TOOLBAR_GetBitmap (hwnd
, wParam
, lParam
);
5739 case TB_GETBITMAPFLAGS
:
5740 return TOOLBAR_GetBitmapFlags (hwnd
, wParam
, lParam
);
5743 return TOOLBAR_GetButton (hwnd
, wParam
, lParam
);
5745 case TB_GETBUTTONINFOA
:
5746 return TOOLBAR_GetButtonInfoA (hwnd
, wParam
, lParam
);
5748 case TB_GETBUTTONINFOW
:
5749 return TOOLBAR_GetButtonInfoW (hwnd
, wParam
, lParam
);
5751 case TB_GETBUTTONSIZE
:
5752 return TOOLBAR_GetButtonSize (hwnd
);
5754 case TB_GETBUTTONTEXTA
:
5755 return TOOLBAR_GetButtonTextA (hwnd
, wParam
, lParam
);
5757 case TB_GETBUTTONTEXTW
:
5758 return TOOLBAR_GetButtonTextW (hwnd
, wParam
, lParam
);
5760 case TB_GETDISABLEDIMAGELIST
:
5761 return TOOLBAR_GetDisabledImageList (hwnd
, wParam
, lParam
);
5763 case TB_GETEXTENDEDSTYLE
:
5764 return TOOLBAR_GetExtendedStyle (hwnd
);
5766 case TB_GETHOTIMAGELIST
:
5767 return TOOLBAR_GetHotImageList (hwnd
, wParam
, lParam
);
5770 return TOOLBAR_GetHotItem (hwnd
);
5772 case TB_GETIMAGELIST
:
5773 return TOOLBAR_GetDefImageList (hwnd
, wParam
, lParam
);
5775 /* case TB_GETINSERTMARK: */ /* 4.71 */
5776 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
5778 case TB_GETITEMRECT
:
5779 return TOOLBAR_GetItemRect (hwnd
, wParam
, lParam
);
5782 return TOOLBAR_GetMaxSize (hwnd
, wParam
, lParam
);
5784 /* case TB_GETOBJECT: */ /* 4.71 */
5787 return TOOLBAR_GetPadding (hwnd
);
5790 return TOOLBAR_GetRect (hwnd
, wParam
, lParam
);
5793 return TOOLBAR_GetRows (hwnd
, wParam
, lParam
);
5796 return TOOLBAR_GetState (hwnd
, wParam
, lParam
);
5799 return TOOLBAR_GetStyle (hwnd
, wParam
, lParam
);
5801 case TB_GETTEXTROWS
:
5802 return TOOLBAR_GetTextRows (hwnd
, wParam
, lParam
);
5804 case TB_GETTOOLTIPS
:
5805 return TOOLBAR_GetToolTips (hwnd
, wParam
, lParam
);
5807 case TB_GETUNICODEFORMAT
:
5808 return TOOLBAR_GetUnicodeFormat (hwnd
, wParam
, lParam
);
5811 return TOOLBAR_HideButton (hwnd
, wParam
, lParam
);
5814 return TOOLBAR_HitTest (hwnd
, wParam
, lParam
);
5816 case TB_INDETERMINATE
:
5817 return TOOLBAR_Indeterminate (hwnd
, wParam
, lParam
);
5819 case TB_INSERTBUTTONA
:
5820 return TOOLBAR_InsertButtonA (hwnd
, wParam
, lParam
);
5822 case TB_INSERTBUTTONW
:
5823 return TOOLBAR_InsertButtonW (hwnd
, wParam
, lParam
);
5825 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
5827 case TB_ISBUTTONCHECKED
:
5828 return TOOLBAR_IsButtonChecked (hwnd
, wParam
, lParam
);
5830 case TB_ISBUTTONENABLED
:
5831 return TOOLBAR_IsButtonEnabled (hwnd
, wParam
, lParam
);
5833 case TB_ISBUTTONHIDDEN
:
5834 return TOOLBAR_IsButtonHidden (hwnd
, wParam
, lParam
);
5836 case TB_ISBUTTONHIGHLIGHTED
:
5837 return TOOLBAR_IsButtonHighlighted (hwnd
, wParam
, lParam
);
5839 case TB_ISBUTTONINDETERMINATE
:
5840 return TOOLBAR_IsButtonIndeterminate (hwnd
, wParam
, lParam
);
5842 case TB_ISBUTTONPRESSED
:
5843 return TOOLBAR_IsButtonPressed (hwnd
, wParam
, lParam
);
5845 case TB_LOADIMAGES
: /* 4.70 */
5846 FIXME("missing standard imagelists\n");
5849 /* case TB_MAPACCELERATORA: */ /* 4.71 */
5850 /* case TB_MAPACCELERATORW: */ /* 4.71 */
5851 /* case TB_MARKBUTTON: */ /* 4.71 */
5852 /* case TB_MOVEBUTTON: */ /* 4.71 */
5854 case TB_PRESSBUTTON
:
5855 return TOOLBAR_PressButton (hwnd
, wParam
, lParam
);
5857 case TB_REPLACEBITMAP
:
5858 return TOOLBAR_ReplaceBitmap (hwnd
, wParam
, lParam
);
5860 case TB_SAVERESTOREA
:
5861 return TOOLBAR_SaveRestoreA (hwnd
, wParam
, lParam
);
5863 case TB_SAVERESTOREW
:
5864 return TOOLBAR_SaveRestoreW (hwnd
, wParam
, lParam
);
5866 case TB_SETANCHORHIGHLIGHT
:
5867 return TOOLBAR_SetAnchorHighlight (hwnd
, wParam
);
5869 case TB_SETBITMAPSIZE
:
5870 return TOOLBAR_SetBitmapSize (hwnd
, wParam
, lParam
);
5872 case TB_SETBUTTONINFOA
:
5873 return TOOLBAR_SetButtonInfoA (hwnd
, wParam
, lParam
);
5875 case TB_SETBUTTONINFOW
:
5876 return TOOLBAR_SetButtonInfoW (hwnd
, wParam
, lParam
);
5878 case TB_SETBUTTONSIZE
:
5879 return TOOLBAR_SetButtonSize (hwnd
, wParam
, lParam
);
5881 case TB_SETBUTTONWIDTH
:
5882 return TOOLBAR_SetButtonWidth (hwnd
, wParam
, lParam
);
5885 return TOOLBAR_SetCmdId (hwnd
, wParam
, lParam
);
5887 case TB_SETDISABLEDIMAGELIST
:
5888 return TOOLBAR_SetDisabledImageList (hwnd
, wParam
, lParam
);
5890 case TB_SETDRAWTEXTFLAGS
:
5891 return TOOLBAR_SetDrawTextFlags (hwnd
, wParam
, lParam
);
5893 case TB_SETEXTENDEDSTYLE
:
5894 return TOOLBAR_SetExtendedStyle (hwnd
, wParam
, lParam
);
5896 case TB_SETHOTIMAGELIST
:
5897 return TOOLBAR_SetHotImageList (hwnd
, wParam
, lParam
);
5900 return TOOLBAR_SetHotItem (hwnd
, wParam
);
5902 case TB_SETIMAGELIST
:
5903 return TOOLBAR_SetImageList (hwnd
, wParam
, lParam
);
5906 return TOOLBAR_SetIndent (hwnd
, wParam
, lParam
);
5908 /* case TB_SETINSERTMARK: */ /* 4.71 */
5910 case TB_SETINSERTMARKCOLOR
:
5911 return TOOLBAR_SetInsertMarkColor (hwnd
, wParam
, lParam
);
5913 case TB_SETMAXTEXTROWS
:
5914 return TOOLBAR_SetMaxTextRows (hwnd
, wParam
, lParam
);
5917 return TOOLBAR_SetPadding (hwnd
, wParam
, lParam
);
5920 return TOOLBAR_SetParent (hwnd
, wParam
, lParam
);
5923 return TOOLBAR_SetRows (hwnd
, wParam
, lParam
);
5926 return TOOLBAR_SetState (hwnd
, wParam
, lParam
);
5929 return TOOLBAR_SetStyle (hwnd
, wParam
, lParam
);
5931 case TB_SETTOOLTIPS
:
5932 return TOOLBAR_SetToolTips (hwnd
, wParam
, lParam
);
5934 case TB_SETUNICODEFORMAT
:
5935 return TOOLBAR_SetUnicodeFormat (hwnd
, wParam
, lParam
);
5938 return TOOLBAR_Unkwn45E (hwnd
, wParam
, lParam
);
5941 return TOOLBAR_Unkwn463 (hwnd
, wParam
, lParam
);
5944 /* Common Control Messages */
5946 /* case TB_GETCOLORSCHEME: */ /* identical to CCM_ */
5947 case CCM_GETCOLORSCHEME
:
5948 return TOOLBAR_GetColorScheme (hwnd
, (LPCOLORSCHEME
)lParam
);
5950 /* case TB_SETCOLORSCHEME: */ /* identical to CCM_ */
5951 case CCM_SETCOLORSCHEME
:
5952 return TOOLBAR_SetColorScheme (hwnd
, (LPCOLORSCHEME
)lParam
);
5954 case CCM_GETVERSION
:
5955 return TOOLBAR_GetVersion (hwnd
);
5957 case CCM_SETVERSION
:
5958 return TOOLBAR_SetVersion (hwnd
, (INT
)wParam
);
5964 return TOOLBAR_Create (hwnd
, wParam
, lParam
);
5967 return TOOLBAR_Destroy (hwnd
, wParam
, lParam
);
5970 return TOOLBAR_EraseBackground (hwnd
, wParam
, lParam
);
5973 return TOOLBAR_GetFont (hwnd
, wParam
, lParam
);
5975 /* case WM_KEYDOWN: */
5976 /* case WM_KILLFOCUS: */
5978 case WM_LBUTTONDBLCLK
:
5979 return TOOLBAR_LButtonDblClk (hwnd
, wParam
, lParam
);
5981 case WM_LBUTTONDOWN
:
5982 return TOOLBAR_LButtonDown (hwnd
, wParam
, lParam
);
5985 return TOOLBAR_LButtonUp (hwnd
, wParam
, lParam
);
5988 return TOOLBAR_MouseMove (hwnd
, wParam
, lParam
);
5991 return TOOLBAR_MouseLeave (hwnd
, wParam
, lParam
);
5993 case WM_CAPTURECHANGED
:
5994 return TOOLBAR_CaptureChanged(hwnd
);
5997 return TOOLBAR_NCActivate (hwnd
, wParam
, lParam
);
6000 return TOOLBAR_NCCalcSize (hwnd
, wParam
, lParam
);
6003 return TOOLBAR_NCCreate (hwnd
, wParam
, lParam
);
6006 return TOOLBAR_NCPaint (hwnd
, wParam
, lParam
);
6009 return TOOLBAR_Notify (hwnd
, wParam
, lParam
);
6011 case WM_NOTIFYFORMAT
:
6012 TOOLBAR_NotifyFormatFake (hwnd
, wParam
, lParam
);
6015 return TOOLBAR_Paint (hwnd
, wParam
);
6018 return TOOLBAR_SetRedraw (hwnd
, wParam
, lParam
);
6021 return TOOLBAR_Size (hwnd
, wParam
, lParam
);
6023 case WM_STYLECHANGED
:
6024 return TOOLBAR_StyleChanged (hwnd
, (INT
)wParam
, (LPSTYLESTRUCT
)lParam
);
6026 case WM_SYSCOLORCHANGE
:
6027 return TOOLBAR_SysColorChange (hwnd
);
6029 /* case WM_WININICHANGE: */
6034 case WM_MEASUREITEM
:
6036 return SendMessageA (infoPtr
->hwndNotify
, uMsg
, wParam
, lParam
);
6038 /* We see this in Outlook Express 5.x and just does DefWindowProc */
6039 case PGM_FORWARDMOUSE
:
6040 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
6043 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
6044 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
6045 uMsg
, wParam
, lParam
);
6046 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
6053 TOOLBAR_Register (void)
6057 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
6058 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
6059 wndClass
.lpfnWndProc
= (WNDPROC
)ToolbarWindowProc
;
6060 wndClass
.cbClsExtra
= 0;
6061 wndClass
.cbWndExtra
= sizeof(TOOLBAR_INFO
*);
6062 wndClass
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
6063 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
6064 wndClass
.lpszClassName
= TOOLBARCLASSNAMEA
;
6066 RegisterClassA (&wndClass
);
6071 TOOLBAR_Unregister (void)
6073 UnregisterClassA (TOOLBARCLASSNAMEA
, NULL
);
6076 static HIMAGELIST
TOOLBAR_InsertImageList(PIMLENTRY
**pies
, INT
*cies
, HIMAGELIST himl
, INT id
)
6081 /* Check if the entry already exists */
6082 c
= TOOLBAR_GetImageListEntry(*pies
, *cies
, id
);
6084 /* If this is a new entry we must create it and insert into the array */
6089 c
= (PIMLENTRY
) Alloc(sizeof(IMLENTRY
));
6092 pnies
= Alloc((*cies
+ 1) * sizeof(PIMLENTRY
));
6093 memcpy(pnies
, *pies
, ((*cies
) * sizeof(PIMLENTRY
)));
6108 static VOID
TOOLBAR_DeleteImageList(PIMLENTRY
**pies
, INT
*cies
)
6112 for (i
= 0; i
< *cies
; i
++)
6122 static PIMLENTRY
TOOLBAR_GetImageListEntry(PIMLENTRY
*pies
, INT cies
, INT id
)
6130 for (i
= 0; i
< cies
; i
++)
6132 if (pies
[i
]->id
== id
)
6144 static HIMAGELIST
TOOLBAR_GetImageList(PIMLENTRY
*pies
, INT cies
, INT id
)
6146 HIMAGELIST himlDef
= 0;
6147 PIMLENTRY pie
= TOOLBAR_GetImageListEntry(pies
, cies
, id
);
6150 himlDef
= pie
->himl
;
6156 static BOOL
TOOLBAR_GetButtonInfo(TOOLBAR_INFO
*infoPtr
, NMTOOLBARW
*nmtb
)
6158 if (infoPtr
->bUnicode
)
6159 return TOOLBAR_SendNotify ((NMHDR
*) nmtb
, infoPtr
, TBN_GETBUTTONINFOW
);
6166 nmtba
.iItem
= nmtb
->iItem
;
6167 nmtba
.pszText
= Buffer
;
6168 nmtba
.cchText
= 256;
6169 ZeroMemory(nmtba
.pszText
, nmtba
.cchText
);
6171 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtba
, infoPtr
, TBN_GETBUTTONINFOA
))
6173 int ccht
= strlen(nmtba
.pszText
);
6175 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)nmtba
.pszText
, -1,
6176 nmtb
->pszText
, nmtb
->cchText
);
6178 memcpy(&nmtb
->tbButton
, &nmtba
.tbButton
, sizeof(TBBUTTON
));
6187 static BOOL
TOOLBAR_IsButtonRemovable(TOOLBAR_INFO
*infoPtr
,
6188 int iItem
, PCUSTOMBUTTON btnInfo
)
6193 memcpy(&nmtb
.tbButton
, &btnInfo
->btn
, sizeof(TBBUTTON
));
6195 return TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_QUERYDELETE
);