4 * Copyright 1998,1999 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Differences between MSDN and actual native control operation:
22 * 1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
23 * to the right of the bitmap. Otherwise, this style is
24 * identical to TBSTYLE_FLAT."
25 * As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
26 * you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
27 * is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
28 * *not* imply TBSTYLE_FLAT as documented. (GA 8/2001)
32 * - A little bug in TOOLBAR_DrawMasked()
33 * - Button wrapping (under construction).
35 * - Notifications (under construction).
37 * - Tooltip support (almost complete).
38 * - Unicode suppport (under construction).
39 * - Fix TOOLBAR_SetButtonInfo32A/W.
40 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
41 * - I_IMAGECALLBACK support.
42 * - iString of -1 is undocumented
43 * - Customization dialog:
45 * - Minor buglet in 'available buttons' list:
46 * Buttons are not listed in M$-like order. M$ seems to use a single
47 * internal list to store the button information of both listboxes.
48 * - Drag list support.
49 * - Help and Reset button support.
52 * - Run tests using Waite Group Windows95 API Bible Volume 2.
53 * The second cdrom contains executables addstr.exe, btncount.exe,
54 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
55 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
56 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
57 * setparnt.exe, setrows.exe, toolwnd.exe.
58 * - Microsofts controlspy examples.
59 * - Charles Petzold's 'Programming Windows': gadgets.exe
68 #include "wine/unicode.h"
70 #include "imagelist.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(toolbar
);
101 } IMLENTRY
, *PIMLENTRY
;
105 DWORD dwStructSize
; /* size of TBBUTTON struct */
106 INT nHeight
; /* height of the toolbar */
107 INT nWidth
; /* width of the toolbar */
113 INT nRows
; /* number of button rows */
114 INT nMaxTextRows
; /* maximum number of text rows */
115 INT cxMin
; /* minimum button width */
116 INT cxMax
; /* maximum button width */
117 INT nNumButtons
; /* number of buttons */
118 INT nNumBitmaps
; /* number of bitmaps */
119 INT nNumStrings
; /* number of strings */
121 BOOL bUnicode
; /* ASCII (FALSE) or Unicode (TRUE)? */
122 BOOL bCaptured
; /* mouse captured? */
125 INT nHotItem
; /* index of the "hot" item */
126 DWORD dwBaseCustDraw
; /* CDRF_ response (w/o TBCDRF_) from PREPAINT */
127 DWORD dwItemCustDraw
; /* CDRF_ response (w/o TBCDRF_) from ITEMPREP */
128 DWORD dwItemCDFlag
; /* TBCDRF_ flags from last ITEMPREPAINT */
129 SIZE szPadding
; /* padding values around button */
131 HFONT hFont
; /* text font */
132 HIMAGELIST himlInt
; /* image list created internally */
133 PIMLENTRY
*himlDef
; /* default image list array */
134 INT cimlDef
; /* default image list array count */
135 PIMLENTRY
*himlHot
; /* hot image list array */
136 INT cimlHot
; /* hot image list array count */
137 PIMLENTRY
*himlDis
; /* disabled image list array */
138 INT cimlDis
; /* disabled image list array count */
139 HWND hwndToolTip
; /* handle to tool tip control */
140 HWND hwndNotify
; /* handle to the window that gets notifications */
141 HWND hwndSelf
; /* my own handle */
142 BOOL bTransparent
; /* background transparency flag */
143 BOOL bBtnTranspnt
; /* button transparency flag */
144 BOOL bAutoSize
; /* auto size deadlock indicator */
145 BOOL bAnchor
; /* anchor highlight enabled */
146 BOOL bNtfUnicode
; /* TRUE if NOTIFYs use {W} */
147 BOOL bDoRedraw
; /* Redraw status */
148 DWORD dwExStyle
; /* extended toolbar style */
149 DWORD dwDTFlags
; /* DrawText flags */
151 COLORREF clrInsertMark
; /* insert mark color */
152 COLORREF clrBtnHighlight
; /* color for Flat Separator */
153 COLORREF clrBtnShadow
; /* color for Flag Separator */
154 RECT rcBound
; /* bounding rectangle */
157 TBUTTON_INFO
*buttons
; /* pointer to button array */
158 LPWSTR
*strings
; /* pointer to string array */
159 TBITMAP_INFO
*bitmaps
;
160 } TOOLBAR_INFO
, *PTOOLBAR_INFO
;
163 /* used by customization dialog */
166 PTOOLBAR_INFO tbInfo
;
168 } CUSTDLG_INFO
, *PCUSTDLG_INFO
;
176 } CUSTOMBUTTON
, *PCUSTOMBUTTON
;
179 #define SEPARATOR_WIDTH 8
181 #define BOTTOM_BORDER 2
182 #define DDARROW_WIDTH 11
184 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
185 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
186 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
188 /* Used to find undocumented extended styles */
189 #define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \
190 TBSTYLE_EX_UNDOC1 | \
191 TBSTYLE_EX_MIXEDBUTTONS | \
192 TBSTYLE_EX_HIDECLIPPEDBUTTONS)
194 #define GETIBITMAP(infoPtr, i) (infoPtr->iVersion >= 5 ? LOWORD(i) : i)
195 #define GETHIMLID(infoPtr, i) (infoPtr->iVersion >= 5 ? HIWORD(i) : 0)
196 #define GETDEFIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDef, infoPtr->cimlDef, id)
197 #define GETHOTIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlHot, infoPtr->cimlHot, id)
198 #define GETDISIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDis, infoPtr->cimlDis, id)
200 static BOOL
TOOLBAR_GetButtonInfo(TOOLBAR_INFO
*infoPtr
, NMTOOLBARW
*nmtb
);
201 static BOOL
TOOLBAR_IsButtonRemovable(TOOLBAR_INFO
*infoPtr
, int iItem
, PCUSTOMBUTTON btnInfo
);
202 static HIMAGELIST
TOOLBAR_GetImageList(PIMLENTRY
*pies
, INT cies
, INT id
);
203 static PIMLENTRY
TOOLBAR_GetImageListEntry(PIMLENTRY
*pies
, INT cies
, INT id
);
204 static VOID
TOOLBAR_DeleteImageList(PIMLENTRY
**pies
, INT
*cies
);
205 static HIMAGELIST
TOOLBAR_InsertImageList(PIMLENTRY
**pies
, INT
*cies
, HIMAGELIST himl
, INT id
);
208 TOOLBAR_NotifyFormat(TOOLBAR_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
);
212 TOOLBAR_GetText(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
)
214 LPWSTR lpText
= NULL
;
216 /* FIXME: iString == -1 is undocumented */
217 if ((HIWORD(btnPtr
->iString
) != 0) && (btnPtr
->iString
!= -1))
218 lpText
= (LPWSTR
)btnPtr
->iString
;
219 else if ((btnPtr
->iString
>= 0) && (btnPtr
->iString
< infoPtr
->nNumStrings
))
220 lpText
= infoPtr
->strings
[btnPtr
->iString
];
226 TOOLBAR_DumpButton(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*bP
, INT btn_num
, BOOL internal
)
228 if (TRACE_ON(toolbar
)){
229 TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08x\n",
230 btn_num
, bP
->idCommand
, GETIBITMAP(infoPtr
, bP
->iBitmap
),
231 bP
->fsState
, bP
->fsStyle
, bP
->dwData
, bP
->iString
);
232 TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr
,bP
)));
234 TRACE("button %d id %d, hot=%s, row=%d, rect=(%ld,%ld)-(%ld,%ld)\n",
235 btn_num
, bP
->idCommand
,
236 (bP
->bHot
) ? "TRUE":"FALSE", bP
->nRow
,
237 bP
->rect
.left
, bP
->rect
.top
,
238 bP
->rect
.right
, bP
->rect
.bottom
);
244 TOOLBAR_DumpToolbar(TOOLBAR_INFO
*iP
, INT line
)
246 if (TRACE_ON(toolbar
)) {
250 dwStyle
= GetWindowLongA (iP
->hwndSelf
, GWL_STYLE
);
251 TRACE("toolbar %p at line %d, exStyle=%08lx, buttons=%d, bitmaps=%d, strings=%d, style=%08lx\n",
253 iP
->dwExStyle
, iP
->nNumButtons
, iP
->nNumBitmaps
,
254 iP
->nNumStrings
, dwStyle
);
255 TRACE("toolbar %p at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p, redrawable=%s\n",
257 iP
->himlInt
, iP
->himlDef
, iP
->himlHot
, iP
->himlDis
,
258 (iP
->bDoRedraw
) ? "TRUE" : "FALSE");
259 for(i
=0; i
<iP
->nNumButtons
; i
++) {
260 TOOLBAR_DumpButton(iP
, &iP
->buttons
[i
], i
, TRUE
);
266 /***********************************************************************
269 * This function validates that the styles set are implemented and
270 * issues FIXME's warning of possible problems. In a perfect world this
271 * function should be null.
274 TOOLBAR_CheckStyle (HWND hwnd
, DWORD dwStyle
)
276 if (dwStyle
& TBSTYLE_ALTDRAG
)
277 FIXME("[%p] TBSTYLE_ALTDRAG not implemented\n", hwnd
);
278 if (dwStyle
& TBSTYLE_REGISTERDROP
)
279 FIXME("[%p] TBSTYLE_REGISTERDROP not implemented\n", hwnd
);
284 TOOLBAR_SendNotify (NMHDR
*nmhdr
, TOOLBAR_INFO
*infoPtr
, UINT code
)
286 if(!IsWindow(infoPtr
->hwndSelf
))
287 return 0; /* we have just been destroyed */
289 nmhdr
->idFrom
= GetDlgCtrlID (infoPtr
->hwndSelf
);
290 nmhdr
->hwndFrom
= infoPtr
->hwndSelf
;
293 TRACE("to window %p, code=%08x, %s\n", infoPtr
->hwndNotify
, code
,
294 (infoPtr
->bNtfUnicode
) ? "via Unicode" : "via ANSI");
296 if (infoPtr
->bNtfUnicode
)
297 return SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
298 (WPARAM
) nmhdr
->idFrom
, (LPARAM
)nmhdr
);
300 return SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
301 (WPARAM
) nmhdr
->idFrom
, (LPARAM
)nmhdr
);
304 /***********************************************************************
305 * TOOLBAR_GetBitmapIndex
307 * This function returns the bitmap index associated with a button.
308 * If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO
309 * is issued to retrieve the index.
312 TOOLBAR_GetBitmapIndex(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
)
314 INT ret
= btnPtr
->iBitmap
;
316 if (ret
== I_IMAGECALLBACK
) {
317 /* issue TBN_GETDISPINFO */
320 nmgd
.idCommand
= btnPtr
->idCommand
;
321 nmgd
.lParam
= btnPtr
->dwData
;
322 nmgd
.dwMask
= TBNF_IMAGE
;
323 TOOLBAR_SendNotify ((NMHDR
*) &nmgd
, infoPtr
,
324 (infoPtr
->bNtfUnicode
) ? TBN_GETDISPINFOW
:
326 if (nmgd
.dwMask
& TBNF_DI_SETITEM
) {
327 btnPtr
->iBitmap
= nmgd
.iImage
;
330 TRACE("TBN_GETDISPINFOA returned bitmap id %d, mask=%08lx, nNumBitmaps=%d\n",
331 ret
, nmgd
.dwMask
, infoPtr
->nNumBitmaps
);
334 if (ret
!= I_IMAGENONE
)
335 ret
= GETIBITMAP(infoPtr
, ret
);
342 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO
*infoPtr
, INT index
)
345 INT id
= GETHIMLID(infoPtr
, index
);
346 INT iBitmap
= GETIBITMAP(infoPtr
, index
);
348 if (((himl
= GETDEFIMAGELIST(infoPtr
, id
)) &&
349 iBitmap
>= 0 && iBitmap
< ImageList_GetImageCount(himl
)) ||
350 (index
== I_IMAGECALLBACK
))
357 /***********************************************************************
358 * TOOLBAR_DrawImageList
360 * This function validates the bitmap index (including I_IMAGECALLBACK
361 * functionality). It then draws the image via the ImageList_Draw
362 * function. It returns TRUE if the image was drawn, FALSE otherwise.
365 TOOLBAR_DrawImageList (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
, HIMAGELIST himl
,
366 HDC hdc
, UINT left
, UINT top
, UINT draw_flags
)
370 if (!himl
) return FALSE
;
372 if (!TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
373 if (btnPtr
->iBitmap
== I_IMAGENONE
) return FALSE
;
374 ERR("index %d is not valid, max %d\n",
375 btnPtr
->iBitmap
, infoPtr
->nNumBitmaps
);
379 if ((index
= TOOLBAR_GetBitmapIndex(infoPtr
, btnPtr
)) < 0) {
380 if ((index
== I_IMAGECALLBACK
) ||
381 (index
== I_IMAGENONE
)) return FALSE
;
382 ERR("TBN_GETDISPINFO returned invalid index %d\n",
386 TRACE("drawing index=%d, himl=%p, left=%d, top=%d, flags=%08x\n",
387 index
, himl
, left
, top
, draw_flags
);
389 ImageList_Draw (himl
, index
, hdc
, left
, top
, draw_flags
);
394 /***********************************************************************
395 * TOOLBAR_TestImageExist
397 * This function is similar to TOOLBAR_DrawImageList, except it does not
398 * draw the image. The I_IMAGECALLBACK functionality is implemented.
401 TOOLBAR_TestImageExist (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
, HIMAGELIST himl
)
405 if (!himl
) return FALSE
;
407 if (!TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
408 if (btnPtr
->iBitmap
== I_IMAGENONE
) return FALSE
;
409 ERR("index %d is not valid, max %d\n",
410 btnPtr
->iBitmap
, infoPtr
->nNumBitmaps
);
414 if ((index
= TOOLBAR_GetBitmapIndex(infoPtr
, btnPtr
)) < 0) {
415 if ((index
== I_IMAGECALLBACK
) ||
416 (index
== I_IMAGENONE
)) return FALSE
;
417 ERR("TBN_GETDISPINFO returned invalid index %d\n",
426 TOOLBAR_DrawFlatSeparator (LPRECT lpRect
, HDC hdc
, TOOLBAR_INFO
*infoPtr
)
429 COLORREF oldcolor
, newcolor
;
431 myrect
.left
= (lpRect
->left
+ lpRect
->right
) / 2 - 1;
432 myrect
.right
= myrect
.left
+ 1;
433 myrect
.top
= lpRect
->top
+ 2;
434 myrect
.bottom
= lpRect
->bottom
- 2;
436 newcolor
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
437 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
438 oldcolor
= SetBkColor (hdc
, newcolor
);
439 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
441 myrect
.left
= myrect
.right
;
442 myrect
.right
= myrect
.left
+ 1;
444 newcolor
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
445 comctl32_color
.clrBtnHighlight
: infoPtr
->clrBtnHighlight
;
446 SetBkColor (hdc
, newcolor
);
447 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
449 SetBkColor (hdc
, oldcolor
);
453 /***********************************************************************
454 * TOOLBAR_DrawDDFlatSeparator
456 * This function draws the separator that was flaged as TBSTYLE_DROPDOWN.
457 * In this case, the separator is a pixel high line of COLOR_BTNSHADOW,
458 * followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators
459 * are horizontal as opposed to the vertical separators for not dropdown
462 * FIXME: It is possible that the height of each line is really SM_CYBORDER.
465 TOOLBAR_DrawDDFlatSeparator (LPRECT lpRect
, HDC hdc
, TBUTTON_INFO
*btnPtr
, TOOLBAR_INFO
*infoPtr
)
468 COLORREF oldcolor
, newcolor
;
470 myrect
.left
= lpRect
->left
;
471 myrect
.right
= lpRect
->right
;
472 myrect
.top
= lpRect
->top
+ (lpRect
->bottom
- lpRect
->top
- 2)/2;
473 myrect
.bottom
= myrect
.top
+ 1;
475 InflateRect (&myrect
, -2, 0);
477 TRACE("rect=(%ld,%ld)-(%ld,%ld)\n",
478 myrect
.left
, myrect
.top
, myrect
.right
, myrect
.bottom
);
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
.top
= myrect
.bottom
;
486 myrect
.bottom
= myrect
.top
+ 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
);
498 TOOLBAR_DrawArrow (HDC hdc
, INT left
, INT top
, INT colorRef
)
503 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
504 hOldPen
= SelectObject ( hdc
, hPen
);
507 MoveToEx (hdc
, x
, y
, NULL
);
508 LineTo (hdc
, x
+5, y
++); x
++;
509 MoveToEx (hdc
, x
, y
, NULL
);
510 LineTo (hdc
, x
+3, y
++); x
++;
511 MoveToEx (hdc
, x
, y
, NULL
);
512 LineTo (hdc
, x
+1, y
++);
513 SelectObject( hdc
, hOldPen
);
514 DeleteObject( hPen
);
518 * Draw the text string for this button.
519 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
520 * is non-zero, so we can simply check himlDef to see if we have
524 TOOLBAR_DrawString (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
525 HDC hdc
, INT nState
, DWORD dwStyle
,
526 RECT
*rcText
, LPWSTR lpText
, NMTBCUSTOMDRAW
*tbcd
)
533 TRACE("string rect=(%ld,%ld)-(%ld,%ld)\n",
534 rcText
->left
, rcText
->top
, rcText
->right
, rcText
->bottom
);
536 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
537 if (!(nState
& TBSTATE_ENABLED
)) {
538 clrOld
= SetTextColor (hdc
, tbcd
->clrBtnHighlight
);
539 OffsetRect (rcText
, 1, 1);
540 DrawTextW (hdc
, lpText
, -1, rcText
, infoPtr
->dwDTFlags
);
541 SetTextColor (hdc
, comctl32_color
.clr3dShadow
);
542 OffsetRect (rcText
, -1, -1);
544 else if (nState
& TBSTATE_INDETERMINATE
) {
545 clrOld
= SetTextColor (hdc
, comctl32_color
.clr3dShadow
);
547 else if (btnPtr
->bHot
&& (infoPtr
->dwItemCDFlag
& TBCDRF_HILITEHOTTRACK
)) {
548 clrOld
= SetTextColor (hdc
, tbcd
->clrTextHighlight
);
551 clrOld
= SetTextColor (hdc
, tbcd
->clrText
);
554 DrawTextW (hdc
, lpText
, -1, rcText
, infoPtr
->dwDTFlags
);
555 SetTextColor (hdc
, clrOld
);
556 SelectObject (hdc
, hOldFont
);
562 TOOLBAR_DrawPattern (HDC hdc
, LPRECT lpRect
)
564 HBRUSH hbr
= SelectObject (hdc
, COMCTL32_hPattern55AABrush
);
565 INT cx
= lpRect
->right
- lpRect
->left
;
566 INT cy
= lpRect
->bottom
- lpRect
->top
;
567 PatBlt (hdc
, lpRect
->left
, lpRect
->top
, cx
, cy
, 0x00FA0089);
568 SelectObject (hdc
, hbr
);
573 TOOLBAR_DrawMasked (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
574 HDC hdc
, INT x
, INT y
)
576 /* FIXME: this function is a hack since it uses image list
577 internals directly */
579 HIMAGELIST himl
= GETDEFIMAGELIST(infoPtr
, 0);
587 /* create new dc's */
588 hdcImageList
= CreateCompatibleDC (0);
589 hdcMask
= CreateCompatibleDC (0);
591 /* create new bitmap */
592 hbmMask
= CreateBitmap (himl
->cx
, himl
->cy
, 1, 1, NULL
);
593 SelectObject (hdcMask
, hbmMask
);
595 /* copy the mask bitmap */
596 SelectObject (hdcImageList
, himl
->hbmMask
);
597 SetBkColor (hdcImageList
, RGB(255, 255, 255));
598 SetTextColor (hdcImageList
, RGB(0, 0, 0));
599 BitBlt (hdcMask
, 0, 0, himl
->cx
, himl
->cy
,
600 hdcImageList
, himl
->cx
* btnPtr
->iBitmap
, 0, SRCCOPY
);
602 /* draw the new mask */
603 SelectObject (hdc
, GetSysColorBrush (COLOR_3DHILIGHT
));
604 BitBlt (hdc
, x
+1, y
+1, himl
->cx
, himl
->cy
,
605 hdcMask
, 0, 0, 0xB8074A);
607 SelectObject (hdc
, GetSysColorBrush (COLOR_3DSHADOW
));
608 BitBlt (hdc
, x
, y
, himl
->cx
, himl
->cy
,
609 hdcMask
, 0, 0, 0xB8074A);
611 DeleteObject (hbmMask
);
613 DeleteDC (hdcImageList
);
618 TOOLBAR_TranslateState(TBUTTON_INFO
*btnPtr
)
622 retstate
|= (btnPtr
->fsState
& TBSTATE_CHECKED
) ? CDIS_CHECKED
: 0;
623 retstate
|= (btnPtr
->fsState
& TBSTATE_PRESSED
) ? CDIS_SELECTED
: 0;
624 retstate
|= (btnPtr
->fsState
& TBSTATE_ENABLED
) ? 0 : CDIS_DISABLED
;
625 retstate
|= (btnPtr
->fsState
& TBSTATE_MARKED
) ? CDIS_MARKED
: 0;
626 retstate
|= (btnPtr
->bHot
) ? CDIS_HOT
: 0;
627 retstate
|= (btnPtr
->fsState
& TBSTATE_INDETERMINATE
) ? CDIS_INDETERMINATE
: 0;
628 /* FIXME: don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT */
629 /* don't test TBSTATE_HIDDEN */
635 TOOLBAR_DrawButton (HWND hwnd
, TBUTTON_INFO
*btnPtr
, HDC hdc
)
637 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
638 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
639 BOOL hasDropDownArrow
= TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
) &&
640 (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
);
641 RECT rc
, rcArrow
, rcBitmap
, rcText
, rcFill
;
642 LPWSTR lpText
= NULL
;
648 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
652 CopyRect (&rcFill
, &rc
);
653 CopyRect (&rcArrow
, &rc
);
654 CopyRect(&rcBitmap
, &rc
);
655 CopyRect(&rcText
, &rc
);
657 /* get a pointer to the text */
658 lpText
= TOOLBAR_GetText(infoPtr
, btnPtr
);
660 if (hasDropDownArrow
)
662 if (dwStyle
& TBSTYLE_FLAT
)
663 rc
.right
= max(rc
.left
, rc
.right
- DDARROW_WIDTH
);
665 rc
.right
= max(rc
.left
, rc
.right
- DDARROW_WIDTH
- 2);
666 rcArrow
.left
= rc
.right
;
669 /* Center the bitmap horizontally and vertically */
670 if (dwStyle
& TBSTYLE_LIST
)
673 rcBitmap
.left
+=(infoPtr
->nButtonWidth
- infoPtr
->nBitmapWidth
) / 2;
676 rcBitmap
.top
+=2; /* this looks to be the correct value from vmware comparison - cmm */
678 rcBitmap
.top
+=(infoPtr
->nButtonHeight
- infoPtr
->nBitmapHeight
) / 2;
680 TRACE("iBitmap: %d, start=(%ld,%ld) w=%d, h=%d\n",
681 btnPtr
->iBitmap
, rcBitmap
.left
, rcBitmap
.top
,
682 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
683 TRACE ("iString: %x\n", btnPtr
->iString
);
684 TRACE ("Stringtext: %s\n", debugstr_w(lpText
));
689 InflateRect (&rcText
, -3, -3);
691 if (GETDEFIMAGELIST(infoPtr
, 0) &&
692 TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
693 /* The following test looked like this before
694 * I changed it. IE4 "Links" toolbar would not
695 * draw correctly with the original code. - GA 8/01
696 * ((dwStyle & TBSTYLE_LIST) &&
697 * ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
698 * (btnPtr->iBitmap != I_IMAGENONE))
700 if (dwStyle
& TBSTYLE_LIST
) {
701 /* LIST style w/ ICON offset is by matching native. */
702 /* Matches IE4 "Links" bar. - GA 8/01 */
703 rcText
.left
+= (infoPtr
->nBitmapWidth
+ 2);
706 rcText
.top
+= infoPtr
->nBitmapHeight
+ 1;
710 if (dwStyle
& TBSTYLE_LIST
) {
711 /* LIST style w/o ICON offset is by matching native. */
712 /* Matches IE4 "menu" bar. - GA 8/01 */
717 if (btnPtr
->fsState
& (TBSTATE_PRESSED
| TBSTATE_CHECKED
))
718 OffsetRect (&rcText
, 1, 1);
721 /* Initialize fields in all cases, because we use these later */
722 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
723 tbcd
.clrText
= comctl32_color
.clrBtnText
;
724 tbcd
.clrTextHighlight
= comctl32_color
.clrHighlightText
;
725 tbcd
.clrBtnFace
= comctl32_color
.clrBtnFace
;
726 tbcd
.clrBtnHighlight
= comctl32_color
.clrBtnHighlight
;
727 tbcd
.clrMark
= comctl32_color
.clrHighlight
;
728 tbcd
.clrHighlightHotTrack
= 0;
729 tbcd
.nStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
730 tbcd
.nHLStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
731 /* MSDN says that this is the text rectangle. */
732 /* But (why always a but) tracing of v5.7 of native shows */
733 /* that this is really a *relative* rectangle based on the */
734 /* the nmcd.rc. Also the left and top are always 0 ignoring*/
735 /* any bitmap that might be present. */
736 tbcd
.rcText
.left
= 0;
738 tbcd
.rcText
.right
= rcText
.right
- rc
.left
;
739 tbcd
.rcText
.bottom
= rcText
.bottom
- rc
.top
;
741 /* FIXME: what should these be set to ????? */
742 tbcd
.hbrMonoDither
= 0;
746 /* Issue Item Prepaint notify */
747 infoPtr
->dwItemCustDraw
= 0;
748 infoPtr
->dwItemCDFlag
= 0;
749 if (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYITEMDRAW
)
751 tbcd
.nmcd
.dwDrawStage
= CDDS_ITEMPREPAINT
;
754 tbcd
.nmcd
.dwItemSpec
= btnPtr
->idCommand
;
755 tbcd
.nmcd
.uItemState
= TOOLBAR_TranslateState(btnPtr
);
756 tbcd
.nmcd
.lItemlParam
= btnPtr
->dwData
;
757 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
758 infoPtr
->dwItemCustDraw
= ntfret
& 0xffff;
759 infoPtr
->dwItemCDFlag
= ntfret
& 0xffff0000;
760 if (infoPtr
->dwItemCustDraw
& CDRF_SKIPDEFAULT
)
762 /* save the only part of the rect that the user can change */
763 rcText
.right
= tbcd
.rcText
.right
+ rc
.left
;
764 rcText
.bottom
= tbcd
.rcText
.bottom
+ rc
.top
;
767 if (!infoPtr
->bBtnTranspnt
)
768 FillRect( hdc
, &rcFill
, GetSysColorBrush(COLOR_BTNFACE
));
771 if (btnPtr
->fsStyle
& TBSTYLE_SEP
) {
772 /* with the FLAT style, iBitmap is the width and has already */
773 /* been taken into consideration in calculating the width */
774 /* so now we need to draw the vertical separator */
775 /* empirical tests show that iBitmap can/will be non-zero */
776 /* when drawing the vertical bar... */
777 if ((dwStyle
& TBSTYLE_FLAT
) /* && (btnPtr->iBitmap == 0) */) {
778 if (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
)
779 TOOLBAR_DrawDDFlatSeparator (&rc
, hdc
, btnPtr
, infoPtr
);
781 TOOLBAR_DrawFlatSeparator (&rc
, hdc
, infoPtr
);
783 else if (btnPtr
->fsStyle
!= TBSTYLE_SEP
) {
784 FIXME("Draw some kind of separator: fsStyle=%x\n",
790 /* Determine index of image list */
791 himlDef
= GETDEFIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
794 if (!(btnPtr
->fsState
& TBSTATE_ENABLED
)) {
795 HIMAGELIST himlDis
= GETDISIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
796 if (!(dwStyle
& TBSTYLE_FLAT
) && !(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
798 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
799 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
800 if (hasDropDownArrow
)
801 DrawEdge (hdc
, &rcArrow
, EDGE_RAISED
,
802 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
805 if (hasDropDownArrow
)
807 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
+1, rcArrow
.top
+1, COLOR_3DHIGHLIGHT
);
808 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
, COLOR_3DSHADOW
);
811 if (!TOOLBAR_DrawImageList (infoPtr
, btnPtr
, himlDis
,
812 hdc
, rcBitmap
.left
, rcBitmap
.top
,
814 TOOLBAR_DrawMasked (infoPtr
, btnPtr
, hdc
, rcBitmap
.left
, rcBitmap
.top
);
816 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, btnPtr
->fsState
, dwStyle
, &rcText
, lpText
, &tbcd
);
820 /* pressed TBSTYLE_BUTTON */
821 if (btnPtr
->fsState
& TBSTATE_PRESSED
) {
822 offset
= (infoPtr
->dwItemCDFlag
& TBCDRF_NOOFFSET
) ? 0 : 1;
823 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
825 if (dwStyle
& TBSTYLE_FLAT
)
827 DrawEdge (hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
828 if (hasDropDownArrow
)
829 DrawEdge (hdc
, &rcArrow
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
833 DrawEdge (hdc
, &rc
, EDGE_SUNKEN
, BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
834 if (hasDropDownArrow
)
835 DrawEdge (hdc
, &rcArrow
, EDGE_SUNKEN
, BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
839 if (hasDropDownArrow
)
840 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
, COLOR_WINDOWFRAME
);
842 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, himlDef
,
843 hdc
, rcBitmap
.left
+offset
, rcBitmap
.top
+offset
,
846 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, btnPtr
->fsState
, dwStyle
, &rcText
, lpText
, &tbcd
);
850 /* checked TBSTYLE_CHECK */
851 if ((btnPtr
->fsStyle
& TBSTYLE_CHECK
) &&
852 (btnPtr
->fsState
& TBSTATE_CHECKED
)) {
853 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
855 if (dwStyle
& TBSTYLE_FLAT
)
856 DrawEdge (hdc
, &rc
, BDR_SUNKENOUTER
,
857 BF_RECT
| BF_ADJUST
);
859 DrawEdge (hdc
, &rc
, EDGE_SUNKEN
,
860 BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
863 TOOLBAR_DrawPattern (hdc
, &rc
);
865 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, himlDef
,
866 hdc
, rcBitmap
.left
+1, rcBitmap
.top
+1,
869 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, btnPtr
->fsState
, dwStyle
, &rcText
, lpText
, &tbcd
);
874 if (btnPtr
->fsState
& TBSTATE_INDETERMINATE
) {
875 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
876 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
877 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
879 TOOLBAR_DrawPattern (hdc
, &rc
);
880 TOOLBAR_DrawMasked (infoPtr
, btnPtr
, hdc
, rcBitmap
.left
, rcBitmap
.top
);
881 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, btnPtr
->fsState
, dwStyle
, &rcText
, lpText
, &tbcd
);
886 if (dwStyle
& TBSTYLE_FLAT
)
890 if ( infoPtr
->dwItemCDFlag
& TBCDRF_HILITEHOTTRACK
)
894 oldclr
= SetBkColor(hdc
, tbcd
.clrHighlightHotTrack
);
895 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, 0);
896 if (hasDropDownArrow
)
897 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rcArrow
, NULL
, 0, 0);
898 SetBkColor(hdc
, oldclr
);
902 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
904 DrawEdge (hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
905 if (hasDropDownArrow
)
906 DrawEdge (hdc
, &rcArrow
, BDR_RAISEDINNER
, BF_RECT
);
911 else /* The following code needs to be removed after
912 * "hot item" support has been implemented for the
913 * case where it is being de-selected.
916 FrameRect(hdc
, &rc
, GetSysColorBrush(COLOR_BTNFACE
));
917 if (hasDropDownArrow
)
918 FrameRect(hdc
, &rcArrow
, GetSysColorBrush(COLOR_BTNFACE
));
922 if (hasDropDownArrow
)
923 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
+1, rcArrow
.top
, COLOR_WINDOWFRAME
);
926 HIMAGELIST himlHot
= GETHOTIMAGELIST(infoPtr
,
927 GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
928 /* if hot, attempt to draw with himlHot, if fails, use himlDef */
929 if (!TOOLBAR_DrawImageList (infoPtr
, btnPtr
,
932 rcBitmap
.top
, ILD_NORMAL
))
933 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, himlDef
,
934 hdc
, rcBitmap
.left
, rcBitmap
.top
,
938 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, himlDef
,
939 hdc
, rcBitmap
.left
, rcBitmap
.top
,
944 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
945 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
946 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
948 if (hasDropDownArrow
)
950 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
951 DrawEdge (hdc
, &rcArrow
, EDGE_RAISED
,
952 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
953 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
, COLOR_WINDOWFRAME
);
956 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, himlDef
,
957 hdc
, rcBitmap
.left
, rcBitmap
.top
,
961 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, btnPtr
->fsState
, dwStyle
, &rcText
, lpText
, &tbcd
);
964 if (infoPtr
->dwItemCustDraw
& CDRF_NOTIFYPOSTPAINT
)
966 tbcd
.nmcd
.dwDrawStage
= CDDS_ITEMPOSTPAINT
;
969 tbcd
.nmcd
.dwItemSpec
= btnPtr
->idCommand
;
970 tbcd
.nmcd
.uItemState
= TOOLBAR_TranslateState(btnPtr
);
971 tbcd
.nmcd
.lItemlParam
= btnPtr
->dwData
;
972 tbcd
.rcText
= rcText
;
973 tbcd
.nStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
974 tbcd
.nHLStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
975 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
982 TOOLBAR_Refresh (HWND hwnd
, HDC hdc
, PAINTSTRUCT
* ps
)
984 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
985 TBUTTON_INFO
*btnPtr
;
986 INT i
, oldBKmode
= 0;
991 /* if imagelist belongs to the app, it can be changed
992 by the app after setting it */
993 if (GETDEFIMAGELIST(infoPtr
, 0) != infoPtr
->himlInt
)
995 infoPtr
->nNumBitmaps
= 0;
996 for (i
= 0; i
< infoPtr
->cimlDef
; i
++)
997 infoPtr
->nNumBitmaps
+= ImageList_GetImageCount(infoPtr
->himlDef
[i
]->himl
);
1000 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
1002 /* Send initial notify */
1003 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
1004 tbcd
.nmcd
.dwDrawStage
= CDDS_PREPAINT
;
1005 tbcd
.nmcd
.hdc
= hdc
;
1006 tbcd
.nmcd
.rc
= ps
->rcPaint
;
1007 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1008 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
1010 if (infoPtr
->bBtnTranspnt
)
1011 oldBKmode
= SetBkMode (hdc
, TRANSPARENT
);
1013 /* redraw necessary buttons */
1014 btnPtr
= infoPtr
->buttons
;
1015 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++)
1017 if(IntersectRect(&rcTemp
, &(ps
->rcPaint
), &(btnPtr
->rect
)))
1018 TOOLBAR_DrawButton (hwnd
, btnPtr
, hdc
);
1021 if (infoPtr
->bBtnTranspnt
&& (oldBKmode
!= TRANSPARENT
))
1022 SetBkMode (hdc
, oldBKmode
);
1024 if (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYPOSTPAINT
)
1026 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
1027 tbcd
.nmcd
.dwDrawStage
= CDDS_POSTPAINT
;
1028 tbcd
.nmcd
.hdc
= hdc
;
1029 tbcd
.nmcd
.rc
= ps
->rcPaint
;
1030 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1034 /***********************************************************************
1035 * TOOLBAR_MeasureString
1037 * This function gets the width and height of a string in pixels. This
1038 * is done first by using GetTextExtentPoint to get the basic width
1039 * and height. The DrawText is called with DT_CALCRECT to get the exact
1040 * width. The reason is because the text may have more than one "&" (or
1041 * prefix characters as M$ likes to call them). The prefix character
1042 * indicates where the underline goes, except for the string "&&" which
1043 * is reduced to a single "&". GetTextExtentPoint does not process these
1044 * only DrawText does. Note that the TBSTYLE_NOPREFIX is handled here.
1047 TOOLBAR_MeasureString(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
1048 HDC hdc
, LPSIZE lpSize
)
1055 if (!(btnPtr
->fsState
& TBSTATE_HIDDEN
) )
1057 LPWSTR lpText
= TOOLBAR_GetText(infoPtr
, btnPtr
);
1059 if(lpText
!= NULL
) {
1060 /* first get size of all the text */
1061 GetTextExtentPoint32W (hdc
, lpText
, strlenW (lpText
), lpSize
);
1063 /* feed above size into the rectangle for DrawText */
1064 myrect
.left
= myrect
.top
= 0;
1065 myrect
.right
= lpSize
->cx
;
1066 myrect
.bottom
= lpSize
->cy
;
1068 /* Use DrawText to get true size as drawn (less pesky "&") */
1069 DrawTextW (hdc
, lpText
, -1, &myrect
, DT_VCENTER
| DT_SINGLELINE
|
1070 DT_CALCRECT
| ((btnPtr
->fsStyle
& TBSTYLE_NOPREFIX
) ?
1073 /* feed back to caller */
1074 lpSize
->cx
= myrect
.right
;
1075 lpSize
->cy
= myrect
.bottom
;
1079 TRACE("string size %ld x %ld!\n", lpSize
->cx
, lpSize
->cy
);
1082 /***********************************************************************
1083 * TOOLBAR_CalcStrings
1085 * This function walks through each string and measures it and returns
1086 * the largest height and width to caller.
1089 TOOLBAR_CalcStrings (HWND hwnd
, LPSIZE lpSize
)
1091 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1092 TBUTTON_INFO
*btnPtr
;
1102 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
1104 btnPtr
= infoPtr
->buttons
;
1105 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1106 if(TOOLBAR_HasText(infoPtr
, btnPtr
))
1108 TOOLBAR_MeasureString(infoPtr
, btnPtr
, hdc
, &sz
);
1109 if (sz
.cx
> lpSize
->cx
)
1111 if (sz
.cy
> lpSize
->cy
)
1116 SelectObject (hdc
, hOldFont
);
1117 ReleaseDC (hwnd
, hdc
);
1119 TRACE("max string size %ld x %ld!\n", lpSize
->cx
, lpSize
->cy
);
1122 /***********************************************************************
1123 * TOOLBAR_WrapToolbar
1125 * This function walks through the buttons and seperators in the
1126 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
1127 * wrapping should occur based on the width of the toolbar window.
1128 * It does *not* calculate button placement itself. That task
1129 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
1130 * the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE
1131 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
1133 * Note: TBSTYLE_WRAPABLE or TBSTYLE_EX_UNDOC1 can be used also to allow
1134 * vertical toolbar lists.
1138 TOOLBAR_WrapToolbar( HWND hwnd
, DWORD dwStyle
)
1140 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1141 TBUTTON_INFO
*btnPtr
;
1144 BOOL bWrap
, bButtonWrap
;
1146 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
1147 /* no layout is necessary. Applications may use this style */
1148 /* to perform their own layout on the toolbar. */
1149 if( !(dwStyle
& TBSTYLE_WRAPABLE
) &&
1150 !(infoPtr
->dwExStyle
& TBSTYLE_EX_UNDOC1
) ) return;
1152 btnPtr
= infoPtr
->buttons
;
1153 x
= infoPtr
->nIndent
;
1155 /* this can get the parents width, to know how far we can extend
1156 * this toolbar. We cannot use its height, as there may be multiple
1157 * toolbars in a rebar control
1159 GetClientRect( GetParent(hwnd
), &rc
);
1160 infoPtr
->nWidth
= rc
.right
- rc
.left
;
1161 bButtonWrap
= FALSE
;
1163 TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
1164 infoPtr
->nButtonWidth
, infoPtr
->nBitmapWidth
, infoPtr
->nWidth
,
1167 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++ )
1170 btnPtr
[i
].fsState
&= ~TBSTATE_WRAP
;
1172 if (btnPtr
[i
].fsState
& TBSTATE_HIDDEN
)
1175 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1176 /* it is the actual width of the separator. This is used for */
1177 /* custom controls in toolbars. */
1179 /* TBSTYLE_DROPDOWN separators are treated as buttons for */
1180 /* width. - GA 8/01 */
1181 if ((btnPtr
[i
].fsStyle
& TBSTYLE_SEP
) &&
1182 !(btnPtr
[i
].fsStyle
& TBSTYLE_DROPDOWN
))
1183 cx
= (btnPtr
[i
].iBitmap
> 0) ?
1184 btnPtr
[i
].iBitmap
: SEPARATOR_WIDTH
;
1186 cx
= infoPtr
->nButtonWidth
;
1188 /* Two or more adjacent separators form a separator group. */
1189 /* The first separator in a group should be wrapped to the */
1190 /* next row if the previous wrapping is on a button. */
1192 (btnPtr
[i
].fsStyle
& TBSTYLE_SEP
) &&
1193 (i
+ 1 < infoPtr
->nNumButtons
) &&
1194 (btnPtr
[i
+ 1].fsStyle
& TBSTYLE_SEP
) )
1196 TRACE("wrap point 1 btn %d style %02x\n", i
, btnPtr
[i
].fsStyle
);
1197 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1198 x
= infoPtr
->nIndent
;
1200 bButtonWrap
= FALSE
;
1204 /* The layout makes sure the bitmap is visible, but not the button. */
1205 /* Test added to also wrap after a button that starts a row but */
1206 /* is bigger than the area. - GA 8/01 */
1207 if (( x
+ cx
- (infoPtr
->nButtonWidth
- infoPtr
->nBitmapWidth
) / 2
1208 > infoPtr
->nWidth
) ||
1209 ((x
== infoPtr
->nIndent
) && (cx
> infoPtr
->nWidth
)))
1211 BOOL bFound
= FALSE
;
1213 /* If the current button is a separator and not hidden, */
1214 /* go to the next until it reaches a non separator. */
1215 /* Wrap the last separator if it is before a button. */
1216 while( ( ((btnPtr
[i
].fsStyle
& TBSTYLE_SEP
) &&
1217 !(btnPtr
[i
].fsStyle
& TBSTYLE_DROPDOWN
)) ||
1218 (btnPtr
[i
].fsState
& TBSTATE_HIDDEN
) ) &&
1219 i
< infoPtr
->nNumButtons
)
1225 if( bFound
&& i
< infoPtr
->nNumButtons
)
1228 TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
1229 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1230 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1231 x
= infoPtr
->nIndent
;
1232 bButtonWrap
= FALSE
;
1235 else if ( i
>= infoPtr
->nNumButtons
)
1238 /* If the current button is not a separator, find the last */
1239 /* separator and wrap it. */
1240 for ( j
= i
- 1; j
>= 0 && !(btnPtr
[j
].fsState
& TBSTATE_WRAP
); j
--)
1242 if ((btnPtr
[j
].fsStyle
& TBSTYLE_SEP
) &&
1243 !(btnPtr
[j
].fsState
& TBSTATE_HIDDEN
))
1247 TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
1248 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1249 x
= infoPtr
->nIndent
;
1250 btnPtr
[j
].fsState
|= TBSTATE_WRAP
;
1251 bButtonWrap
= FALSE
;
1256 /* If no separator available for wrapping, wrap one of */
1257 /* non-hidden previous button. */
1261 j
>= 0 && !(btnPtr
[j
].fsState
& TBSTATE_WRAP
); j
--)
1263 if (btnPtr
[j
].fsState
& TBSTATE_HIDDEN
)
1268 TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
1269 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1270 x
= infoPtr
->nIndent
;
1271 btnPtr
[j
].fsState
|= TBSTATE_WRAP
;
1277 /* If all above failed, wrap the current button. */
1280 TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
1281 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1282 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1284 x
= infoPtr
->nIndent
;
1285 if (btnPtr
[i
].fsStyle
& TBSTYLE_SEP
)
1286 bButtonWrap
= FALSE
;
1292 TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
1293 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1300 /***********************************************************************
1301 * TOOLBAR_CalcToolbar
1303 * This function calculates button and separator placement. It first
1304 * calculates the button sizes, gets the toolbar window width and then
1305 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
1306 * on. It assigns a new location to each item and sends this location to
1307 * the tooltip window if appropriate. Finally, it updates the rcBound
1308 * rect and calculates the new required toolbar window height.
1312 TOOLBAR_CalcToolbar (HWND hwnd
)
1314 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
1315 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1316 TBUTTON_INFO
*btnPtr
;
1317 INT i
, nRows
, nSepRows
;
1321 BOOL usesBitmaps
= FALSE
;
1322 BOOL hasDropDownArrows
= TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
);
1324 TOOLBAR_CalcStrings (hwnd
, &sizeString
);
1326 for (i
= 0; i
< infoPtr
->nNumButtons
&& !usesBitmaps
; i
++)
1328 if (TOOLBAR_IsValidBitmapIndex(infoPtr
,infoPtr
->buttons
[i
].iBitmap
))
1331 if (dwStyle
& TBSTYLE_LIST
)
1333 infoPtr
->nButtonHeight
= max((usesBitmaps
) ? infoPtr
->nBitmapHeight
:
1334 0, sizeString
.cy
) + infoPtr
->szPadding
.cy
;
1335 infoPtr
->nButtonWidth
= ((usesBitmaps
) ? infoPtr
->nBitmapWidth
:
1336 0) + sizeString
.cx
+ 6;
1337 TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n",
1338 infoPtr
->nButtonWidth
, infoPtr
->nButtonHeight
, usesBitmaps
,
1339 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
1340 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
1343 if (sizeString
.cy
> 0)
1346 infoPtr
->nButtonHeight
= sizeString
.cy
+
1347 2 + /* this is the space to separate text from bitmap */
1348 infoPtr
->nBitmapHeight
+ 6;
1350 infoPtr
->nButtonHeight
= sizeString
.cy
+ 6;
1352 else if (infoPtr
->nButtonHeight
< infoPtr
->nBitmapHeight
+ 6)
1353 infoPtr
->nButtonHeight
= infoPtr
->nBitmapHeight
+ 6;
1355 if (sizeString
.cx
> infoPtr
->nBitmapWidth
)
1356 infoPtr
->nButtonWidth
= sizeString
.cx
+ 6;
1357 else if (infoPtr
->nButtonWidth
< infoPtr
->nBitmapWidth
+ 6)
1358 infoPtr
->nButtonWidth
= infoPtr
->nBitmapWidth
+ 6;
1361 if ( infoPtr
->cxMin
>= 0 && infoPtr
->nButtonWidth
< infoPtr
->cxMin
)
1362 infoPtr
->nButtonWidth
= infoPtr
->cxMin
;
1363 if ( infoPtr
->cxMax
> 0 && infoPtr
->nButtonWidth
> infoPtr
->cxMax
)
1364 infoPtr
->nButtonWidth
= infoPtr
->cxMax
;
1366 TOOLBAR_WrapToolbar( hwnd
, dwStyle
);
1368 x
= infoPtr
->nIndent
;
1372 * We will set the height below, and we set the width on entry
1373 * so we do not reset them here..
1376 GetClientRect( hwnd
, &rc
);
1377 /* get initial values for toolbar */
1378 infoPtr
->nWidth
= rc
.right
- rc
.left
;
1379 infoPtr
->nHeight
= rc
.bottom
- rc
.top
;
1382 /* from above, minimum is a button, and possible text */
1383 cx
= infoPtr
->nButtonWidth
;
1385 /* cannot use just ButtonHeight, we may have no buttons! */
1386 if (infoPtr
->nNumButtons
> 0)
1387 infoPtr
->nHeight
= infoPtr
->nButtonHeight
;
1389 cy
= infoPtr
->nHeight
;
1391 nRows
= nSepRows
= 0;
1393 infoPtr
->rcBound
.top
= y
;
1394 infoPtr
->rcBound
.left
= x
;
1395 infoPtr
->rcBound
.bottom
= y
+ cy
;
1396 infoPtr
->rcBound
.right
= x
;
1398 btnPtr
= infoPtr
->buttons
;
1400 /* do not base height/width on parent, if the parent is a */
1401 /* rebar control it could have multiple rows of toolbars */
1402 /* GetClientRect( GetParent(hwnd), &rc ); */
1403 /* cx = rc.right - rc.left; */
1404 /* cy = rc.bottom - rc.top; */
1406 TRACE("cy=%d\n", cy
);
1408 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++ )
1411 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
1413 SetRectEmpty (&btnPtr
->rect
);
1417 cy
= infoPtr
->nHeight
;
1419 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1420 /* it is the actual width of the separator. This is used for */
1421 /* custom controls in toolbars. */
1422 if (btnPtr
->fsStyle
& TBSTYLE_SEP
) {
1423 if (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
) {
1424 cy
= (btnPtr
->iBitmap
> 0) ?
1425 btnPtr
->iBitmap
: SEPARATOR_WIDTH
;
1426 cx
= infoPtr
->nButtonWidth
;
1429 cx
= (btnPtr
->iBitmap
> 0) ?
1430 btnPtr
->iBitmap
: SEPARATOR_WIDTH
;
1434 if (btnPtr
->fsStyle
& TBSTYLE_AUTOSIZE
)
1441 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
1443 TOOLBAR_MeasureString(infoPtr
, btnPtr
, hdc
, &sz
);
1445 SelectObject (hdc
, hOldFont
);
1446 ReleaseDC (hwnd
, hdc
);
1448 /* Fudge amount measured against IE4 "menu" and "Links" */
1449 /* toolbars with native control (v4.71). - GA 8/01 */
1450 cx
= sz
.cx
+ 6 + 5 + 5;
1451 if ((dwStyle
& TBSTYLE_LIST
) &&
1452 (TOOLBAR_TestImageExist (infoPtr
, btnPtr
, GETDEFIMAGELIST(infoPtr
,0))))
1453 cx
+= infoPtr
->nBitmapWidth
;
1456 cx
= infoPtr
->nButtonWidth
;
1458 if (hasDropDownArrows
&& (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
))
1459 cx
+= DDARROW_WIDTH
;
1461 if (btnPtr
->fsState
& TBSTATE_WRAP
)
1464 SetRect (&btnPtr
->rect
, x
, y
, x
+ cx
, y
+ cy
);
1466 if (infoPtr
->rcBound
.left
> x
)
1467 infoPtr
->rcBound
.left
= x
;
1468 if (infoPtr
->rcBound
.right
< x
+ cx
)
1469 infoPtr
->rcBound
.right
= x
+ cx
;
1470 if (infoPtr
->rcBound
.bottom
< y
+ cy
)
1471 infoPtr
->rcBound
.bottom
= y
+ cy
;
1473 /* Set the toolTip only for non-hidden, non-separator button */
1474 if (infoPtr
->hwndToolTip
&& !(btnPtr
->fsStyle
& TBSTYLE_SEP
))
1478 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
1479 ti
.cbSize
= sizeof(TTTOOLINFOA
);
1481 ti
.uId
= btnPtr
->idCommand
;
1482 ti
.rect
= btnPtr
->rect
;
1483 SendMessageA (infoPtr
->hwndToolTip
, TTM_NEWTOOLRECTA
,
1487 /* btnPtr->nRow is zero based. The space between the rows is */
1488 /* also considered as a row. */
1489 btnPtr
->nRow
= nRows
+ nSepRows
;
1491 TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n",
1492 i
, btnPtr
->fsStyle
, bWrap
, nRows
, nSepRows
, btnPtr
->nRow
,
1497 if ( !(btnPtr
->fsStyle
& TBSTYLE_SEP
) )
1501 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1502 /* it is the actual width of the separator. This is used for */
1503 /* custom controls in toolbars. */
1504 if ( !(btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
))
1505 y
+= cy
+ ( (btnPtr
->iBitmap
> 0 ) ?
1506 btnPtr
->iBitmap
: SEPARATOR_WIDTH
) * 2 /3;
1510 /* nSepRows is used to calculate the extra height follwoing */
1514 x
= infoPtr
->nIndent
;
1516 /* Increment row number unless this is the last button */
1517 /* and it has Wrap set. */
1518 if (i
!= infoPtr
->nNumButtons
-1)
1525 /* infoPtr->nRows is the number of rows on the toolbar */
1526 infoPtr
->nRows
= nRows
+ nSepRows
+ 1;
1529 /********************************************************************
1530 * The following while interesting, does not match the values *
1531 * created above for the button rectangles, nor the rcBound rect. *
1532 * We will comment it out and remove it later. *
1534 * The problem showed up as heights in the pager control that was *
1536 ********************************************************************/
1538 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
1540 infoPtr
->nHeight
= TOP_BORDER
+ (nRows
+ 1) * infoPtr
->nButtonHeight
+
1541 nSepRows
* (SEPARATOR_WIDTH
* 2 / 3) +
1542 nSepRows
* (infoPtr
->nBitmapHeight
+ 1) +
1546 infoPtr
->nHeight
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
1548 TRACE("toolbar height %d, button width %d\n", infoPtr
->nHeight
, infoPtr
->nButtonWidth
);
1553 TOOLBAR_InternalHitTest (HWND hwnd
, LPPOINT lpPt
)
1555 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1556 TBUTTON_INFO
*btnPtr
;
1559 btnPtr
= infoPtr
->buttons
;
1560 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1561 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
1564 if (btnPtr
->fsStyle
& TBSTYLE_SEP
) {
1565 if (PtInRect (&btnPtr
->rect
, *lpPt
)) {
1566 TRACE(" ON SEPARATOR %d!\n", i
);
1571 if (PtInRect (&btnPtr
->rect
, *lpPt
)) {
1572 TRACE(" ON BUTTON %d!\n", i
);
1578 TRACE(" NOWHERE!\n");
1584 TOOLBAR_GetButtonIndex (TOOLBAR_INFO
*infoPtr
, INT idCommand
, BOOL CommandIsIndex
)
1586 TBUTTON_INFO
*btnPtr
;
1589 if (CommandIsIndex
) {
1590 TRACE("command is really index command=%d\n", idCommand
);
1591 if (idCommand
>= infoPtr
->nNumButtons
) return -1;
1594 btnPtr
= infoPtr
->buttons
;
1595 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1596 if (btnPtr
->idCommand
== idCommand
) {
1597 TRACE("command=%d index=%d\n", idCommand
, i
);
1601 TRACE("no index found for command=%d\n", idCommand
);
1607 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO
*infoPtr
, INT nIndex
)
1609 TBUTTON_INFO
*btnPtr
;
1612 if ((nIndex
< 0) || (nIndex
> infoPtr
->nNumButtons
))
1615 /* check index button */
1616 btnPtr
= &infoPtr
->buttons
[nIndex
];
1617 if ((btnPtr
->fsStyle
& TBSTYLE_CHECKGROUP
) == TBSTYLE_CHECKGROUP
) {
1618 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1622 /* check previous buttons */
1623 nRunIndex
= nIndex
- 1;
1624 while (nRunIndex
>= 0) {
1625 btnPtr
= &infoPtr
->buttons
[nRunIndex
];
1626 if ((btnPtr
->fsStyle
& TBSTYLE_CHECKGROUP
) == TBSTYLE_CHECKGROUP
) {
1627 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1635 /* check next buttons */
1636 nRunIndex
= nIndex
+ 1;
1637 while (nRunIndex
< infoPtr
->nNumButtons
) {
1638 btnPtr
= &infoPtr
->buttons
[nRunIndex
];
1639 if ((btnPtr
->fsStyle
& TBSTYLE_CHECKGROUP
) == TBSTYLE_CHECKGROUP
) {
1640 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1653 TOOLBAR_RelayEvent (HWND hwndTip
, HWND hwndMsg
, UINT uMsg
,
1654 WPARAM wParam
, LPARAM lParam
)
1660 msg
.wParam
= wParam
;
1661 msg
.lParam
= lParam
;
1662 msg
.time
= GetMessageTime ();
1663 msg
.pt
.x
= LOWORD(GetMessagePos ());
1664 msg
.pt
.y
= HIWORD(GetMessagePos ());
1666 SendMessageA (hwndTip
, TTM_RELAYEVENT
, 0, (LPARAM
)&msg
);
1670 /***********************************************************************
1671 * TOOLBAR_CustomizeDialogProc
1672 * This function implements the toolbar customization dialog.
1674 static INT_PTR CALLBACK
1675 TOOLBAR_CustomizeDialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1677 PCUSTDLG_INFO custInfo
= (PCUSTDLG_INFO
)GetWindowLongA (hwnd
, DWL_USER
);
1678 PCUSTOMBUTTON btnInfo
;
1680 TOOLBAR_INFO
*infoPtr
= custInfo
? custInfo
->tbInfo
: NULL
;
1685 custInfo
= (PCUSTDLG_INFO
)lParam
;
1686 SetWindowLongA (hwnd
, DWL_USER
, (DWORD
)custInfo
);
1694 infoPtr
= custInfo
->tbInfo
;
1696 /* send TBN_QUERYINSERT notification */
1697 nmtb
.iItem
= custInfo
->tbInfo
->nNumButtons
;
1699 if (!TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_QUERYINSERT
))
1702 /* Send TBN_INITCUSTOMIZE notification */
1703 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_INITCUSTOMIZE
) ==
1706 FIXME("TBNRF_HIDEHELP not supported\n");
1709 /* add items to 'toolbar buttons' list and check if removable */
1710 for (i
= 0; i
< custInfo
->tbInfo
->nNumButtons
; i
++)
1712 btnInfo
= (PCUSTOMBUTTON
)COMCTL32_Alloc(sizeof(CUSTOMBUTTON
));
1713 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1714 btnInfo
->btn
.fsStyle
= TBSTYLE_SEP
;
1715 btnInfo
->bVirtual
= FALSE
;
1716 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1718 /* send TBN_QUERYDELETE notification */
1719 btnInfo
->bRemovable
= TOOLBAR_IsButtonRemovable(infoPtr
, i
, btnInfo
);
1721 index
= (int)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_ADDSTRING
, 0, 0);
1722 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1725 /* insert separator button into 'available buttons' list */
1726 btnInfo
= (PCUSTOMBUTTON
)COMCTL32_Alloc(sizeof(CUSTOMBUTTON
));
1727 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1728 btnInfo
->btn
.fsStyle
= TBSTYLE_SEP
;
1729 btnInfo
->bVirtual
= FALSE
;
1730 btnInfo
->bRemovable
= TRUE
;
1731 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1732 index
= (int)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, (LPARAM
)btnInfo
);
1733 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1735 /* insert all buttons into dsa */
1738 /* send TBN_GETBUTTONINFO notification */
1741 nmtb
.pszText
= Buffer
;
1744 /* Clear previous button's text */
1745 ZeroMemory(nmtb
.pszText
, nmtb
.cchText
* sizeof(WCHAR
));
1747 if (!TOOLBAR_GetButtonInfo(infoPtr
, &nmtb
))
1750 TRACE("WM_INITDIALOG style: %x iItem(%d) idCommand(%d) iString(%d) %s\n",
1751 nmtb
.tbButton
.fsStyle
, i
,
1752 nmtb
.tbButton
.idCommand
,
1753 nmtb
.tbButton
.iString
,
1754 nmtb
.tbButton
.iString
>= 0 ? debugstr_w(infoPtr
->strings
[nmtb
.tbButton
.iString
])
1757 /* insert button into the apropriate list */
1758 index
= TOOLBAR_GetButtonIndex (custInfo
->tbInfo
, nmtb
.tbButton
.idCommand
, FALSE
);
1761 btnInfo
= (PCUSTOMBUTTON
)COMCTL32_Alloc(sizeof(CUSTOMBUTTON
));
1762 btnInfo
->bVirtual
= FALSE
;
1763 btnInfo
->bRemovable
= TRUE
;
1765 index
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, 0);
1766 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
,
1767 LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1771 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
,
1772 IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1775 memcpy (&btnInfo
->btn
, &nmtb
.tbButton
, sizeof(TBBUTTON
));
1776 if (!(nmtb
.tbButton
.fsStyle
& TBSTYLE_SEP
))
1778 if (lstrlenW(nmtb
.pszText
))
1779 lstrcpyW(btnInfo
->text
, nmtb
.pszText
);
1780 else if (nmtb
.tbButton
.iString
>= 0 &&
1781 nmtb
.tbButton
.iString
< infoPtr
->nNumStrings
)
1783 lstrcpyW(btnInfo
->text
,
1784 infoPtr
->strings
[nmtb
.tbButton
.iString
]);
1789 /* select first item in the 'available' list */
1790 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, 0, 0);
1792 /* append 'virtual' separator button to the 'toolbar buttons' list */
1793 btnInfo
= (PCUSTOMBUTTON
)COMCTL32_Alloc(sizeof(CUSTOMBUTTON
));
1794 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1795 btnInfo
->btn
.fsStyle
= TBSTYLE_SEP
;
1796 btnInfo
->bVirtual
= TRUE
;
1797 btnInfo
->bRemovable
= FALSE
;
1798 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1799 index
= (int)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_ADDSTRING
, 0, (LPARAM
)btnInfo
);
1800 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1802 /* select last item in the 'toolbar' list */
1803 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
, 0);
1804 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETTOPINDEX
, index
, 0);
1806 /* set focus and disable buttons */
1807 PostMessageA (hwnd
, WM_USER
, 0, 0);
1812 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1813 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1814 EnableWindow (GetDlgItem (hwnd
,IDC_REMOVE_BTN
), FALSE
);
1815 SetFocus (GetDlgItem (hwnd
, IDC_TOOLBARBTN_LBOX
));
1819 EndDialog(hwnd
, FALSE
);
1823 switch (LOWORD(wParam
))
1825 case IDC_TOOLBARBTN_LBOX
:
1826 if (HIWORD(wParam
) == LBN_SELCHANGE
)
1828 PCUSTOMBUTTON btnInfo
;
1833 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1834 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1836 /* send TBN_QUERYINSERT notification */
1838 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1841 /* get list box item */
1842 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1844 if (index
== (count
- 1))
1846 /* last item (virtual separator) */
1847 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1848 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1850 else if (index
== (count
- 2))
1852 /* second last item (last non-virtual item) */
1853 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1854 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1856 else if (index
== 0)
1859 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1860 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1864 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1865 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1868 EnableWindow (GetDlgItem (hwnd
,IDC_REMOVE_BTN
), btnInfo
->bRemovable
);
1872 case IDC_MOVEUP_BTN
:
1874 PCUSTOMBUTTON btnInfo
;
1878 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1879 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1880 TRACE("Move up: index %d\n", index
);
1882 /* send TBN_QUERYINSERT notification */
1885 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1888 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1890 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1891 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
-1, 0);
1892 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
-1, (LPARAM
)btnInfo
);
1893 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
-1 , 0);
1896 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1897 else if (index
>= (count
- 3))
1898 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1900 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
1901 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
-1, (LPARAM
)&(btnInfo
->btn
));
1906 case IDC_MOVEDN_BTN
: /* move down */
1908 PCUSTOMBUTTON btnInfo
;
1912 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1913 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1914 TRACE("Move up: index %d\n", index
);
1916 /* send TBN_QUERYINSERT notification */
1918 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1921 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1923 /* move button down */
1924 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1925 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
+1, 0);
1926 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
+1, (LPARAM
)btnInfo
);
1927 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
+1 , 0);
1930 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1931 else if (index
>= (count
- 3))
1932 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1934 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
1935 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
+1, (LPARAM
)&(btnInfo
->btn
));
1940 case IDC_REMOVE_BTN
: /* remove button */
1942 PCUSTOMBUTTON btnInfo
;
1945 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1947 if (LB_ERR
== index
)
1950 TRACE("Remove: index %d\n", index
);
1952 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
,
1953 LB_GETITEMDATA
, index
, 0);
1955 /* send TBN_QUERYDELETE notification */
1956 if (TOOLBAR_IsButtonRemovable(infoPtr
, index
, btnInfo
))
1958 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1959 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1960 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
, 0);
1962 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
1964 /* insert into 'available button' list */
1965 if (!(btnInfo
->btn
.fsStyle
& TBSTYLE_SEP
))
1967 index
= (int)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, 0);
1968 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1971 COMCTL32_Free (btnInfo
);
1976 case IDOK
: /* Add button */
1981 count
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1982 index
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1983 TRACE("Add: index %d\n", index
);
1985 /* send TBN_QUERYINSERT notification */
1987 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1990 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1994 /* remove from 'available buttons' list */
1995 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1996 if (index
== count
-1)
1997 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, index
-1 , 0);
1999 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, index
, 0);
2003 PCUSTOMBUTTON btnNew
;
2005 /* duplicate 'separator' button */
2006 btnNew
= (PCUSTOMBUTTON
)COMCTL32_Alloc (sizeof(CUSTOMBUTTON
));
2007 memcpy (btnNew
, btnInfo
, sizeof(CUSTOMBUTTON
));
2011 /* insert into 'toolbar button' list */
2012 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
2013 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
, 0);
2014 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
2016 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
, (LPARAM
)&(btnInfo
->btn
));
2022 EndDialog(hwnd
, FALSE
);
2032 /* delete items from 'toolbar buttons' listbox*/
2033 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2034 for (i
= 0; i
< count
; i
++)
2036 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, i
, 0);
2037 COMCTL32_Free(btnInfo
);
2038 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, 0, 0);
2040 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_RESETCONTENT
, 0, 0);
2043 /* delete items from 'available buttons' listbox*/
2044 count
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2045 for (i
= 0; i
< count
; i
++)
2047 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETITEMDATA
, i
, 0);
2048 COMCTL32_Free(btnInfo
);
2049 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, i
, 0);
2051 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_RESETCONTENT
, 0, 0);
2056 if (wParam
== IDC_AVAILBTN_LBOX
|| wParam
== IDC_TOOLBARBTN_LBOX
)
2058 LPDRAWITEMSTRUCT lpdis
= (LPDRAWITEMSTRUCT
)lParam
;
2059 DWORD dwStyle
= GetWindowLongA (infoPtr
->hwndSelf
, GWL_STYLE
);
2064 COLORREF oldText
= 0;
2068 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, wParam
, LB_GETITEMDATA
, (WPARAM
)lpdis
->itemID
, 0);
2069 if (btnInfo
== NULL
)
2071 FIXME("btnInfo invalid!\n");
2075 /* set colors and select objects */
2076 oldBk
= SetBkColor (lpdis
->hDC
, (lpdis
->itemState
& ODS_FOCUS
)?comctl32_color
.clrHighlight
:comctl32_color
.clrWindow
);
2077 if (btnInfo
->bVirtual
)
2078 oldText
= SetTextColor (lpdis
->hDC
, comctl32_color
.clrGrayText
);
2080 oldText
= SetTextColor (lpdis
->hDC
, (lpdis
->itemState
& ODS_FOCUS
)?comctl32_color
.clrHighlightText
:comctl32_color
.clrWindowText
);
2081 hPen
= CreatePen( PS_SOLID
, 1,
2082 GetSysColor( (lpdis
->itemState
& ODS_SELECTED
)?COLOR_HIGHLIGHT
:COLOR_WINDOW
));
2083 hOldPen
= SelectObject (lpdis
->hDC
, hPen
);
2084 hOldBrush
= SelectObject (lpdis
->hDC
, GetSysColorBrush ((lpdis
->itemState
& ODS_FOCUS
)?COLOR_HIGHLIGHT
:COLOR_WINDOW
));
2086 /* fill background rectangle */
2087 Rectangle (lpdis
->hDC
, lpdis
->rcItem
.left
, lpdis
->rcItem
.top
,
2088 lpdis
->rcItem
.right
, lpdis
->rcItem
.bottom
);
2090 /* calculate button and text rectangles */
2091 CopyRect (&rcButton
, &lpdis
->rcItem
);
2092 InflateRect (&rcButton
, -1, -1);
2093 CopyRect (&rcText
, &rcButton
);
2094 rcButton
.right
= rcButton
.left
+ custInfo
->tbInfo
->nBitmapWidth
+ 6;
2095 rcText
.left
= rcButton
.right
+ 2;
2097 /* draw focus rectangle */
2098 if (lpdis
->itemState
& ODS_FOCUS
)
2099 DrawFocusRect (lpdis
->hDC
, &lpdis
->rcItem
);
2102 if (!(dwStyle
& TBSTYLE_FLAT
))
2103 DrawEdge (lpdis
->hDC
, &rcButton
, EDGE_RAISED
, BF_RECT
|BF_MIDDLE
|BF_SOFT
);
2105 /* draw image and text */
2106 if ((btnInfo
->btn
.fsStyle
& TBSTYLE_SEP
) == 0) {
2107 HIMAGELIST himl
= GETDEFIMAGELIST(infoPtr
, GETHIMLID(infoPtr
,
2108 btnInfo
->btn
.iBitmap
));
2109 ImageList_Draw (himl
, GETIBITMAP(infoPtr
, btnInfo
->btn
.iBitmap
),
2110 lpdis
->hDC
, rcButton
.left
+3, rcButton
.top
+3, ILD_NORMAL
);
2112 DrawTextW (lpdis
->hDC
, btnInfo
->text
, -1, &rcText
,
2113 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
2115 /* delete objects and reset colors */
2116 SelectObject (lpdis
->hDC
, hOldBrush
);
2117 SelectObject (lpdis
->hDC
, hOldPen
);
2118 SetBkColor (lpdis
->hDC
, oldBk
);
2119 SetTextColor (lpdis
->hDC
, oldText
);
2120 DeleteObject( hPen
);
2125 case WM_MEASUREITEM
:
2126 if (wParam
== IDC_AVAILBTN_LBOX
|| wParam
== IDC_TOOLBARBTN_LBOX
)
2128 MEASUREITEMSTRUCT
*lpmis
= (MEASUREITEMSTRUCT
*)lParam
;
2130 if (custInfo
&& custInfo
->tbInfo
)
2131 lpmis
->itemHeight
= custInfo
->tbInfo
->nBitmapHeight
+ 8;
2133 lpmis
->itemHeight
= 15 + 8; /* default height */
2145 /***********************************************************************
2146 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
2150 TOOLBAR_AddBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2152 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2153 LPTBADDBITMAP lpAddBmp
= (LPTBADDBITMAP
)lParam
;
2154 INT nIndex
= 0, nButtons
, nCount
;
2158 TRACE("hwnd=%p wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2162 if (lpAddBmp
->hInst
== HINST_COMMCTRL
)
2164 if ((lpAddBmp
->nID
& ~1) == IDB_STD_SMALL_COLOR
)
2166 else if ((lpAddBmp
->nID
& ~1) == IDB_VIEW_SMALL_COLOR
)
2168 else if ((lpAddBmp
->nID
& ~1) == IDB_HIST_SMALL_COLOR
)
2173 TRACE ("adding %d internal bitmaps!\n", nButtons
);
2175 /* Windows resize all the buttons to the size of a newly added standard image */
2176 if (lpAddBmp
->nID
& 1)
2179 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
2180 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
2182 SendMessageA (hwnd
, TB_SETBITMAPSIZE
, 0,
2183 MAKELPARAM((WORD
)24, (WORD
)24));
2184 SendMessageA (hwnd
, TB_SETBUTTONSIZE
, 0,
2185 MAKELPARAM((WORD
)31, (WORD
)30));
2190 SendMessageA (hwnd
, TB_SETBITMAPSIZE
, 0,
2191 MAKELPARAM((WORD
)16, (WORD
)16));
2192 SendMessageA (hwnd
, TB_SETBUTTONSIZE
, 0,
2193 MAKELPARAM((WORD
)22, (WORD
)22));
2196 TOOLBAR_CalcToolbar (hwnd
);
2200 nButtons
= (INT
)wParam
;
2204 TRACE ("adding %d bitmaps!\n", nButtons
);
2207 if (!infoPtr
->cimlDef
) {
2208 /* create new default image list */
2209 TRACE ("creating default image list!\n");
2211 himlDef
= ImageList_Create (infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
,
2212 ILC_COLOR
| ILC_MASK
, nButtons
, 2);
2213 TOOLBAR_InsertImageList(&infoPtr
->himlDef
, &infoPtr
->cimlDef
, himlDef
, 0);
2214 infoPtr
->himlInt
= himlDef
;
2217 himlDef
= GETDEFIMAGELIST(infoPtr
, 0);
2221 WARN("No default image list available\n");
2225 nCount
= ImageList_GetImageCount(himlDef
);
2227 /* Add bitmaps to the default image list */
2228 if (lpAddBmp
->hInst
== NULL
)
2231 HBITMAP hOldBitmapBitmap
, hOldBitmapLoad
;
2232 HDC hdcImage
, hdcBitmap
;
2234 /* copy the bitmap before adding it so that the user's bitmap
2235 * doesn't get modified.
2237 GetObjectA ((HBITMAP
)lpAddBmp
->nID
, sizeof(BITMAP
), (LPVOID
)&bmp
);
2239 hdcImage
= CreateCompatibleDC(0);
2240 hdcBitmap
= CreateCompatibleDC(0);
2242 /* create new bitmap */
2243 hbmLoad
= CreateBitmap (bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
, bmp
.bmBitsPixel
, NULL
);
2244 hOldBitmapBitmap
= SelectObject(hdcBitmap
, (HBITMAP
)lpAddBmp
->nID
);
2245 hOldBitmapLoad
= SelectObject(hdcImage
, hbmLoad
);
2247 /* Copy the user's image */
2248 BitBlt (hdcImage
, 0, 0, bmp
.bmWidth
, bmp
.bmHeight
,
2249 hdcBitmap
, 0, 0, SRCCOPY
);
2251 SelectObject (hdcImage
, hOldBitmapLoad
);
2252 SelectObject (hdcBitmap
, hOldBitmapBitmap
);
2253 DeleteDC (hdcImage
);
2254 DeleteDC (hdcBitmap
);
2256 nIndex
= ImageList_AddMasked (himlDef
, hbmLoad
, CLR_DEFAULT
);
2257 DeleteObject (hbmLoad
);
2259 else if (lpAddBmp
->hInst
== HINST_COMMCTRL
)
2261 /* Add system bitmaps */
2262 switch (lpAddBmp
->nID
)
2264 case IDB_STD_SMALL_COLOR
:
2265 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2266 MAKEINTRESOURCEA(IDB_STD_SMALL
));
2267 nIndex
= ImageList_AddMasked (himlDef
,
2268 hbmLoad
, CLR_DEFAULT
);
2269 DeleteObject (hbmLoad
);
2272 case IDB_STD_LARGE_COLOR
:
2273 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2274 MAKEINTRESOURCEA(IDB_STD_LARGE
));
2275 nIndex
= ImageList_AddMasked (himlDef
,
2276 hbmLoad
, CLR_DEFAULT
);
2277 DeleteObject (hbmLoad
);
2280 case IDB_VIEW_SMALL_COLOR
:
2281 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2282 MAKEINTRESOURCEA(IDB_VIEW_SMALL
));
2283 nIndex
= ImageList_AddMasked (himlDef
,
2284 hbmLoad
, CLR_DEFAULT
);
2285 DeleteObject (hbmLoad
);
2288 case IDB_VIEW_LARGE_COLOR
:
2289 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2290 MAKEINTRESOURCEA(IDB_VIEW_LARGE
));
2291 nIndex
= ImageList_AddMasked (himlDef
,
2292 hbmLoad
, CLR_DEFAULT
);
2293 DeleteObject (hbmLoad
);
2296 case IDB_HIST_SMALL_COLOR
:
2297 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2298 MAKEINTRESOURCEA(IDB_HIST_SMALL
));
2299 nIndex
= ImageList_AddMasked (himlDef
,
2300 hbmLoad
, CLR_DEFAULT
);
2301 DeleteObject (hbmLoad
);
2304 case IDB_HIST_LARGE_COLOR
:
2305 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2306 MAKEINTRESOURCEA(IDB_HIST_LARGE
));
2307 nIndex
= ImageList_AddMasked (himlDef
,
2308 hbmLoad
, CLR_DEFAULT
);
2309 DeleteObject (hbmLoad
);
2313 nIndex
= ImageList_GetImageCount (himlDef
);
2314 ERR ("invalid imagelist!\n");
2320 hbmLoad
= LoadBitmapA (lpAddBmp
->hInst
, (LPSTR
)lpAddBmp
->nID
);
2321 nIndex
= ImageList_AddMasked (himlDef
, hbmLoad
, CLR_DEFAULT
);
2322 DeleteObject (hbmLoad
);
2325 TRACE("Number of bitmap infos: %d\n", infoPtr
->nNumBitmapInfos
);
2327 if (infoPtr
->nNumBitmapInfos
== 0)
2329 infoPtr
->bitmaps
= COMCTL32_Alloc(sizeof(TBITMAP_INFO
));
2333 TBITMAP_INFO
*oldBitmaps
= infoPtr
->bitmaps
;
2334 infoPtr
->bitmaps
= COMCTL32_Alloc((infoPtr
->nNumBitmapInfos
+ 1) * sizeof(TBITMAP_INFO
));
2335 memcpy(&infoPtr
->bitmaps
[0], &oldBitmaps
[0], infoPtr
->nNumBitmapInfos
);
2338 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].nButtons
= nButtons
;
2339 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].hInst
= lpAddBmp
->hInst
;
2340 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].nID
= lpAddBmp
->nID
;
2342 infoPtr
->nNumBitmapInfos
++;
2343 TRACE("Number of bitmap infos: %d\n", infoPtr
->nNumBitmapInfos
);
2347 INT imagecount
= ImageList_GetImageCount(himlDef
);
2349 if (infoPtr
->nNumBitmaps
+ nButtons
!= imagecount
)
2351 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",
2352 infoPtr
->nNumBitmaps
, nCount
, imagecount
- nCount
,
2353 infoPtr
->nNumBitmaps
+nButtons
,imagecount
);
2355 infoPtr
->nNumBitmaps
= imagecount
;
2358 infoPtr
->nNumBitmaps
+= nButtons
;
2361 InvalidateRect(hwnd
, NULL
, FALSE
);
2368 TOOLBAR_AddButtonsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2370 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2371 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
2372 INT nOldButtons
, nNewButtons
, nAddButtons
, nCount
;
2374 TRACE("adding %d buttons!\n", wParam
);
2376 nAddButtons
= (UINT
)wParam
;
2377 nOldButtons
= infoPtr
->nNumButtons
;
2378 nNewButtons
= nOldButtons
+ nAddButtons
;
2380 if (infoPtr
->nNumButtons
== 0) {
2382 COMCTL32_Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2385 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2387 COMCTL32_Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2388 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2389 nOldButtons
* sizeof(TBUTTON_INFO
));
2390 COMCTL32_Free (oldButtons
);
2393 infoPtr
->nNumButtons
= nNewButtons
;
2395 /* insert new button data */
2396 for (nCount
= 0; nCount
< nAddButtons
; nCount
++) {
2397 TBUTTON_INFO
*btnPtr
= &infoPtr
->buttons
[nOldButtons
+nCount
];
2398 btnPtr
->iBitmap
= lpTbb
[nCount
].iBitmap
;
2399 btnPtr
->idCommand
= lpTbb
[nCount
].idCommand
;
2400 btnPtr
->fsState
= lpTbb
[nCount
].fsState
;
2401 btnPtr
->fsStyle
= lpTbb
[nCount
].fsStyle
;
2402 btnPtr
->dwData
= lpTbb
[nCount
].dwData
;
2403 btnPtr
->iString
= lpTbb
[nCount
].iString
;
2404 btnPtr
->bHot
= FALSE
;
2406 if ((infoPtr
->hwndToolTip
) && !(btnPtr
->fsStyle
& TBSTYLE_SEP
)) {
2409 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
2410 ti
.cbSize
= sizeof (TTTOOLINFOA
);
2412 ti
.uId
= btnPtr
->idCommand
;
2414 ti
.lpszText
= LPSTR_TEXTCALLBACKA
;
2416 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
,
2421 TOOLBAR_CalcToolbar (hwnd
);
2423 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
2425 InvalidateRect(hwnd
, NULL
, FALSE
);
2432 TOOLBAR_AddButtonsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2434 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2435 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
2436 INT nOldButtons
, nNewButtons
, nAddButtons
, nCount
;
2438 TRACE("adding %d buttons!\n", wParam
);
2440 nAddButtons
= (UINT
)wParam
;
2441 nOldButtons
= infoPtr
->nNumButtons
;
2442 nNewButtons
= nOldButtons
+ nAddButtons
;
2444 if (infoPtr
->nNumButtons
== 0) {
2446 COMCTL32_Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2449 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2451 COMCTL32_Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2452 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2453 nOldButtons
* sizeof(TBUTTON_INFO
));
2454 COMCTL32_Free (oldButtons
);
2457 infoPtr
->nNumButtons
= nNewButtons
;
2459 /* insert new button data */
2460 for (nCount
= 0; nCount
< nAddButtons
; nCount
++) {
2461 TBUTTON_INFO
*btnPtr
= &infoPtr
->buttons
[nOldButtons
+nCount
];
2462 btnPtr
->iBitmap
= lpTbb
[nCount
].iBitmap
;
2463 btnPtr
->idCommand
= lpTbb
[nCount
].idCommand
;
2464 btnPtr
->fsState
= lpTbb
[nCount
].fsState
;
2465 btnPtr
->fsStyle
= lpTbb
[nCount
].fsStyle
;
2466 btnPtr
->dwData
= lpTbb
[nCount
].dwData
;
2467 btnPtr
->iString
= lpTbb
[nCount
].iString
;
2468 btnPtr
->bHot
= FALSE
;
2470 if ((infoPtr
->hwndToolTip
) && !(btnPtr
->fsStyle
& TBSTYLE_SEP
)) {
2473 ZeroMemory (&ti
, sizeof(TTTOOLINFOW
));
2474 ti
.cbSize
= sizeof (TTTOOLINFOW
);
2476 ti
.uId
= btnPtr
->idCommand
;
2478 ti
.lpszText
= LPSTR_TEXTCALLBACKW
;
2481 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
,
2486 TOOLBAR_CalcToolbar (hwnd
);
2488 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
2490 InvalidateRect(hwnd
, NULL
, FALSE
);
2497 TOOLBAR_AddStringA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2499 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2502 if ((wParam
) && (HIWORD(lParam
) == 0)) {
2505 TRACE("adding string from resource!\n");
2507 len
= LoadStringA ((HINSTANCE
)wParam
, (UINT
)lParam
,
2510 TRACE("len=%d \"%s\"\n", len
, szString
);
2511 nIndex
= infoPtr
->nNumStrings
;
2512 if (infoPtr
->nNumStrings
== 0) {
2514 COMCTL32_Alloc (sizeof(LPWSTR
));
2517 LPWSTR
*oldStrings
= infoPtr
->strings
;
2519 COMCTL32_Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2520 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2521 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2522 COMCTL32_Free (oldStrings
);
2525 /*COMCTL32_Alloc zeros out the allocated memory*/
2526 Str_SetPtrAtoW (&infoPtr
->strings
[infoPtr
->nNumStrings
], szString
);
2527 infoPtr
->nNumStrings
++;
2530 LPSTR p
= (LPSTR
)lParam
;
2535 TRACE("adding string(s) from array!\n");
2537 nIndex
= infoPtr
->nNumStrings
;
2540 TRACE("len=%d \"%s\"\n", len
, p
);
2542 if (infoPtr
->nNumStrings
== 0) {
2544 COMCTL32_Alloc (sizeof(LPWSTR
));
2547 LPWSTR
*oldStrings
= infoPtr
->strings
;
2549 COMCTL32_Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2550 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2551 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2552 COMCTL32_Free (oldStrings
);
2555 Str_SetPtrAtoW (&infoPtr
->strings
[infoPtr
->nNumStrings
], p
);
2556 infoPtr
->nNumStrings
++;
2567 TOOLBAR_AddStringW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2569 #define MAX_RESOURCE_STRING_LENGTH 512
2570 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2573 if ((wParam
) && (HIWORD(lParam
) == 0)) {
2574 WCHAR szString
[MAX_RESOURCE_STRING_LENGTH
];
2576 TRACE("adding string from resource!\n");
2578 len
= LoadStringW ((HINSTANCE
)wParam
, (UINT
)lParam
,
2579 szString
, MAX_RESOURCE_STRING_LENGTH
);
2581 TRACE("len=%d %s\n", len
, debugstr_w(szString
));
2582 TRACE("First char: 0x%x\n", *szString
);
2583 if (szString
[0] == L
'|')
2585 PWSTR p
= szString
+ 1;
2587 nIndex
= infoPtr
->nNumStrings
;
2588 while (*p
!= L
'|' && *p
!= L
'\0') {
2591 if (infoPtr
->nNumStrings
== 0) {
2592 infoPtr
->strings
= COMCTL32_Alloc (sizeof(LPWSTR
));
2596 LPWSTR
*oldStrings
= infoPtr
->strings
;
2597 infoPtr
->strings
= COMCTL32_Alloc(sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2598 memcpy(&infoPtr
->strings
[0], &oldStrings
[0],
2599 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2600 COMCTL32_Free(oldStrings
);
2603 np
=COMCTL32_StrChrW (p
, L
'|');
2611 TRACE("len=%d %s\n", len
, debugstr_w(p
));
2612 infoPtr
->strings
[infoPtr
->nNumStrings
] =
2613 COMCTL32_Alloc (sizeof(WCHAR
)*(len
+1));
2614 lstrcpynW (infoPtr
->strings
[infoPtr
->nNumStrings
], p
, len
+1);
2615 infoPtr
->nNumStrings
++;
2622 nIndex
= infoPtr
->nNumStrings
;
2623 if (infoPtr
->nNumStrings
== 0) {
2625 COMCTL32_Alloc (sizeof(LPWSTR
));
2628 LPWSTR
*oldStrings
= infoPtr
->strings
;
2630 COMCTL32_Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2631 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2632 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2633 COMCTL32_Free (oldStrings
);
2636 Str_SetPtrW (&infoPtr
->strings
[infoPtr
->nNumStrings
], szString
);
2637 infoPtr
->nNumStrings
++;
2641 LPWSTR p
= (LPWSTR
)lParam
;
2646 TRACE("adding string(s) from array!\n");
2647 nIndex
= infoPtr
->nNumStrings
;
2651 TRACE("len=%d %s\n", len
, debugstr_w(p
));
2652 if (infoPtr
->nNumStrings
== 0) {
2654 COMCTL32_Alloc (sizeof(LPWSTR
));
2657 LPWSTR
*oldStrings
= infoPtr
->strings
;
2659 COMCTL32_Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2660 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2661 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2662 COMCTL32_Free (oldStrings
);
2665 Str_SetPtrW (&infoPtr
->strings
[infoPtr
->nNumStrings
], p
);
2666 infoPtr
->nNumStrings
++;
2677 TOOLBAR_AutoSize (HWND hwnd
)
2679 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2680 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2686 UINT uPosFlags
= SWP_NOZORDER
;
2688 TRACE("resize forced, style=%lx!\n", dwStyle
);
2690 parent
= GetParent (hwnd
);
2691 GetClientRect(parent
, &parent_rect
);
2693 x
= parent_rect
.left
;
2694 y
= parent_rect
.top
;
2696 /* FIXME: we should be able to early out if nothing */
2697 /* has changed with nWidth != parent_rect width */
2699 if (dwStyle
& CCS_NORESIZE
) {
2700 uPosFlags
|= (SWP_NOSIZE
| SWP_NOMOVE
);
2703 TOOLBAR_CalcToolbar (hwnd
);
2706 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
2707 TOOLBAR_CalcToolbar (hwnd
);
2708 InvalidateRect( hwnd
, NULL
, TRUE
);
2709 cy
= infoPtr
->nHeight
;
2710 cx
= infoPtr
->nWidth
;
2712 if (dwStyle
& CCS_NOMOVEY
) {
2713 GetWindowRect(hwnd
, &window_rect
);
2714 ScreenToClient(parent
, (LPPOINT
)&window_rect
.left
);
2715 y
= window_rect
.top
;
2719 if (dwStyle
& CCS_NOPARENTALIGN
)
2720 uPosFlags
|= SWP_NOMOVE
;
2722 if (!(dwStyle
& CCS_NODIVIDER
))
2723 cy
+= GetSystemMetrics(SM_CYEDGE
);
2725 if (dwStyle
& WS_BORDER
)
2728 cy
+= GetSystemMetrics(SM_CYEDGE
);
2729 cx
+= GetSystemMetrics(SM_CYEDGE
);
2732 infoPtr
->bAutoSize
= TRUE
;
2733 SetWindowPos (hwnd
, HWND_TOP
, parent_rect
.left
- x
, parent_rect
.top
- y
,
2735 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2736 * the setwindowpos calls */
2737 infoPtr
->bAutoSize
= FALSE
;
2744 TOOLBAR_ButtonCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2746 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2748 return infoPtr
->nNumButtons
;
2753 TOOLBAR_ButtonStructSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2755 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2757 if (infoPtr
== NULL
) {
2758 ERR("(%p, 0x%x, 0x%lx)\n", hwnd
, wParam
, lParam
);
2759 ERR("infoPtr == NULL!\n");
2763 infoPtr
->dwStructSize
= (DWORD
)wParam
;
2770 TOOLBAR_ChangeBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2772 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2773 TBUTTON_INFO
*btnPtr
;
2776 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2780 btnPtr
= &infoPtr
->buttons
[nIndex
];
2781 btnPtr
->iBitmap
= LOWORD(lParam
);
2783 /* we HAVE to erase the background, the new bitmap could be */
2785 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
2792 TOOLBAR_CheckButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2794 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2795 TBUTTON_INFO
*btnPtr
;
2798 BOOL bChecked
= FALSE
;
2800 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2804 btnPtr
= &infoPtr
->buttons
[nIndex
];
2806 if (!(btnPtr
->fsStyle
& TBSTYLE_CHECK
))
2809 bChecked
= (btnPtr
->fsState
& TBSTATE_CHECKED
) ? TRUE
: FALSE
;
2811 if (LOWORD(lParam
) == FALSE
)
2812 btnPtr
->fsState
&= ~TBSTATE_CHECKED
;
2814 if (btnPtr
->fsStyle
& TBSTYLE_GROUP
) {
2816 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr
, nIndex
);
2817 if (nOldIndex
== nIndex
)
2819 if (nOldIndex
!= -1)
2820 infoPtr
->buttons
[nOldIndex
].fsState
&= ~TBSTATE_CHECKED
;
2822 btnPtr
->fsState
|= TBSTATE_CHECKED
;
2825 if( bChecked
!= LOWORD(lParam
) )
2827 if (nOldIndex
!= -1)
2829 InvalidateRect(hwnd
, &infoPtr
->buttons
[nOldIndex
].rect
,
2830 TOOLBAR_HasText(infoPtr
, &infoPtr
->buttons
[nOldIndex
]));
2832 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
2835 /* FIXME: Send a WM_NOTIFY?? */
2842 TOOLBAR_CommandToIndex (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2844 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2846 return TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2851 TOOLBAR_Customize (HWND hwnd
)
2853 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2854 CUSTDLG_INFO custInfo
;
2860 custInfo
.tbInfo
= infoPtr
;
2861 custInfo
.tbHwnd
= hwnd
;
2863 /* send TBN_BEGINADJUST notification */
2864 TOOLBAR_SendNotify ((NMHDR
*) &nmhdr
, infoPtr
,
2867 if (!(hRes
= FindResourceA (COMCTL32_hModule
,
2868 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE
),
2872 if(!(template = (LPVOID
)LoadResource (COMCTL32_hModule
, hRes
)))
2875 ret
= DialogBoxIndirectParamA ((HINSTANCE
)GetWindowLongA(hwnd
, GWL_HINSTANCE
),
2876 (LPDLGTEMPLATEA
)template,
2878 TOOLBAR_CustomizeDialogProc
,
2881 /* send TBN_ENDADJUST notification */
2882 TOOLBAR_SendNotify ((NMHDR
*) &nmhdr
, infoPtr
,
2890 TOOLBAR_DeleteButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2892 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2893 INT nIndex
= (INT
)wParam
;
2895 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
2898 if ((infoPtr
->hwndToolTip
) &&
2899 !(infoPtr
->buttons
[nIndex
].fsStyle
& TBSTYLE_SEP
)) {
2902 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
2903 ti
.cbSize
= sizeof (TTTOOLINFOA
);
2905 ti
.uId
= infoPtr
->buttons
[nIndex
].idCommand
;
2907 SendMessageA (infoPtr
->hwndToolTip
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
2910 if (infoPtr
->nNumButtons
== 1) {
2911 TRACE(" simple delete!\n");
2912 COMCTL32_Free (infoPtr
->buttons
);
2913 infoPtr
->buttons
= NULL
;
2914 infoPtr
->nNumButtons
= 0;
2917 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2918 TRACE("complex delete! [nIndex=%d]\n", nIndex
);
2920 infoPtr
->nNumButtons
--;
2921 infoPtr
->buttons
= COMCTL32_Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
2923 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2924 nIndex
* sizeof(TBUTTON_INFO
));
2927 if (nIndex
< infoPtr
->nNumButtons
) {
2928 memcpy (&infoPtr
->buttons
[nIndex
], &oldButtons
[nIndex
+1],
2929 (infoPtr
->nNumButtons
- nIndex
) * sizeof(TBUTTON_INFO
));
2932 COMCTL32_Free (oldButtons
);
2935 TOOLBAR_CalcToolbar (hwnd
);
2937 InvalidateRect (hwnd
, NULL
, TRUE
);
2944 TOOLBAR_EnableButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2946 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2947 TBUTTON_INFO
*btnPtr
;
2951 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2955 btnPtr
= &infoPtr
->buttons
[nIndex
];
2957 bState
= btnPtr
->fsState
& TBSTATE_ENABLED
;
2959 /* update the toolbar button state */
2960 if(LOWORD(lParam
) == FALSE
) {
2961 btnPtr
->fsState
&= ~(TBSTATE_ENABLED
| TBSTATE_PRESSED
);
2963 btnPtr
->fsState
|= TBSTATE_ENABLED
;
2966 /* redraw the button only if the state of the button changed */
2967 if(bState
!= (btnPtr
->fsState
& TBSTATE_ENABLED
))
2969 InvalidateRect(hwnd
, &btnPtr
->rect
,
2970 TOOLBAR_HasText(infoPtr
, btnPtr
));
2977 static inline LRESULT
2978 TOOLBAR_GetAnchorHighlight (HWND hwnd
)
2980 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2982 return infoPtr
->bAnchor
;
2987 TOOLBAR_GetBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2989 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2992 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2996 return infoPtr
->buttons
[nIndex
].iBitmap
;
3000 static inline LRESULT
3001 TOOLBAR_GetBitmapFlags (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3003 return (GetDeviceCaps (0, LOGPIXELSX
) >= 120) ? TBBF_LARGE
: 0;
3008 TOOLBAR_GetButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3010 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3011 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3012 INT nIndex
= (INT
)wParam
;
3013 TBUTTON_INFO
*btnPtr
;
3015 if (infoPtr
== NULL
)
3021 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3024 btnPtr
= &infoPtr
->buttons
[nIndex
];
3025 lpTbb
->iBitmap
= btnPtr
->iBitmap
;
3026 lpTbb
->idCommand
= btnPtr
->idCommand
;
3027 lpTbb
->fsState
= btnPtr
->fsState
;
3028 lpTbb
->fsStyle
= btnPtr
->fsStyle
;
3029 lpTbb
->bReserved
[0] = 0;
3030 lpTbb
->bReserved
[1] = 0;
3031 lpTbb
->dwData
= btnPtr
->dwData
;
3032 lpTbb
->iString
= btnPtr
->iString
;
3039 TOOLBAR_GetButtonInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3041 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3042 LPTBBUTTONINFOA lpTbInfo
= (LPTBBUTTONINFOA
)lParam
;
3043 TBUTTON_INFO
*btnPtr
;
3046 if (infoPtr
== NULL
)
3048 if (lpTbInfo
== NULL
)
3050 if (lpTbInfo
->cbSize
< sizeof(TBBUTTONINFOA
))
3053 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
3054 lpTbInfo
->dwMask
& 0x80000000);
3058 if (!(btnPtr
= &infoPtr
->buttons
[nIndex
])) return -1;
3060 if (lpTbInfo
->dwMask
& TBIF_COMMAND
)
3061 lpTbInfo
->idCommand
= btnPtr
->idCommand
;
3062 if (lpTbInfo
->dwMask
& TBIF_IMAGE
)
3063 lpTbInfo
->iImage
= btnPtr
->iBitmap
;
3064 if (lpTbInfo
->dwMask
& TBIF_LPARAM
)
3065 lpTbInfo
->lParam
= btnPtr
->dwData
;
3066 if (lpTbInfo
->dwMask
& TBIF_SIZE
)
3067 lpTbInfo
->cx
= (WORD
)(btnPtr
->rect
.right
- btnPtr
->rect
.left
);
3068 if (lpTbInfo
->dwMask
& TBIF_STATE
)
3069 lpTbInfo
->fsState
= btnPtr
->fsState
;
3070 if (lpTbInfo
->dwMask
& TBIF_STYLE
)
3071 lpTbInfo
->fsStyle
= btnPtr
->fsStyle
;
3072 if (lpTbInfo
->dwMask
& TBIF_TEXT
) {
3073 LPWSTR lpText
= TOOLBAR_GetText(infoPtr
,btnPtr
);
3074 Str_GetPtrWtoA (lpText
, lpTbInfo
->pszText
,lpTbInfo
->cchText
);
3081 TOOLBAR_GetButtonInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3083 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3084 LPTBBUTTONINFOW lpTbInfo
= (LPTBBUTTONINFOW
)lParam
;
3085 TBUTTON_INFO
*btnPtr
;
3088 if (infoPtr
== NULL
)
3090 if (lpTbInfo
== NULL
)
3092 if (lpTbInfo
->cbSize
< sizeof(TBBUTTONINFOW
))
3095 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
3096 lpTbInfo
->dwMask
& 0x80000000);
3100 btnPtr
= &infoPtr
->buttons
[nIndex
];
3105 if (lpTbInfo
->dwMask
& TBIF_COMMAND
)
3106 lpTbInfo
->idCommand
= btnPtr
->idCommand
;
3107 if (lpTbInfo
->dwMask
& TBIF_IMAGE
)
3108 lpTbInfo
->iImage
= btnPtr
->iBitmap
;
3109 if (lpTbInfo
->dwMask
& TBIF_LPARAM
)
3110 lpTbInfo
->lParam
= btnPtr
->dwData
;
3111 if (lpTbInfo
->dwMask
& TBIF_SIZE
)
3112 lpTbInfo
->cx
= (WORD
)(btnPtr
->rect
.right
- btnPtr
->rect
.left
);
3113 if (lpTbInfo
->dwMask
& TBIF_STATE
)
3114 lpTbInfo
->fsState
= btnPtr
->fsState
;
3115 if (lpTbInfo
->dwMask
& TBIF_STYLE
)
3116 lpTbInfo
->fsStyle
= btnPtr
->fsStyle
;
3117 if (lpTbInfo
->dwMask
& TBIF_TEXT
) {
3118 LPWSTR lpText
= TOOLBAR_GetText(infoPtr
,btnPtr
);
3119 Str_GetPtrW (lpText
,lpTbInfo
->pszText
,lpTbInfo
->cchText
);
3127 TOOLBAR_GetButtonSize (HWND hwnd
)
3129 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3131 if (infoPtr
->nNumButtons
> 0)
3132 return MAKELONG((WORD
)infoPtr
->nButtonWidth
,
3133 (WORD
)infoPtr
->nButtonHeight
);
3135 return MAKELONG(8,7);
3140 TOOLBAR_GetButtonTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3142 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3149 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3153 lpText
= TOOLBAR_GetText(infoPtr
,&infoPtr
->buttons
[nIndex
]);
3155 return WideCharToMultiByte( CP_ACP
, 0, lpText
, -1,
3156 (LPSTR
)lParam
, 0x7fffffff, NULL
, NULL
) - 1;
3161 TOOLBAR_GetButtonTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3163 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3170 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3174 lpText
= TOOLBAR_GetText(infoPtr
,&infoPtr
->buttons
[nIndex
]);
3176 strcpyW ((LPWSTR
)lParam
, lpText
);
3178 return strlenW (lpText
);
3183 TOOLBAR_GetDisabledImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3185 return (LRESULT
)GETDISIMAGELIST(TOOLBAR_GetInfoPtr (hwnd
), 0);
3189 inline static LRESULT
3190 TOOLBAR_GetExtendedStyle (HWND hwnd
)
3192 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3194 return infoPtr
->dwExStyle
;
3199 TOOLBAR_GetHotImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3201 return (LRESULT
)GETHOTIMAGELIST(TOOLBAR_GetInfoPtr (hwnd
), 0);
3206 TOOLBAR_GetHotItem (HWND hwnd
)
3208 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3210 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_FLAT
))
3213 if (infoPtr
->nHotItem
< 0)
3216 return (LRESULT
)infoPtr
->nHotItem
;
3221 TOOLBAR_GetDefImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3223 return (LRESULT
) GETDEFIMAGELIST(TOOLBAR_GetInfoPtr(hwnd
), 0);
3227 /* << TOOLBAR_GetInsertMark >> */
3228 /* << TOOLBAR_GetInsertMarkColor >> */
3232 TOOLBAR_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3234 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3235 TBUTTON_INFO
*btnPtr
;
3239 if (infoPtr
== NULL
)
3241 nIndex
= (INT
)wParam
;
3242 btnPtr
= &infoPtr
->buttons
[nIndex
];
3243 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3245 lpRect
= (LPRECT
)lParam
;
3248 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
3251 lpRect
->left
= btnPtr
->rect
.left
;
3252 lpRect
->right
= btnPtr
->rect
.right
;
3253 lpRect
->bottom
= btnPtr
->rect
.bottom
;
3254 lpRect
->top
= btnPtr
->rect
.top
;
3261 TOOLBAR_GetMaxSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3263 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3264 LPSIZE lpSize
= (LPSIZE
)lParam
;
3269 lpSize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
3270 lpSize
->cy
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
3272 TRACE("maximum size %ld x %ld\n",
3273 infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
,
3274 infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
);
3280 /* << TOOLBAR_GetObject >> */
3284 TOOLBAR_GetPadding (HWND hwnd
)
3286 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3289 oldPad
= MAKELONG(infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
3290 return (LRESULT
) oldPad
;
3295 TOOLBAR_GetRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3297 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3298 TBUTTON_INFO
*btnPtr
;
3302 if (infoPtr
== NULL
)
3304 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3305 btnPtr
= &infoPtr
->buttons
[nIndex
];
3306 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3308 lpRect
= (LPRECT
)lParam
;
3312 lpRect
->left
= btnPtr
->rect
.left
;
3313 lpRect
->right
= btnPtr
->rect
.right
;
3314 lpRect
->bottom
= btnPtr
->rect
.bottom
;
3315 lpRect
->top
= btnPtr
->rect
.top
;
3322 TOOLBAR_GetRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3324 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3326 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_WRAPABLE
)
3327 return infoPtr
->nRows
;
3334 TOOLBAR_GetState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3336 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3339 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3343 return infoPtr
->buttons
[nIndex
].fsState
;
3348 TOOLBAR_GetStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3350 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3353 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3357 return infoPtr
->buttons
[nIndex
].fsStyle
;
3362 TOOLBAR_GetTextRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3364 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3366 if (infoPtr
== NULL
)
3369 return infoPtr
->nMaxTextRows
;
3374 TOOLBAR_GetToolTips (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3376 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3378 if (infoPtr
== NULL
)
3380 return (LRESULT
)infoPtr
->hwndToolTip
;
3385 TOOLBAR_GetUnicodeFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3387 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3389 TRACE("%s hwnd=%p stub!\n",
3390 infoPtr
->bUnicode
? "TRUE" : "FALSE", hwnd
);
3392 return infoPtr
->bUnicode
;
3396 inline static LRESULT
3397 TOOLBAR_GetVersion (HWND hwnd
)
3399 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3400 return infoPtr
->iVersion
;
3405 TOOLBAR_HideButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3407 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3408 TBUTTON_INFO
*btnPtr
;
3413 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3417 btnPtr
= &infoPtr
->buttons
[nIndex
];
3418 if (LOWORD(lParam
) == FALSE
)
3419 btnPtr
->fsState
&= ~TBSTATE_HIDDEN
;
3421 btnPtr
->fsState
|= TBSTATE_HIDDEN
;
3423 TOOLBAR_CalcToolbar (hwnd
);
3425 InvalidateRect (hwnd
, NULL
, TRUE
);
3431 inline static LRESULT
3432 TOOLBAR_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3434 return TOOLBAR_InternalHitTest (hwnd
, (LPPOINT
)lParam
);
3439 TOOLBAR_Indeterminate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3441 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3442 TBUTTON_INFO
*btnPtr
;
3445 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3449 btnPtr
= &infoPtr
->buttons
[nIndex
];
3450 if (LOWORD(lParam
) == FALSE
)
3451 btnPtr
->fsState
&= ~TBSTATE_INDETERMINATE
;
3453 btnPtr
->fsState
|= TBSTATE_INDETERMINATE
;
3455 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
3462 TOOLBAR_InsertButtonA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3464 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3465 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3466 INT nIndex
= (INT
)wParam
;
3467 TBUTTON_INFO
*oldButtons
;
3472 TOOLBAR_DumpButton(infoPtr
, (TBUTTON_INFO
*)lpTbb
, nIndex
, FALSE
);
3475 /* EPP: this seems to be an undocumented call (from my IE4)
3476 * I assume in that case that:
3477 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3478 * - index of insertion is at the end of existing buttons
3479 * I only see this happen with nIndex == -1, but it could have a special
3480 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3482 nIndex
= infoPtr
->nNumButtons
;
3484 } else if (nIndex
< 0)
3487 /* If the string passed is not an index, assume address of string
3488 and do our own AddString */
3489 if ((HIWORD(lpTbb
->iString
) != 0) && (lpTbb
->iString
!= -1)) {
3493 TRACE("string %s passed instead of index, adding string\n",
3494 debugstr_a((LPSTR
)lpTbb
->iString
));
3495 len
= strlen((LPSTR
)lpTbb
->iString
) + 2;
3496 ptr
= COMCTL32_Alloc(len
);
3497 strcpy(ptr
, (LPSTR
)lpTbb
->iString
);
3498 ptr
[len
- 1] = 0; /* ended by two '\0' */
3499 lpTbb
->iString
= TOOLBAR_AddStringA(hwnd
, 0, (LPARAM
)ptr
);
3503 TRACE("inserting button index=%d\n", nIndex
);
3504 if (nIndex
> infoPtr
->nNumButtons
) {
3505 nIndex
= infoPtr
->nNumButtons
;
3506 TRACE("adjust index=%d\n", nIndex
);
3509 oldButtons
= infoPtr
->buttons
;
3510 infoPtr
->nNumButtons
++;
3511 infoPtr
->buttons
= COMCTL32_Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
3512 /* pre insert copy */
3514 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
3515 nIndex
* sizeof(TBUTTON_INFO
));
3518 /* insert new button */
3519 infoPtr
->buttons
[nIndex
].iBitmap
= lpTbb
->iBitmap
;
3520 infoPtr
->buttons
[nIndex
].idCommand
= lpTbb
->idCommand
;
3521 infoPtr
->buttons
[nIndex
].fsState
= lpTbb
->fsState
;
3522 infoPtr
->buttons
[nIndex
].fsStyle
= lpTbb
->fsStyle
;
3523 infoPtr
->buttons
[nIndex
].dwData
= lpTbb
->dwData
;
3524 /* if passed string and not index, then add string */
3525 if(HIWORD(lpTbb
->iString
) && lpTbb
->iString
!=-1) {
3526 Str_SetPtrAtoW ((LPWSTR
*)&infoPtr
->buttons
[nIndex
].iString
, (LPCSTR
)lpTbb
->iString
);
3529 infoPtr
->buttons
[nIndex
].iString
= lpTbb
->iString
;
3531 if ((infoPtr
->hwndToolTip
) && !(lpTbb
->fsStyle
& TBSTYLE_SEP
)) {
3534 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
3535 ti
.cbSize
= sizeof (TTTOOLINFOA
);
3537 ti
.uId
= lpTbb
->idCommand
;
3539 ti
.lpszText
= LPSTR_TEXTCALLBACKA
;
3541 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
,
3545 /* post insert copy */
3546 if (nIndex
< infoPtr
->nNumButtons
- 1) {
3547 memcpy (&infoPtr
->buttons
[nIndex
+1], &oldButtons
[nIndex
],
3548 (infoPtr
->nNumButtons
- nIndex
- 1) * sizeof(TBUTTON_INFO
));
3551 COMCTL32_Free (oldButtons
);
3553 TOOLBAR_CalcToolbar (hwnd
);
3555 InvalidateRect (hwnd
, NULL
, TRUE
);
3562 TOOLBAR_InsertButtonW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3564 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3565 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3566 INT nIndex
= (INT
)wParam
;
3567 TBUTTON_INFO
*oldButtons
;
3572 TOOLBAR_DumpButton(infoPtr
, (TBUTTON_INFO
*)lpTbb
, nIndex
, FALSE
);
3575 /* EPP: this seems to be an undocumented call (from my IE4)
3576 * I assume in that case that:
3577 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3578 * - index of insertion is at the end of existing buttons
3579 * I only see this happen with nIndex == -1, but it could have a special
3580 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3582 nIndex
= infoPtr
->nNumButtons
;
3584 } else if (nIndex
< 0)
3587 /* If the string passed is not an index, assume address of string
3588 and do our own AddString */
3589 if ((HIWORD(lpTbb
->iString
) != 0) && (lpTbb
->iString
!= -1)) {
3593 TRACE("string %s passed instead of index, adding string\n",
3594 debugstr_w((LPWSTR
)lpTbb
->iString
));
3595 len
= strlenW((LPWSTR
)lpTbb
->iString
) + 2;
3596 ptr
= COMCTL32_Alloc(len
*sizeof(WCHAR
));
3597 strcpyW(ptr
, (LPWSTR
)lpTbb
->iString
);
3598 ptr
[len
- 1] = 0; /* ended by two '\0' */
3599 lpTbb
->iString
= TOOLBAR_AddStringW(hwnd
, 0, (LPARAM
)ptr
);
3603 TRACE("inserting button index=%d\n", nIndex
);
3604 if (nIndex
> infoPtr
->nNumButtons
) {
3605 nIndex
= infoPtr
->nNumButtons
;
3606 TRACE("adjust index=%d\n", nIndex
);
3609 oldButtons
= infoPtr
->buttons
;
3610 infoPtr
->nNumButtons
++;
3611 infoPtr
->buttons
= COMCTL32_Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
3612 /* pre insert copy */
3614 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
3615 nIndex
* sizeof(TBUTTON_INFO
));
3618 /* insert new button */
3619 infoPtr
->buttons
[nIndex
].iBitmap
= lpTbb
->iBitmap
;
3620 infoPtr
->buttons
[nIndex
].idCommand
= lpTbb
->idCommand
;
3621 infoPtr
->buttons
[nIndex
].fsState
= lpTbb
->fsState
;
3622 infoPtr
->buttons
[nIndex
].fsStyle
= lpTbb
->fsStyle
;
3623 infoPtr
->buttons
[nIndex
].dwData
= lpTbb
->dwData
;
3624 /* if passed string and not index, then add string */
3625 if(HIWORD(lpTbb
->iString
) && lpTbb
->iString
!=-1) {
3626 Str_SetPtrW ((LPWSTR
*)&infoPtr
->buttons
[nIndex
].iString
, (LPWSTR
)lpTbb
->iString
);
3629 infoPtr
->buttons
[nIndex
].iString
= lpTbb
->iString
;
3631 if ((infoPtr
->hwndToolTip
) && !(lpTbb
->fsStyle
& TBSTYLE_SEP
)) {
3634 ZeroMemory (&ti
, sizeof(TTTOOLINFOW
));
3635 ti
.cbSize
= sizeof (TTTOOLINFOW
);
3637 ti
.uId
= lpTbb
->idCommand
;
3639 ti
.lpszText
= LPSTR_TEXTCALLBACKW
;
3641 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
,
3645 /* post insert copy */
3646 if (nIndex
< infoPtr
->nNumButtons
- 1) {
3647 memcpy (&infoPtr
->buttons
[nIndex
+1], &oldButtons
[nIndex
],
3648 (infoPtr
->nNumButtons
- nIndex
- 1) * sizeof(TBUTTON_INFO
));
3651 COMCTL32_Free (oldButtons
);
3653 TOOLBAR_CalcToolbar (hwnd
);
3655 InvalidateRect (hwnd
, NULL
, TRUE
);
3661 /* << TOOLBAR_InsertMarkHitTest >> */
3665 TOOLBAR_IsButtonChecked (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3667 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3670 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3674 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_CHECKED
);
3679 TOOLBAR_IsButtonEnabled (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3681 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3684 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3688 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_ENABLED
);
3693 TOOLBAR_IsButtonHidden (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3695 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3698 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3702 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_HIDDEN
);
3707 TOOLBAR_IsButtonHighlighted (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3709 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3712 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3716 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_MARKED
);
3721 TOOLBAR_IsButtonIndeterminate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3723 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3726 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3730 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_INDETERMINATE
);
3735 TOOLBAR_IsButtonPressed (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3737 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3740 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3744 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_PRESSED
);
3748 /* << TOOLBAR_LoadImages >> */
3749 /* << TOOLBAR_MapAccelerator >> */
3750 /* << TOOLBAR_MarkButton >> */
3751 /* << TOOLBAR_MoveButton >> */
3755 TOOLBAR_PressButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3757 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3758 TBUTTON_INFO
*btnPtr
;
3761 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3765 btnPtr
= &infoPtr
->buttons
[nIndex
];
3766 if (LOWORD(lParam
) == FALSE
)
3767 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
3769 btnPtr
->fsState
|= TBSTATE_PRESSED
;
3771 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
3778 TOOLBAR_ReplaceBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3780 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3781 LPTBREPLACEBITMAP lpReplace
= (LPTBREPLACEBITMAP
) lParam
;
3783 int i
= 0, nOldButtons
= 0, pos
= 0;
3784 HIMAGELIST himlDef
= 0;
3786 TRACE("hInstOld %p nIDOld %x hInstNew %p nIDNew %x nButtons %x\n",
3787 lpReplace
->hInstOld
, lpReplace
->nIDOld
, lpReplace
->hInstNew
, lpReplace
->nIDNew
,
3788 lpReplace
->nButtons
);
3790 if (lpReplace
->hInstOld
== HINST_COMMCTRL
)
3792 FIXME("changing standard bitmaps not implemented\n");
3795 else if (lpReplace
->hInstOld
!= 0)
3797 FIXME("resources not in the current module not implemented\n");
3802 hBitmap
= (HBITMAP
) lpReplace
->nIDNew
;
3805 TRACE("To be replaced hInstOld %p nIDOld %x\n", lpReplace
->hInstOld
, lpReplace
->nIDOld
);
3806 for (i
= 0; i
< infoPtr
->nNumBitmapInfos
; i
++) {
3807 TBITMAP_INFO
*tbi
= &infoPtr
->bitmaps
[i
];
3808 TRACE("tbimapinfo %d hInstOld %p nIDOld %x\n", i
, tbi
->hInst
, tbi
->nID
);
3809 if (tbi
->hInst
== lpReplace
->hInstOld
&& tbi
->nID
== lpReplace
->nIDOld
)
3811 TRACE("Found: nButtons %d hInst %p nID %x\n", tbi
->nButtons
, tbi
->hInst
, tbi
->nID
);
3812 nOldButtons
= tbi
->nButtons
;
3813 tbi
->nButtons
= lpReplace
->nButtons
;
3814 tbi
->hInst
= lpReplace
->hInstNew
;
3815 tbi
->nID
= lpReplace
->nIDNew
;
3816 TRACE("tbimapinfo changed %d hInstOld %p nIDOld %x\n", i
, tbi
->hInst
, tbi
->nID
);
3819 pos
+= tbi
->nButtons
;
3822 if (nOldButtons
== 0)
3824 WARN("No hinst/bitmap found! hInst %p nID %x\n", lpReplace
->hInstOld
, lpReplace
->nIDOld
);
3828 infoPtr
->nNumBitmaps
= infoPtr
->nNumBitmaps
- nOldButtons
+ lpReplace
->nButtons
;
3830 /* ImageList_Replace(GETDEFIMAGELIST(), pos, hBitmap, NULL); */
3833 himlDef
= GETDEFIMAGELIST(infoPtr
, 0);
3834 for (i
= pos
+ nOldButtons
- 1; i
>= pos
; i
--) {
3835 ImageList_Remove(himlDef
, i
);
3840 HBITMAP hOldBitmapBitmap
, hOldBitmapLoad
, hbmLoad
;
3841 HDC hdcImage
, hdcBitmap
;
3843 /* copy the bitmap before adding it so that the user's bitmap
3844 * doesn't get modified.
3846 GetObjectA (hBitmap
, sizeof(BITMAP
), (LPVOID
)&bmp
);
3848 hdcImage
= CreateCompatibleDC(0);
3849 hdcBitmap
= CreateCompatibleDC(0);
3851 /* create new bitmap */
3852 hbmLoad
= CreateBitmap (bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
, bmp
.bmBitsPixel
, NULL
);
3853 hOldBitmapBitmap
= SelectObject(hdcBitmap
, hBitmap
);
3854 hOldBitmapLoad
= SelectObject(hdcImage
, hbmLoad
);
3856 /* Copy the user's image */
3857 BitBlt (hdcImage
, 0, 0, bmp
.bmWidth
, bmp
.bmHeight
,
3858 hdcBitmap
, 0, 0, SRCCOPY
);
3860 SelectObject (hdcImage
, hOldBitmapLoad
);
3861 SelectObject (hdcBitmap
, hOldBitmapBitmap
);
3862 DeleteDC (hdcImage
);
3863 DeleteDC (hdcBitmap
);
3865 ImageList_AddMasked (himlDef
, hbmLoad
, CLR_DEFAULT
);
3866 DeleteObject (hbmLoad
);
3869 InvalidateRect(hwnd
, NULL
, FALSE
);
3875 TOOLBAR_SaveRestoreA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3878 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3879 LPTBSAVEPARAMSA lpSave
= (LPTBSAVEPARAMSA
)lParam
;
3881 if (lpSave
== NULL
) return 0;
3884 /* save toolbar information */
3885 FIXME("save to \"%s\" \"%s\"\n",
3886 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3891 /* restore toolbar information */
3893 FIXME("restore from \"%s\" \"%s\"\n",
3894 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3905 TOOLBAR_SaveRestoreW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3908 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3909 LPTBSAVEPARAMSW lpSave
= (LPTBSAVEPARAMSW
)lParam
;
3915 /* save toolbar information */
3916 FIXME("save to \"%s\" \"%s\"\n",
3917 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3922 /* restore toolbar information */
3924 FIXME("restore from \"%s\" \"%s\"\n",
3925 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3936 TOOLBAR_SetAnchorHighlight (HWND hwnd
, WPARAM wParam
)
3938 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3939 BOOL bOldAnchor
= infoPtr
->bAnchor
;
3941 infoPtr
->bAnchor
= (BOOL
)wParam
;
3943 return (LRESULT
)bOldAnchor
;
3948 TOOLBAR_SetBitmapSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3950 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3951 HIMAGELIST himlDef
= GETDEFIMAGELIST(infoPtr
, 0);
3953 if ((LOWORD(lParam
) <= 0) || (HIWORD(lParam
)<=0))
3956 if (infoPtr
->nNumButtons
> 0)
3957 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
3958 infoPtr
->nNumButtons
,
3959 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
,
3960 LOWORD(lParam
), HIWORD(lParam
));
3962 infoPtr
->nBitmapWidth
= (INT
)LOWORD(lParam
);
3963 infoPtr
->nBitmapHeight
= (INT
)HIWORD(lParam
);
3965 /* uses image list internals directly */
3967 himlDef
->cx
= infoPtr
->nBitmapWidth
;
3968 himlDef
->cy
= infoPtr
->nBitmapHeight
;
3976 TOOLBAR_SetButtonInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3978 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3979 LPTBBUTTONINFOA lptbbi
= (LPTBBUTTONINFOA
)lParam
;
3980 TBUTTON_INFO
*btnPtr
;
3985 if (lptbbi
->cbSize
< sizeof(TBBUTTONINFOA
))
3988 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
3989 lptbbi
->dwMask
& 0x80000000);
3993 btnPtr
= &infoPtr
->buttons
[nIndex
];
3994 if (lptbbi
->dwMask
& TBIF_COMMAND
)
3995 btnPtr
->idCommand
= lptbbi
->idCommand
;
3996 if (lptbbi
->dwMask
& TBIF_IMAGE
)
3997 btnPtr
->iBitmap
= lptbbi
->iImage
;
3998 if (lptbbi
->dwMask
& TBIF_LPARAM
)
3999 btnPtr
->dwData
= lptbbi
->lParam
;
4000 /* if (lptbbi->dwMask & TBIF_SIZE) */
4001 /* btnPtr->cx = lptbbi->cx; */
4002 if (lptbbi
->dwMask
& TBIF_STATE
)
4003 btnPtr
->fsState
= lptbbi
->fsState
;
4004 if (lptbbi
->dwMask
& TBIF_STYLE
)
4005 btnPtr
->fsStyle
= lptbbi
->fsStyle
;
4007 if ((lptbbi
->dwMask
& TBIF_TEXT
) && ((INT
)lptbbi
->pszText
!= -1)) {
4008 if ((HIWORD(btnPtr
->iString
) == 0) || (btnPtr
->iString
== -1))
4009 /* iString is index, zero it to make Str_SetPtr succeed */
4012 Str_SetPtrAtoW ((LPWSTR
*)&btnPtr
->iString
, lptbbi
->pszText
);
4019 TOOLBAR_SetButtonInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4021 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4022 LPTBBUTTONINFOW lptbbi
= (LPTBBUTTONINFOW
)lParam
;
4023 TBUTTON_INFO
*btnPtr
;
4028 if (lptbbi
->cbSize
< sizeof(TBBUTTONINFOW
))
4031 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
4032 lptbbi
->dwMask
& 0x80000000);
4036 btnPtr
= &infoPtr
->buttons
[nIndex
];
4037 if (lptbbi
->dwMask
& TBIF_COMMAND
)
4038 btnPtr
->idCommand
= lptbbi
->idCommand
;
4039 if (lptbbi
->dwMask
& TBIF_IMAGE
)
4040 btnPtr
->iBitmap
= lptbbi
->iImage
;
4041 if (lptbbi
->dwMask
& TBIF_LPARAM
)
4042 btnPtr
->dwData
= lptbbi
->lParam
;
4043 /* if (lptbbi->dwMask & TBIF_SIZE) */
4044 /* btnPtr->cx = lptbbi->cx; */
4045 if (lptbbi
->dwMask
& TBIF_STATE
)
4046 btnPtr
->fsState
= lptbbi
->fsState
;
4047 if (lptbbi
->dwMask
& TBIF_STYLE
)
4048 btnPtr
->fsStyle
= lptbbi
->fsStyle
;
4050 if ((lptbbi
->dwMask
& TBIF_TEXT
) && ((INT
)lptbbi
->pszText
!= -1)) {
4051 if ((HIWORD(btnPtr
->iString
) == 0) || (btnPtr
->iString
== -1))
4052 /* iString is index, zero it to make Str_SetPtr succeed */
4054 Str_SetPtrW ((LPWSTR
*)&btnPtr
->iString
, lptbbi
->pszText
);
4061 TOOLBAR_SetButtonSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4063 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4064 INT cx
= LOWORD(lParam
), cy
= HIWORD(lParam
);
4066 if ((cx
< 0) || (cy
< 0))
4068 ERR("invalid parameter 0x%08lx\n", (DWORD
)lParam
);
4072 /* The documentation claims you can only change the button size before
4073 * any button has been added. But this is wrong.
4074 * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding
4075 * it to the toolbar, and it checks that the return value is nonzero - mjm
4076 * Further testing shows that we must actually perform the change too.
4079 * The documentation also does not mention that if 0 is supplied for
4080 * either size, the system changes it to the default of 24 wide and
4081 * 22 high. Demonstarted in ControlSpy Toolbar. GLA 3/02
4083 infoPtr
->nButtonWidth
= (cx
) ? cx
: 24;
4084 infoPtr
->nButtonHeight
= (cy
) ? cy
: 22;
4090 TOOLBAR_SetButtonWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4092 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4094 if (infoPtr
== NULL
) {
4095 TRACE("Toolbar not initialized yet?????\n");
4099 /* if setting to current values, ignore */
4100 if ((infoPtr
->cxMin
== (INT
)LOWORD(lParam
)) &&
4101 (infoPtr
->cxMax
== (INT
)HIWORD(lParam
))) {
4102 TRACE("matches current width, min=%d, max=%d, no recalc\n",
4103 infoPtr
->cxMin
, infoPtr
->cxMax
);
4107 /* save new values */
4108 infoPtr
->cxMin
= (INT
)LOWORD(lParam
);
4109 infoPtr
->cxMax
= (INT
)HIWORD(lParam
);
4111 /* if both values are 0 then we are done */
4113 TRACE("setting both min and max to 0, norecalc\n");
4117 /* otherwise we need to recalc the toolbar and in some cases
4118 recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
4119 which doesn't actually draw - GA). */
4120 TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n",
4121 infoPtr
->nNumButtons
, infoPtr
->cxMin
, infoPtr
->cxMax
);
4123 TOOLBAR_CalcToolbar (hwnd
);
4125 InvalidateRect (hwnd
, NULL
, TRUE
);
4132 TOOLBAR_SetCmdId (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4134 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4135 INT nIndex
= (INT
)wParam
;
4137 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
4140 infoPtr
->buttons
[nIndex
].idCommand
= (INT
)lParam
;
4142 if (infoPtr
->hwndToolTip
) {
4144 FIXME("change tool tip!\n");
4153 TOOLBAR_SetDisabledImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4155 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4156 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4157 HIMAGELIST himlTemp
;
4160 if (infoPtr
->iVersion
>= 5)
4163 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlDis
,
4164 &infoPtr
->cimlDis
, himl
, id
);
4166 /* FIXME: redraw ? */
4168 return (LRESULT
)himlTemp
;
4173 TOOLBAR_SetDrawTextFlags (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4175 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4178 dwTemp
= infoPtr
->dwDTFlags
;
4179 infoPtr
->dwDTFlags
=
4180 (infoPtr
->dwDTFlags
& (DWORD
)wParam
) | (DWORD
)lParam
;
4182 return (LRESULT
)dwTemp
;
4186 TOOLBAR_SetExtendedStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4188 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4191 dwTemp
= infoPtr
->dwExStyle
;
4192 infoPtr
->dwExStyle
= (DWORD
)lParam
;
4194 if (infoPtr
->dwExStyle
& (TBSTYLE_EX_MIXEDBUTTONS
|
4195 TBSTYLE_EX_HIDECLIPPEDBUTTONS
)) {
4196 FIXME("Extended style not implemented %s %s\n",
4197 (infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) ?
4198 "TBSTYLE_EX_MIXEDBUTTONS" : "",
4199 (infoPtr
->dwExStyle
& TBSTYLE_EX_HIDECLIPPEDBUTTONS
) ?
4200 "TBSTYLE_EX_HIDECLIPPEDBUTTONS" : "");
4203 if (infoPtr
->dwExStyle
& ~TBSTYLE_EX_ALL
)
4204 FIXME("Unknown Toolbar Extended Style 0x%08lx. Please report.\n",
4205 (infoPtr
->dwExStyle
& ~TBSTYLE_EX_ALL
));
4207 return (LRESULT
)dwTemp
;
4212 TOOLBAR_SetHotImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4214 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4215 HIMAGELIST himlTemp
;
4216 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4219 if (infoPtr
->iVersion
>= 5)
4222 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlHot
,
4223 &infoPtr
->cimlHot
, himl
, id
);
4225 /* FIXME: redraw ? */
4227 return (LRESULT
)himlTemp
;
4232 TOOLBAR_SetHotItem (HWND hwnd
, WPARAM wParam
)
4234 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4235 INT nOldHotItem
= infoPtr
->nHotItem
;
4236 TBUTTON_INFO
*btnPtr
;
4238 if ((INT
) wParam
< 0 || (INT
)wParam
> infoPtr
->nNumButtons
)
4241 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_FLAT
)
4244 infoPtr
->nHotItem
= (INT
)wParam
;
4245 if ((INT
)wParam
>=0)
4247 btnPtr
= &infoPtr
->buttons
[(INT
)wParam
];
4248 btnPtr
->bHot
= TRUE
;
4249 InvalidateRect (hwnd
, &btnPtr
->rect
,
4250 TOOLBAR_HasText(infoPtr
, btnPtr
));
4254 btnPtr
= &infoPtr
->buttons
[nOldHotItem
];
4255 btnPtr
->bHot
= FALSE
;
4256 InvalidateRect (hwnd
, &btnPtr
->rect
,
4257 TOOLBAR_HasText(infoPtr
, btnPtr
));
4261 if (nOldHotItem
< 0)
4264 return (LRESULT
)nOldHotItem
;
4269 TOOLBAR_SetImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4271 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4272 HIMAGELIST himlTemp
;
4273 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4276 if (infoPtr
->iVersion
>= 5)
4279 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlDef
,
4280 &infoPtr
->cimlDef
, himl
, id
);
4282 infoPtr
->nNumBitmaps
= 0;
4283 for (i
= 0; i
< infoPtr
->cimlDef
; i
++)
4284 infoPtr
->nNumBitmaps
+= ImageList_GetImageCount(infoPtr
->himlDef
[i
]->himl
);
4286 ImageList_GetIconSize(himl
, &infoPtr
->nBitmapWidth
,
4287 &infoPtr
->nBitmapHeight
);
4288 TRACE("hwnd %p, new himl=%08x, count=%d, bitmap w=%d, h=%d\n",
4289 hwnd
, (INT
)infoPtr
->himlDef
, infoPtr
->nNumBitmaps
,
4290 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
4292 /* FIXME: redraw ? */
4293 InvalidateRect(hwnd
, NULL
, TRUE
);
4295 return (LRESULT
)himlTemp
;
4300 TOOLBAR_SetIndent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4302 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4304 infoPtr
->nIndent
= (INT
)wParam
;
4308 /* process only on indent changing */
4309 if(infoPtr
->nIndent
!= (INT
)wParam
)
4311 infoPtr
->nIndent
= (INT
)wParam
;
4312 TOOLBAR_CalcToolbar (hwnd
);
4313 InvalidateRect(hwnd
, NULL
, FALSE
);
4320 /* << TOOLBAR_SetInsertMark >> */
4324 TOOLBAR_SetInsertMarkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4326 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4328 infoPtr
->clrInsertMark
= (COLORREF
)lParam
;
4330 /* FIXME : redraw ??*/
4337 TOOLBAR_SetMaxTextRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4339 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4341 if (infoPtr
== NULL
)
4344 infoPtr
->nMaxTextRows
= (INT
)wParam
;
4351 TOOLBAR_SetPadding (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4353 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4356 oldPad
= MAKELONG(infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
4357 infoPtr
->szPadding
.cx
= LOWORD((DWORD
)lParam
);
4358 infoPtr
->szPadding
.cy
= HIWORD((DWORD
)lParam
);
4359 FIXME("stub - nothing done with values, cx=%ld, cy=%ld\n",
4360 infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
4361 return (LRESULT
) oldPad
;
4366 TOOLBAR_SetParent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4368 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4373 if (infoPtr
== NULL
)
4375 hwndOldNotify
= infoPtr
->hwndNotify
;
4376 infoPtr
->hwndNotify
= (HWND
)wParam
;
4378 return (LRESULT
)hwndOldNotify
;
4383 TOOLBAR_SetRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4385 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4386 LPRECT lprc
= (LPRECT
)lParam
;
4390 if (LOWORD(wParam
) > 1) {
4391 FIXME("multiple rows not supported!\n");
4394 if(infoPtr
->nRows
!= LOWORD(wParam
))
4396 infoPtr
->nRows
= LOWORD(wParam
);
4398 /* recalculate toolbar */
4399 TOOLBAR_CalcToolbar (hwnd
);
4401 /* repaint toolbar */
4402 InvalidateRect(hwnd
, NULL
, FALSE
);
4405 /* return bounding rectangle */
4407 lprc
->left
= infoPtr
->rcBound
.left
;
4408 lprc
->right
= infoPtr
->rcBound
.right
;
4409 lprc
->top
= infoPtr
->rcBound
.top
;
4410 lprc
->bottom
= infoPtr
->rcBound
.bottom
;
4418 TOOLBAR_SetState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4420 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4421 TBUTTON_INFO
*btnPtr
;
4424 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
4428 btnPtr
= &infoPtr
->buttons
[nIndex
];
4430 /* if hidden state has changed the invalidate entire window and recalc */
4431 if ((btnPtr
->fsState
& TBSTATE_HIDDEN
) != (LOWORD(lParam
) & TBSTATE_HIDDEN
)) {
4432 btnPtr
->fsState
= LOWORD(lParam
);
4433 TOOLBAR_CalcToolbar (hwnd
);
4434 InvalidateRect(hwnd
, 0, TOOLBAR_HasText(infoPtr
, btnPtr
));
4438 /* process state changing if current state doesn't match new state */
4439 if(btnPtr
->fsState
!= LOWORD(lParam
))
4441 btnPtr
->fsState
= LOWORD(lParam
);
4442 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
4451 TOOLBAR_SetStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4453 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4454 TBUTTON_INFO
*btnPtr
;
4457 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
4461 btnPtr
= &infoPtr
->buttons
[nIndex
];
4463 /* process style change if current style doesn't match new style */
4464 if(btnPtr
->fsStyle
!= LOWORD(lParam
))
4466 btnPtr
->fsStyle
= LOWORD(lParam
);
4467 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
4470 if (infoPtr
->hwndToolTip
) {
4471 FIXME("change tool tip!\n");
4479 inline static LRESULT
4480 TOOLBAR_SetToolTips (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4482 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4484 if (infoPtr
== NULL
)
4486 infoPtr
->hwndToolTip
= (HWND
)wParam
;
4492 TOOLBAR_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4494 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4497 TRACE("%s hwnd=%p stub!\n",
4498 ((BOOL
)wParam
) ? "TRUE" : "FALSE", hwnd
);
4500 bTemp
= infoPtr
->bUnicode
;
4501 infoPtr
->bUnicode
= (BOOL
)wParam
;
4508 TOOLBAR_GetColorScheme (HWND hwnd
, LPCOLORSCHEME lParam
)
4510 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4512 lParam
->clrBtnHighlight
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
4513 comctl32_color
.clrBtnHighlight
:
4514 infoPtr
->clrBtnHighlight
;
4515 lParam
->clrBtnShadow
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
4516 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
4522 TOOLBAR_SetColorScheme (HWND hwnd
, LPCOLORSCHEME lParam
)
4524 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4526 TRACE("new colors Hl=%lx Shd=%lx, old colors Hl=%lx Shd=%lx\n",
4527 lParam
->clrBtnHighlight
, lParam
->clrBtnShadow
,
4528 infoPtr
->clrBtnHighlight
, infoPtr
->clrBtnShadow
);
4530 infoPtr
->clrBtnHighlight
= lParam
->clrBtnHighlight
;
4531 infoPtr
->clrBtnShadow
= lParam
->clrBtnShadow
;
4532 InvalidateRect(hwnd
, 0, 0);
4538 TOOLBAR_SetVersion (HWND hwnd
, INT iVersion
)
4540 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4541 INT iOldVersion
= infoPtr
->iVersion
;
4543 infoPtr
->iVersion
= iVersion
;
4545 if (infoPtr
->iVersion
>= 5)
4546 TOOLBAR_SetUnicodeFormat(hwnd
, (WPARAM
)TRUE
, (LPARAM
)0);
4552 /*********************************************************************/
4554 /* This is undocumented and appears to be a "Super" TB_SETHOTITEM */
4555 /* without the restriction of TBSTYLE_FLAT. This implementation is */
4556 /* based on relay traces of the native control and IE 5.5 */
4558 /*********************************************************************/
4560 TOOLBAR_Unkwn45E (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4562 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4563 INT nOldHotItem
= infoPtr
->nHotItem
;
4564 TBUTTON_INFO
*btnPtr
;
4566 NMTBHOTITEM nmhotitem
;
4568 if ((INT
) wParam
< 0 || (INT
)wParam
> infoPtr
->nNumButtons
)
4571 infoPtr
->nHotItem
= (INT
)wParam
;
4572 if (nOldHotItem
!= infoPtr
->nHotItem
) {
4573 nmhotitem
.dwFlags
= (DWORD
)lParam
;
4574 if ( !(nmhotitem
.dwFlags
& HICF_ENTERING
) )
4575 nmhotitem
.idOld
= (nOldHotItem
>= 0) ?
4576 infoPtr
->buttons
[nOldHotItem
].idCommand
: 0;
4577 if ( !(nmhotitem
.dwFlags
& HICF_LEAVING
) )
4578 nmhotitem
.idNew
= (infoPtr
->nHotItem
>= 0) ?
4579 infoPtr
->buttons
[infoPtr
->nHotItem
].idCommand
: 0;
4580 no_hi
= TOOLBAR_SendNotify((NMHDR
*)&nmhotitem
, infoPtr
, TBN_HOTITEMCHANGE
);
4582 if ((INT
)wParam
>=0) {
4583 btnPtr
= &infoPtr
->buttons
[(INT
)wParam
];
4584 btnPtr
->bHot
= (no_hi
) ? FALSE
: TRUE
;
4585 InvalidateRect (hwnd
, &btnPtr
->rect
,
4586 TOOLBAR_HasText(infoPtr
, btnPtr
));
4588 if (nOldHotItem
>=0) {
4589 btnPtr
= &infoPtr
->buttons
[nOldHotItem
];
4590 btnPtr
->bHot
= FALSE
;
4591 InvalidateRect (hwnd
, &btnPtr
->rect
,
4592 TOOLBAR_HasText(infoPtr
, btnPtr
));
4595 TRACE("old item=%d, new item=%d, flags=%08lx, notify=%d\n",
4596 nOldHotItem
, infoPtr
->nHotItem
, (DWORD
)lParam
, no_hi
);
4598 if (nOldHotItem
< 0)
4601 return (LRESULT
)nOldHotItem
;
4606 TOOLBAR_Unkwn463 (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4608 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4609 LPSIZE lpsize
= (LPSIZE
)lParam
;
4615 * Testing shows the following:
4616 * wParam = 0 adjust cx value
4617 * = 1 set cy value to max size.
4618 * lParam pointer to SIZE structure
4621 TRACE("[0463] wParam %d, lParam 0x%08lx -> 0x%08lx 0x%08lx\n",
4622 wParam
, lParam
, lpsize
->cx
, lpsize
->cy
);
4626 if (lpsize
->cx
== -1) {
4627 /* **** this is wrong, native measures each button and sets it */
4628 lpsize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
4630 else if(HIWORD(lpsize
->cx
)) {
4632 HWND hwndParent
= GetParent(hwnd
);
4634 InvalidateRect(hwnd
, 0, 1);
4635 GetWindowRect(hwnd
, &rc
);
4636 MapWindowPoints(0, hwndParent
, (LPPOINT
)&rc
, 2);
4637 TRACE("mapped to (%ld,%ld)-(%ld,%ld)\n",
4638 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4639 lpsize
->cx
= max(rc
.right
-rc
.left
,
4640 infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
);
4643 lpsize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
4647 lpsize
->cy
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
4648 /* lpsize->cy = infoPtr->nHeight; */
4651 ERR("Unknown wParam %d for Toolbar message [0463]. Please report\n",
4655 TRACE("[0463] set to -> 0x%08lx 0x%08lx\n",
4656 lpsize
->cx
, lpsize
->cy
);
4662 TOOLBAR_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4664 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4665 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
4668 /* initialize info structure */
4669 infoPtr
->nButtonHeight
= 22;
4670 infoPtr
->nButtonWidth
= 24;
4671 infoPtr
->nBitmapHeight
= 15;
4672 infoPtr
->nBitmapWidth
= 16;
4674 infoPtr
->nHeight
= infoPtr
->nButtonHeight
+ TOP_BORDER
+ BOTTOM_BORDER
;
4676 infoPtr
->nMaxTextRows
= 1;
4677 infoPtr
->cxMin
= -1;
4678 infoPtr
->cxMax
= -1;
4679 infoPtr
->nNumBitmaps
= 0;
4680 infoPtr
->nNumStrings
= 0;
4682 infoPtr
->bCaptured
= FALSE
;
4683 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
4684 infoPtr
->nButtonDown
= -1;
4685 infoPtr
->nOldHit
= -1;
4686 infoPtr
->nHotItem
= -2; /* It has to be initially different from nOldHit */
4687 infoPtr
->hwndNotify
= GetParent (hwnd
);
4688 infoPtr
->bTransparent
= (dwStyle
& TBSTYLE_TRANSPARENT
);
4689 infoPtr
->bBtnTranspnt
= (dwStyle
& (TBSTYLE_FLAT
| TBSTYLE_LIST
));
4690 infoPtr
->dwDTFlags
= (dwStyle
& TBSTYLE_LIST
) ? DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
: DT_CENTER
;
4691 infoPtr
->bAnchor
= FALSE
; /* no anchor highlighting */
4692 infoPtr
->iVersion
= 0;
4693 infoPtr
->hwndSelf
= hwnd
;
4694 infoPtr
->bDoRedraw
= TRUE
;
4695 infoPtr
->clrBtnHighlight
= CLR_DEFAULT
;
4696 infoPtr
->clrBtnShadow
= CLR_DEFAULT
;
4697 infoPtr
->szPadding
.cx
= 7;
4698 infoPtr
->szPadding
.cy
= 6;
4699 TOOLBAR_NotifyFormat(infoPtr
, (WPARAM
)hwnd
, (LPARAM
)NF_REQUERY
);
4701 SystemParametersInfoA (SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0);
4702 infoPtr
->hFont
= infoPtr
->hDefaultFont
= CreateFontIndirectA (&logFont
);
4704 if (dwStyle
& TBSTYLE_TOOLTIPS
) {
4705 /* Create tooltip control */
4706 infoPtr
->hwndToolTip
=
4707 CreateWindowExA (0, TOOLTIPS_CLASSA
, NULL
, 0,
4708 CW_USEDEFAULT
, CW_USEDEFAULT
,
4709 CW_USEDEFAULT
, CW_USEDEFAULT
,
4712 /* Send NM_TOOLTIPSCREATED notification */
4713 if (infoPtr
->hwndToolTip
) {
4714 NMTOOLTIPSCREATED nmttc
;
4716 nmttc
.hwndToolTips
= infoPtr
->hwndToolTip
;
4718 TOOLBAR_SendNotify ((NMHDR
*) &nmttc
, infoPtr
,
4719 NM_TOOLTIPSCREATED
);
4723 TOOLBAR_CheckStyle (hwnd
, dwStyle
);
4725 TOOLBAR_CalcToolbar(hwnd
);
4732 TOOLBAR_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4734 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4736 /* delete tooltip control */
4737 if (infoPtr
->hwndToolTip
)
4738 DestroyWindow (infoPtr
->hwndToolTip
);
4740 /* delete button data */
4741 if (infoPtr
->buttons
)
4742 COMCTL32_Free (infoPtr
->buttons
);
4744 /* delete strings */
4745 if (infoPtr
->strings
) {
4747 for (i
= 0; i
< infoPtr
->nNumStrings
; i
++)
4748 if (infoPtr
->strings
[i
])
4749 COMCTL32_Free (infoPtr
->strings
[i
]);
4751 COMCTL32_Free (infoPtr
->strings
);
4754 /* destroy internal image list */
4755 if (infoPtr
->himlInt
)
4756 ImageList_Destroy (infoPtr
->himlInt
);
4758 TOOLBAR_DeleteImageList(&infoPtr
->himlDef
, &infoPtr
->cimlDef
);
4759 TOOLBAR_DeleteImageList(&infoPtr
->himlDis
, &infoPtr
->cimlDis
);
4760 TOOLBAR_DeleteImageList(&infoPtr
->himlHot
, &infoPtr
->cimlHot
);
4762 /* delete default font */
4764 DeleteObject (infoPtr
->hDefaultFont
);
4766 /* free toolbar info data */
4767 COMCTL32_Free (infoPtr
);
4768 SetWindowLongA (hwnd
, 0, 0);
4775 TOOLBAR_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4777 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4778 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
4779 NMTBCUSTOMDRAW tbcd
;
4783 if (dwStyle
& TBSTYLE_CUSTOMERASE
) {
4784 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
4785 tbcd
.nmcd
.dwDrawStage
= CDDS_PREERASE
;
4786 tbcd
.nmcd
.hdc
= (HDC
)wParam
;
4787 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
4788 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
4790 /* FIXME: in general the return flags *can* be or'ed together */
4791 switch (infoPtr
->dwBaseCustDraw
)
4793 case CDRF_DODEFAULT
:
4795 case CDRF_SKIPDEFAULT
:
4798 FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4803 /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up
4804 * to my parent for processing.
4806 if (infoPtr
->bTransparent
) {
4808 HDC hdc
= (HDC
)wParam
;
4813 parent
= GetParent(hwnd
);
4814 MapWindowPoints(hwnd
, parent
, &pt
, 1);
4815 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
4816 ret
= SendMessageA (parent
, WM_ERASEBKGND
, wParam
, lParam
);
4817 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
4820 ret
= DefWindowProcA (hwnd
, WM_ERASEBKGND
, wParam
, lParam
);
4822 if ((dwStyle
& TBSTYLE_CUSTOMERASE
) &&
4823 (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYPOSTERASE
)) {
4824 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
4825 tbcd
.nmcd
.dwDrawStage
= CDDS_POSTERASE
;
4826 tbcd
.nmcd
.hdc
= (HDC
)wParam
;
4827 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
4828 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
4829 switch (infoPtr
->dwBaseCustDraw
)
4831 case CDRF_DODEFAULT
:
4833 case CDRF_SKIPDEFAULT
:
4836 FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4845 TOOLBAR_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4847 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4849 return (LRESULT
)infoPtr
->hFont
;
4854 TOOLBAR_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4856 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4857 TBUTTON_INFO
*btnPtr
;
4861 pt
.x
= (INT
)LOWORD(lParam
);
4862 pt
.y
= (INT
)HIWORD(lParam
);
4863 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
4866 btnPtr
= &infoPtr
->buttons
[nHit
];
4867 if (!(btnPtr
->fsState
& TBSTATE_ENABLED
))
4870 infoPtr
->bCaptured
= TRUE
;
4871 infoPtr
->nButtonDown
= nHit
;
4873 btnPtr
->fsState
|= TBSTATE_PRESSED
;
4875 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
4878 else if (GetWindowLongA (hwnd
, GWL_STYLE
) & CCS_ADJUSTABLE
)
4879 TOOLBAR_Customize (hwnd
);
4886 TOOLBAR_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4888 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4889 TBUTTON_INFO
*btnPtr
;
4894 if (infoPtr
->hwndToolTip
)
4895 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
4896 WM_LBUTTONDOWN
, wParam
, lParam
);
4898 pt
.x
= (INT
)LOWORD(lParam
);
4899 pt
.y
= (INT
)HIWORD(lParam
);
4900 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
4904 btnPtr
= &infoPtr
->buttons
[nHit
];
4905 infoPtr
->nOldHit
= nHit
;
4907 CopyRect(&arrowRect
, &btnPtr
->rect
);
4908 arrowRect
.left
= max(btnPtr
->rect
.left
, btnPtr
->rect
.right
- DDARROW_WIDTH
);
4910 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
4911 if ((btnPtr
->fsState
& TBSTATE_ENABLED
) && (btnPtr
->fsStyle
& TBSTYLE_DROPDOWN
) &&
4912 ((TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
) && PtInRect(&arrowRect
, pt
)) ||
4913 (!TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
))))
4917 * this time we must force a Redraw, so the btn is
4918 * painted down before CaptureChanged repaints it up
4920 RedrawWindow(hwnd
,&btnPtr
->rect
,0,
4921 RDW_ERASE
|RDW_INVALIDATE
|RDW_UPDATENOW
);
4923 nmtb
.iItem
= btnPtr
->idCommand
;
4924 memset(&nmtb
.tbButton
, 0, sizeof(TBBUTTON
));
4927 memset(&nmtb
.rcButton
, 0, sizeof(RECT
));
4928 res
= TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
4930 if (res
!= TBDDRET_TREATPRESSED
)
4931 /* ??? guess (GA) */
4933 /* otherwise drop through and process as pushed */
4935 /* SetCapture (hwnd); */
4936 infoPtr
->bCaptured
= TRUE
;
4937 infoPtr
->nButtonDown
= nHit
;
4939 btnPtr
->fsState
|= TBSTATE_PRESSED
;
4940 btnPtr
->bHot
= FALSE
;
4942 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
4943 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
4947 /* native issues the TBN_BEGINDRAG here */
4948 nmtb
.iItem
= btnPtr
->idCommand
;
4949 nmtb
.tbButton
.iBitmap
= btnPtr
->iBitmap
;
4950 nmtb
.tbButton
.idCommand
= btnPtr
->idCommand
;
4951 nmtb
.tbButton
.fsState
= btnPtr
->fsState
;
4952 nmtb
.tbButton
.fsStyle
= btnPtr
->fsStyle
;
4953 nmtb
.tbButton
.dwData
= btnPtr
->dwData
;
4954 nmtb
.tbButton
.iString
= btnPtr
->iString
;
4955 nmtb
.cchText
= 0; /* !!! not correct */
4956 nmtb
.pszText
= 0; /* !!! not correct */
4957 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
4965 TOOLBAR_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4967 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4968 TBUTTON_INFO
*btnPtr
;
4972 BOOL bSendMessage
= TRUE
;
4977 if (infoPtr
->hwndToolTip
)
4978 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
4979 WM_LBUTTONUP
, wParam
, lParam
);
4981 pt
.x
= (INT
)LOWORD(lParam
);
4982 pt
.y
= (INT
)HIWORD(lParam
);
4983 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
4985 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
4986 /* if the cursor is still inside of the toolbar */
4987 if((infoPtr
->nHotItem
>= 0) && (nHit
!= -1))
4988 infoPtr
->buttons
[infoPtr
->nHotItem
].bHot
= TRUE
;
4990 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
4991 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
4993 if (btnPtr
->fsStyle
& TBSTYLE_CHECK
) {
4994 if (btnPtr
->fsStyle
& TBSTYLE_GROUP
) {
4995 nOldIndex
= TOOLBAR_GetCheckedGroupButtonIndex (infoPtr
,
4997 if (nOldIndex
== nHit
)
4998 bSendMessage
= FALSE
;
4999 if ((nOldIndex
!= nHit
) &&
5001 infoPtr
->buttons
[nOldIndex
].fsState
&= ~TBSTATE_CHECKED
;
5002 btnPtr
->fsState
|= TBSTATE_CHECKED
;
5005 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
5006 btnPtr
->fsState
&= ~TBSTATE_CHECKED
;
5008 btnPtr
->fsState
|= TBSTATE_CHECKED
;
5012 if (nOldIndex
!= -1)
5014 InvalidateRect(hwnd
, &infoPtr
->buttons
[nOldIndex
].rect
,
5015 TOOLBAR_HasText(infoPtr
, &infoPtr
->buttons
[nOldIndex
]));
5019 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
5020 * that resets bCaptured and btn TBSTATE_PRESSED flags,
5021 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
5023 if ((infoPtr
->bCaptured
) && (infoPtr
->nButtonDown
>= 0))
5025 infoPtr
->nButtonDown
= -1;
5027 /* Issue NM_RELEASEDCAPTURE to parent to let him know it is released */
5028 TOOLBAR_SendNotify ((NMHDR
*) &hdr
, infoPtr
,
5029 NM_RELEASEDCAPTURE
);
5031 /* native issues TBN_ENDDRAG here, if _LBUTTONDOWN issued the
5034 nmtb
.iItem
= btnPtr
->idCommand
;
5035 nmtb
.tbButton
.iBitmap
= btnPtr
->iBitmap
;
5036 nmtb
.tbButton
.idCommand
= btnPtr
->idCommand
;
5037 nmtb
.tbButton
.fsState
= btnPtr
->fsState
;
5038 nmtb
.tbButton
.fsStyle
= btnPtr
->fsStyle
;
5039 nmtb
.tbButton
.dwData
= btnPtr
->dwData
;
5040 nmtb
.tbButton
.iString
= btnPtr
->iString
;
5041 nmtb
.cchText
= 0; /* !!! not correct */
5042 nmtb
.pszText
= 0; /* !!! not correct */
5043 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
5046 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
5048 SendMessageA (infoPtr
->hwndNotify
, WM_COMMAND
,
5049 MAKEWPARAM(infoPtr
->buttons
[nHit
].idCommand
, 0), (LPARAM
)hwnd
);
5051 /* !!! Undocumented - toolbar at 4.71 level and above sends
5052 * either NMRCLICK or NM_CLICK with the NMMOUSE structure.
5053 * Only NM_RCLICK is documented.
5055 nmmouse
.dwItemSpec
= btnPtr
->idCommand
;
5056 nmmouse
.dwItemData
= btnPtr
->dwData
;
5057 TOOLBAR_SendNotify ((NMHDR
*) &nmmouse
, infoPtr
, NM_CLICK
);
5063 TOOLBAR_CaptureChanged(HWND hwnd
)
5065 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5066 TBUTTON_INFO
*btnPtr
;
5068 infoPtr
->bCaptured
= FALSE
;
5070 if (infoPtr
->nButtonDown
>= 0)
5072 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5073 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5075 infoPtr
->nOldHit
= -1;
5077 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
5078 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
5085 TOOLBAR_MouseLeave (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5087 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5088 TBUTTON_INFO
*hotBtnPtr
, *btnPtr
;
5091 if (infoPtr
->nOldHit
< 0)
5094 hotBtnPtr
= &infoPtr
->buttons
[infoPtr
->nOldHit
];
5096 /* Redraw the button if the last button we were over is the hot button and it
5098 if((infoPtr
->nOldHit
== infoPtr
->nHotItem
) && (hotBtnPtr
->fsState
& TBSTATE_ENABLED
))
5100 hotBtnPtr
->bHot
= FALSE
;
5101 rc1
= hotBtnPtr
->rect
;
5102 InflateRect (&rc1
, 1, 1);
5103 InvalidateRect (hwnd
, &rc1
, TOOLBAR_HasText(infoPtr
,
5107 /* If the last button we were over is depressed then make it not */
5108 /* depressed and redraw it */
5109 if(infoPtr
->nOldHit
== infoPtr
->nButtonDown
)
5111 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5113 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5115 rc1
= hotBtnPtr
->rect
;
5116 InflateRect (&rc1
, 1, 1);
5117 InvalidateRect (hwnd
, &rc1
, TRUE
);
5120 infoPtr
->nOldHit
= -1; /* reset the old hit index as we've left the toolbar */
5121 infoPtr
->nHotItem
= -2; /* It has to be initially different from nOldHit */
5127 TOOLBAR_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5129 TBUTTON_INFO
*btnPtr
= NULL
, *oldBtnPtr
= NULL
;
5130 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5133 TRACKMOUSEEVENT trackinfo
;
5134 NMTBHOTITEM nmhotitem
;
5136 /* fill in the TRACKMOUSEEVENT struct */
5137 trackinfo
.cbSize
= sizeof(TRACKMOUSEEVENT
);
5138 trackinfo
.dwFlags
= TME_QUERY
;
5139 trackinfo
.hwndTrack
= hwnd
;
5140 trackinfo
.dwHoverTime
= HOVER_DEFAULT
;
5142 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
5143 _TrackMouseEvent(&trackinfo
);
5145 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
5146 if(!(trackinfo
.dwFlags
& TME_LEAVE
)) {
5147 trackinfo
.dwFlags
= TME_LEAVE
; /* notify upon leaving */
5149 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
5150 /* and can properly deactivate the hot toolbar button */
5151 _TrackMouseEvent(&trackinfo
);
5154 if (infoPtr
->hwndToolTip
)
5155 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
5156 WM_MOUSEMOVE
, wParam
, lParam
);
5158 pt
.x
= (INT
)LOWORD(lParam
);
5159 pt
.y
= (INT
)HIWORD(lParam
);
5161 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
5163 if (infoPtr
->nOldHit
!= nHit
)
5165 /* Remove the effect of an old hot button if the button was enabled and was
5166 drawn with the hot button effect */
5167 if(infoPtr
->nOldHit
>= 0 && infoPtr
->nOldHit
== infoPtr
->nHotItem
&&
5168 (infoPtr
->buttons
[infoPtr
->nOldHit
].fsState
& TBSTATE_ENABLED
))
5170 oldBtnPtr
= &infoPtr
->buttons
[infoPtr
->nOldHit
];
5171 oldBtnPtr
->bHot
= FALSE
;
5174 /* It's not a separator or in nowhere. It's a hot button. */
5177 btnPtr
= &infoPtr
->buttons
[nHit
];
5179 infoPtr
->nHotItem
= nHit
;
5181 /* only enabled buttons show hot effect */
5182 if(infoPtr
->buttons
[nHit
].fsState
& TBSTATE_ENABLED
)
5184 btnPtr
->bHot
= TRUE
;
5188 nmhotitem
.dwFlags
= HICF_MOUSE
;
5190 nmhotitem
.idOld
= oldBtnPtr
->idCommand
;
5192 nmhotitem
.dwFlags
|= HICF_ENTERING
;
5194 nmhotitem
.idNew
= btnPtr
->idCommand
;
5196 nmhotitem
.dwFlags
|= HICF_LEAVING
;
5197 TOOLBAR_SendNotify((NMHDR
*)&nmhotitem
, infoPtr
, TBN_HOTITEMCHANGE
);
5199 /* now invalidate the old and new buttons so they will be painted */
5201 InvalidateRect (hwnd
, &oldBtnPtr
->rect
,
5202 TOOLBAR_HasText(infoPtr
, oldBtnPtr
));
5203 if (btnPtr
&& (btnPtr
->fsState
& TBSTATE_ENABLED
))
5204 InvalidateRect(hwnd
, &btnPtr
->rect
,
5205 TOOLBAR_HasText(infoPtr
, btnPtr
));
5207 if (infoPtr
->bCaptured
) {
5208 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5209 if (infoPtr
->nOldHit
== infoPtr
->nButtonDown
) {
5210 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5211 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
5213 else if (nHit
== infoPtr
->nButtonDown
) {
5214 btnPtr
->fsState
|= TBSTATE_PRESSED
;
5215 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
5218 infoPtr
->nOldHit
= nHit
;
5224 inline static LRESULT
5225 TOOLBAR_NCActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5227 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
5228 return DefWindowProcA (hwnd
, WM_NCACTIVATE
, wParam
, lParam
);
5230 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
5234 inline static LRESULT
5235 TOOLBAR_NCCalcSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5237 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & CCS_NODIVIDER
))
5238 ((LPRECT
)lParam
)->top
+= GetSystemMetrics(SM_CYEDGE
);
5240 return DefWindowProcA (hwnd
, WM_NCCALCSIZE
, wParam
, lParam
);
5245 TOOLBAR_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5247 TOOLBAR_INFO
*infoPtr
;
5248 LPCREATESTRUCTA cs
= (LPCREATESTRUCTA
)lParam
;
5251 /* allocate memory for info structure */
5252 infoPtr
= (TOOLBAR_INFO
*)COMCTL32_Alloc (sizeof(TOOLBAR_INFO
));
5253 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
5256 infoPtr
->dwStructSize
= sizeof(TBBUTTON
);
5258 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
5259 if (!GetWindowLongA (hwnd
, GWL_HINSTANCE
)) {
5260 HINSTANCE hInst
= (HINSTANCE
)GetWindowLongA (GetParent (hwnd
), GWL_HINSTANCE
);
5261 SetWindowLongA (hwnd
, GWL_HINSTANCE
, (DWORD
)hInst
);
5264 /* native control does:
5265 * Get a lot of colors and brushes
5267 * SystemParametersInfoA(0x1f, 0x3c, adr1, 0)
5268 * CreateFontIndirectA(adr1)
5269 * CreateBitmap(0x27, 0x24, 1, 1, 0)
5270 * hdc = GetDC(toolbar)
5271 * GetSystemMetrics(0x48)
5272 * fnt2=CreateFontA(0xe, 0, 0, 0, 0x190, 0, 0, 0, 0, 2,
5273 * 0, 0, 0, 0, "MARLETT")
5274 * oldfnt = SelectObject(hdc, fnt2)
5275 * GetCharWidthA(hdc, 0x36, 0x36, adr2)
5276 * GetTextMetricsA(hdc, adr3)
5277 * SelectObject(hdc, oldfnt)
5278 * DeleteObject(fnt2)
5280 * InvalidateRect(toolbar, 0, 1)
5281 * SetWindowLongA(toolbar, 0, addr)
5282 * SetWindowLongA(toolbar, -16, xxx) **sometimes**
5285 * ie 1 0x56000a4c 0x46000a4c 0x56008a4d
5286 * ie 2 0x4600094c 0x4600094c 0x4600894d
5287 * ie 3 0x56000b4c 0x46000b4c 0x56008b4d
5288 * rebar 0x50008844 0x40008844 0x50008845
5289 * pager 0x50000844 0x40000844 0x50008845
5290 * IC35mgr 0x5400084e **nochange**
5291 * on entry to _NCCREATE 0x5400084e
5292 * rowlist 0x5400004e **nochange**
5293 * on entry to _NCCREATE 0x5400004e
5297 /* I think the code below is a bug, but it is the way that the native
5298 * controls seem to work. The effect is that if the user of TBSTYLE_FLAT
5299 * forgets to specify TBSTYLE_TRANSPARENT but does specify either
5300 * CCS_TOP or CCS_BOTTOM (_NOMOVEY and _TOP), then the control
5301 * does *not* set TBSTYLE_TRANSPARENT even though it should!!!!
5302 * Some how, the only cases of this seem to be MFC programs.
5304 * Note also that the addition of _TRANSPARENT occurs *only* here. It
5305 * does not occur in the WM_STYLECHANGING routine.
5306 * (Guy Albertelli 9/2001)
5309 if ((cs
->style
& TBSTYLE_FLAT
) && !(cs
->style
& TBSTYLE_TRANSPARENT
))
5310 styleadd
|= TBSTYLE_TRANSPARENT
;
5311 if (!(cs
->style
& (CCS_TOP
| CCS_NOMOVEY
))) {
5312 styleadd
|= CCS_TOP
; /* default to top */
5313 SetWindowLongA (hwnd
, GWL_STYLE
, cs
->style
| styleadd
);
5316 return DefWindowProcA (hwnd
, WM_NCCREATE
, wParam
, lParam
);
5321 TOOLBAR_NCPaint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5323 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
5327 if (dwStyle
& WS_MINIMIZE
)
5328 return 0; /* Nothing to do */
5330 DefWindowProcA (hwnd
, WM_NCPAINT
, wParam
, lParam
);
5332 if (!(hdc
= GetDCEx (hwnd
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
5335 if (!(dwStyle
& CCS_NODIVIDER
))
5337 GetWindowRect (hwnd
, &rcWindow
);
5338 OffsetRect (&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
5339 if( dwStyle
& WS_BORDER
)
5340 OffsetRect (&rcWindow
, 1, 1);
5341 DrawEdge (hdc
, &rcWindow
, EDGE_ETCHED
, BF_TOP
);
5344 ReleaseDC( hwnd
, hdc
);
5350 inline static LRESULT
5351 TOOLBAR_Notify (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5353 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5354 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
5356 if (lpnmh
->code
== PGN_CALCSIZE
) {
5357 LPNMPGCALCSIZE lppgc
= (LPNMPGCALCSIZE
)lParam
;
5359 if (lppgc
->dwFlag
== PGF_CALCWIDTH
) {
5360 lppgc
->iWidth
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
5361 TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
5365 lppgc
->iHeight
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
5366 TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
5372 if (lpnmh
->code
== PGN_SCROLL
) {
5373 LPNMPGSCROLL lppgs
= (LPNMPGSCROLL
)lParam
;
5375 lppgs
->iScroll
= (lppgs
->iDir
& (PGF_SCROLLLEFT
| PGF_SCROLLRIGHT
)) ?
5376 infoPtr
->nButtonWidth
: infoPtr
->nButtonHeight
;
5377 TRACE("processed PGN_SCROLL, returning scroll=%d, dir=%d\n",
5378 lppgs
->iScroll
, lppgs
->iDir
);
5383 TRACE("passing WM_NOTIFY!\n");
5385 if ((infoPtr
->hwndToolTip
) && (lpnmh
->hwndFrom
== infoPtr
->hwndToolTip
)) {
5386 if (infoPtr
->bNtfUnicode
)
5387 return SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
5390 return SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
5394 if (lpnmh
->code
== TTN_GETDISPINFOA
) {
5395 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
5397 FIXME("retrieving ASCII string\n");
5400 else if (lpnmh
->code
== TTN_GETDISPINFOW
) {
5401 LPNMTTDISPINFOW lpdi
= (LPNMTTDISPINFOW
)lParam
;
5403 FIXME("retrieving UNICODE string\n");
5414 TOOLBAR_NotifyFormatFake(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5416 /* remove this routine when Toolbar is improved to pass infoPtr
5417 * around instead of hwnd.
5419 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
5420 return TOOLBAR_NotifyFormat(infoPtr
, wParam
, lParam
);
5425 TOOLBAR_NotifyFormat(TOOLBAR_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
5429 if (lParam
== NF_REQUERY
) {
5430 i
= SendMessageA(GetParent(infoPtr
->hwndSelf
),
5431 WM_NOTIFYFORMAT
, (WPARAM
)infoPtr
->hwndSelf
, NF_QUERY
);
5432 if ((i
< NFR_ANSI
) || (i
> NFR_UNICODE
)) {
5433 ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n",
5437 infoPtr
->bNtfUnicode
= (i
== NFR_UNICODE
) ? 1 : 0;
5440 return (LRESULT
)((infoPtr
->bUnicode
) ? NFR_UNICODE
: NFR_ANSI
);
5445 TOOLBAR_Paint (HWND hwnd
, WPARAM wParam
)
5447 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
5451 /* fill ps.rcPaint with a default rect */
5452 memcpy(&(ps
.rcPaint
), &(infoPtr
->rcBound
), sizeof(infoPtr
->rcBound
));
5454 hdc
= wParam
==0 ? BeginPaint(hwnd
, &ps
) : (HDC
)wParam
;
5456 TRACE("psrect=(%ld,%ld)-(%ld,%ld)\n",
5457 ps
.rcPaint
.left
, ps
.rcPaint
.top
,
5458 ps
.rcPaint
.right
, ps
.rcPaint
.bottom
);
5460 TOOLBAR_Refresh (hwnd
, hdc
, &ps
);
5461 if (!wParam
) EndPaint (hwnd
, &ps
);
5468 TOOLBAR_SetRedraw (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5469 /*****************************************************
5472 * Handles the WM_SETREDRAW message.
5475 * According to testing V4.71 of COMCTL32 returns the
5476 * *previous* status of the redraw flag (either 0 or 1)
5477 * instead of the MSDN documented value of 0 if handled.
5478 * (For laughs see the "consistancy" with same function
5481 *****************************************************/
5483 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5484 BOOL oldredraw
= infoPtr
->bDoRedraw
;
5486 TRACE("set to %s\n",
5487 (wParam
) ? "TRUE" : "FALSE");
5488 infoPtr
->bDoRedraw
= (BOOL
) wParam
;
5490 InvalidateRect (infoPtr
->hwndSelf
, 0, TRUE
);
5492 return (oldredraw
) ? 1 : 0;
5497 TOOLBAR_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5499 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5500 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
5509 /* Resize deadlock check */
5510 if (infoPtr
->bAutoSize
) {
5511 infoPtr
->bAutoSize
= FALSE
;
5515 /* FIXME: optimize to only update size if the new size doesn't */
5516 /* match the current size */
5518 flags
= (INT
) wParam
;
5520 /* FIXME for flags =
5521 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
5524 TRACE("sizing toolbar!\n");
5526 if (flags
== SIZE_RESTORED
) {
5527 /* width and height don't apply */
5528 parent
= GetParent (hwnd
);
5529 GetClientRect(parent
, &parent_rect
);
5530 x
= parent_rect
.left
;
5531 y
= parent_rect
.top
;
5533 if (dwStyle
& CCS_NORESIZE
) {
5534 uPosFlags
|= (SWP_NOSIZE
| SWP_NOMOVE
);
5537 * this sets the working width of the toolbar, and
5538 * Calc Toolbar will not adjust it, only the height
5540 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
5541 cy
= infoPtr
->nHeight
;
5542 cx
= infoPtr
->nWidth
;
5543 TOOLBAR_CalcToolbar (hwnd
);
5544 infoPtr
->nWidth
= cx
;
5545 infoPtr
->nHeight
= cy
;
5548 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
5549 TOOLBAR_CalcToolbar (hwnd
);
5550 cy
= infoPtr
->nHeight
;
5551 cx
= infoPtr
->nWidth
;
5553 if (dwStyle
& CCS_NOMOVEY
) {
5554 GetWindowRect(hwnd
, &window_rect
);
5555 ScreenToClient(parent
, (LPPOINT
)&window_rect
.left
);
5556 y
= window_rect
.top
;
5560 if (dwStyle
& CCS_NOPARENTALIGN
) {
5561 uPosFlags
|= SWP_NOMOVE
;
5562 cy
= infoPtr
->nHeight
;
5563 cx
= infoPtr
->nWidth
;
5566 if (!(dwStyle
& CCS_NODIVIDER
))
5567 cy
+= GetSystemMetrics(SM_CYEDGE
);
5569 if (dwStyle
& WS_BORDER
)
5572 cy
+= GetSystemMetrics(SM_CYEDGE
);
5573 cx
+= GetSystemMetrics(SM_CYEDGE
);
5576 SetWindowPos (hwnd
, 0, parent_rect
.left
- x
, parent_rect
.top
- y
,
5577 cx
, cy
, uPosFlags
| SWP_NOZORDER
);
5584 TOOLBAR_StyleChanged (HWND hwnd
, INT nType
, LPSTYLESTRUCT lpStyle
)
5586 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5588 if (nType
== GWL_STYLE
) {
5589 if (lpStyle
->styleNew
& TBSTYLE_LIST
) {
5590 infoPtr
->dwDTFlags
= DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
;
5593 infoPtr
->dwDTFlags
= DT_CENTER
;
5595 infoPtr
->bTransparent
= (lpStyle
->styleNew
& TBSTYLE_TRANSPARENT
);
5596 infoPtr
->bBtnTranspnt
= (lpStyle
->styleNew
&
5597 (TBSTYLE_FLAT
| TBSTYLE_LIST
));
5598 TOOLBAR_CheckStyle (hwnd
, lpStyle
->styleNew
);
5601 TOOLBAR_AutoSize (hwnd
);
5603 InvalidateRect(hwnd
, NULL
, FALSE
);
5610 TOOLBAR_SysColorChange (HWND hwnd
)
5612 COMCTL32_RefreshSysColors();
5619 static LRESULT WINAPI
5620 ToolbarWindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
5622 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n",
5623 hwnd
, uMsg
, /* SPY_GetMsgName(uMsg), */ wParam
, lParam
);
5625 if (!TOOLBAR_GetInfoPtr(hwnd
) && (uMsg
!= WM_NCCREATE
))
5626 return DefWindowProcA( hwnd
, uMsg
, wParam
, lParam
);
5631 return TOOLBAR_AddBitmap (hwnd
, wParam
, lParam
);
5633 case TB_ADDBUTTONSA
:
5634 return TOOLBAR_AddButtonsA (hwnd
, wParam
, lParam
);
5636 case TB_ADDBUTTONSW
:
5637 return TOOLBAR_AddButtonsW (hwnd
, wParam
, lParam
);
5640 return TOOLBAR_AddStringA (hwnd
, wParam
, lParam
);
5643 return TOOLBAR_AddStringW (hwnd
, wParam
, lParam
);
5646 return TOOLBAR_AutoSize (hwnd
);
5648 case TB_BUTTONCOUNT
:
5649 return TOOLBAR_ButtonCount (hwnd
, wParam
, lParam
);
5651 case TB_BUTTONSTRUCTSIZE
:
5652 return TOOLBAR_ButtonStructSize (hwnd
, wParam
, lParam
);
5654 case TB_CHANGEBITMAP
:
5655 return TOOLBAR_ChangeBitmap (hwnd
, wParam
, lParam
);
5657 case TB_CHECKBUTTON
:
5658 return TOOLBAR_CheckButton (hwnd
, wParam
, lParam
);
5660 case TB_COMMANDTOINDEX
:
5661 return TOOLBAR_CommandToIndex (hwnd
, wParam
, lParam
);
5664 return TOOLBAR_Customize (hwnd
);
5666 case TB_DELETEBUTTON
:
5667 return TOOLBAR_DeleteButton (hwnd
, wParam
, lParam
);
5669 case TB_ENABLEBUTTON
:
5670 return TOOLBAR_EnableButton (hwnd
, wParam
, lParam
);
5672 case TB_GETANCHORHIGHLIGHT
:
5673 return TOOLBAR_GetAnchorHighlight (hwnd
);
5676 return TOOLBAR_GetBitmap (hwnd
, wParam
, lParam
);
5678 case TB_GETBITMAPFLAGS
:
5679 return TOOLBAR_GetBitmapFlags (hwnd
, wParam
, lParam
);
5682 return TOOLBAR_GetButton (hwnd
, wParam
, lParam
);
5684 case TB_GETBUTTONINFOA
:
5685 return TOOLBAR_GetButtonInfoA (hwnd
, wParam
, lParam
);
5687 case TB_GETBUTTONINFOW
:
5688 return TOOLBAR_GetButtonInfoW (hwnd
, wParam
, lParam
);
5690 case TB_GETBUTTONSIZE
:
5691 return TOOLBAR_GetButtonSize (hwnd
);
5693 case TB_GETBUTTONTEXTA
:
5694 return TOOLBAR_GetButtonTextA (hwnd
, wParam
, lParam
);
5696 case TB_GETBUTTONTEXTW
:
5697 return TOOLBAR_GetButtonTextW (hwnd
, wParam
, lParam
);
5699 case TB_GETDISABLEDIMAGELIST
:
5700 return TOOLBAR_GetDisabledImageList (hwnd
, wParam
, lParam
);
5702 case TB_GETEXTENDEDSTYLE
:
5703 return TOOLBAR_GetExtendedStyle (hwnd
);
5705 case TB_GETHOTIMAGELIST
:
5706 return TOOLBAR_GetHotImageList (hwnd
, wParam
, lParam
);
5709 return TOOLBAR_GetHotItem (hwnd
);
5711 case TB_GETIMAGELIST
:
5712 return TOOLBAR_GetDefImageList (hwnd
, wParam
, lParam
);
5714 /* case TB_GETINSERTMARK: */ /* 4.71 */
5715 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
5717 case TB_GETITEMRECT
:
5718 return TOOLBAR_GetItemRect (hwnd
, wParam
, lParam
);
5721 return TOOLBAR_GetMaxSize (hwnd
, wParam
, lParam
);
5723 /* case TB_GETOBJECT: */ /* 4.71 */
5726 return TOOLBAR_GetPadding (hwnd
);
5729 return TOOLBAR_GetRect (hwnd
, wParam
, lParam
);
5732 return TOOLBAR_GetRows (hwnd
, wParam
, lParam
);
5735 return TOOLBAR_GetState (hwnd
, wParam
, lParam
);
5738 return TOOLBAR_GetStyle (hwnd
, wParam
, lParam
);
5740 case TB_GETTEXTROWS
:
5741 return TOOLBAR_GetTextRows (hwnd
, wParam
, lParam
);
5743 case TB_GETTOOLTIPS
:
5744 return TOOLBAR_GetToolTips (hwnd
, wParam
, lParam
);
5746 case TB_GETUNICODEFORMAT
:
5747 return TOOLBAR_GetUnicodeFormat (hwnd
, wParam
, lParam
);
5750 return TOOLBAR_HideButton (hwnd
, wParam
, lParam
);
5753 return TOOLBAR_HitTest (hwnd
, wParam
, lParam
);
5755 case TB_INDETERMINATE
:
5756 return TOOLBAR_Indeterminate (hwnd
, wParam
, lParam
);
5758 case TB_INSERTBUTTONA
:
5759 return TOOLBAR_InsertButtonA (hwnd
, wParam
, lParam
);
5761 case TB_INSERTBUTTONW
:
5762 return TOOLBAR_InsertButtonW (hwnd
, wParam
, lParam
);
5764 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
5766 case TB_ISBUTTONCHECKED
:
5767 return TOOLBAR_IsButtonChecked (hwnd
, wParam
, lParam
);
5769 case TB_ISBUTTONENABLED
:
5770 return TOOLBAR_IsButtonEnabled (hwnd
, wParam
, lParam
);
5772 case TB_ISBUTTONHIDDEN
:
5773 return TOOLBAR_IsButtonHidden (hwnd
, wParam
, lParam
);
5775 case TB_ISBUTTONHIGHLIGHTED
:
5776 return TOOLBAR_IsButtonHighlighted (hwnd
, wParam
, lParam
);
5778 case TB_ISBUTTONINDETERMINATE
:
5779 return TOOLBAR_IsButtonIndeterminate (hwnd
, wParam
, lParam
);
5781 case TB_ISBUTTONPRESSED
:
5782 return TOOLBAR_IsButtonPressed (hwnd
, wParam
, lParam
);
5784 case TB_LOADIMAGES
: /* 4.70 */
5785 FIXME("missing standard imagelists\n");
5788 /* case TB_MAPACCELERATORA: */ /* 4.71 */
5789 /* case TB_MAPACCELERATORW: */ /* 4.71 */
5790 /* case TB_MARKBUTTON: */ /* 4.71 */
5791 /* case TB_MOVEBUTTON: */ /* 4.71 */
5793 case TB_PRESSBUTTON
:
5794 return TOOLBAR_PressButton (hwnd
, wParam
, lParam
);
5796 case TB_REPLACEBITMAP
:
5797 return TOOLBAR_ReplaceBitmap (hwnd
, wParam
, lParam
);
5799 case TB_SAVERESTOREA
:
5800 return TOOLBAR_SaveRestoreA (hwnd
, wParam
, lParam
);
5802 case TB_SAVERESTOREW
:
5803 return TOOLBAR_SaveRestoreW (hwnd
, wParam
, lParam
);
5805 case TB_SETANCHORHIGHLIGHT
:
5806 return TOOLBAR_SetAnchorHighlight (hwnd
, wParam
);
5808 case TB_SETBITMAPSIZE
:
5809 return TOOLBAR_SetBitmapSize (hwnd
, wParam
, lParam
);
5811 case TB_SETBUTTONINFOA
:
5812 return TOOLBAR_SetButtonInfoA (hwnd
, wParam
, lParam
);
5814 case TB_SETBUTTONINFOW
:
5815 return TOOLBAR_SetButtonInfoW (hwnd
, wParam
, lParam
);
5817 case TB_SETBUTTONSIZE
:
5818 return TOOLBAR_SetButtonSize (hwnd
, wParam
, lParam
);
5820 case TB_SETBUTTONWIDTH
:
5821 return TOOLBAR_SetButtonWidth (hwnd
, wParam
, lParam
);
5824 return TOOLBAR_SetCmdId (hwnd
, wParam
, lParam
);
5826 case TB_SETDISABLEDIMAGELIST
:
5827 return TOOLBAR_SetDisabledImageList (hwnd
, wParam
, lParam
);
5829 case TB_SETDRAWTEXTFLAGS
:
5830 return TOOLBAR_SetDrawTextFlags (hwnd
, wParam
, lParam
);
5832 case TB_SETEXTENDEDSTYLE
:
5833 return TOOLBAR_SetExtendedStyle (hwnd
, wParam
, lParam
);
5835 case TB_SETHOTIMAGELIST
:
5836 return TOOLBAR_SetHotImageList (hwnd
, wParam
, lParam
);
5839 return TOOLBAR_SetHotItem (hwnd
, wParam
);
5841 case TB_SETIMAGELIST
:
5842 return TOOLBAR_SetImageList (hwnd
, wParam
, lParam
);
5845 return TOOLBAR_SetIndent (hwnd
, wParam
, lParam
);
5847 /* case TB_SETINSERTMARK: */ /* 4.71 */
5849 case TB_SETINSERTMARKCOLOR
:
5850 return TOOLBAR_SetInsertMarkColor (hwnd
, wParam
, lParam
);
5852 case TB_SETMAXTEXTROWS
:
5853 return TOOLBAR_SetMaxTextRows (hwnd
, wParam
, lParam
);
5856 return TOOLBAR_SetPadding (hwnd
, wParam
, lParam
);
5859 return TOOLBAR_SetParent (hwnd
, wParam
, lParam
);
5862 return TOOLBAR_SetRows (hwnd
, wParam
, lParam
);
5865 return TOOLBAR_SetState (hwnd
, wParam
, lParam
);
5868 return TOOLBAR_SetStyle (hwnd
, wParam
, lParam
);
5870 case TB_SETTOOLTIPS
:
5871 return TOOLBAR_SetToolTips (hwnd
, wParam
, lParam
);
5873 case TB_SETUNICODEFORMAT
:
5874 return TOOLBAR_SetUnicodeFormat (hwnd
, wParam
, lParam
);
5877 return TOOLBAR_Unkwn45E (hwnd
, wParam
, lParam
);
5880 return TOOLBAR_Unkwn463 (hwnd
, wParam
, lParam
);
5883 /* Common Control Messages */
5885 /* case TB_GETCOLORSCHEME: */ /* identical to CCM_ */
5886 case CCM_GETCOLORSCHEME
:
5887 return TOOLBAR_GetColorScheme (hwnd
, (LPCOLORSCHEME
)lParam
);
5889 /* case TB_SETCOLORSCHEME: */ /* identical to CCM_ */
5890 case CCM_SETCOLORSCHEME
:
5891 return TOOLBAR_SetColorScheme (hwnd
, (LPCOLORSCHEME
)lParam
);
5893 case CCM_GETVERSION
:
5894 return TOOLBAR_GetVersion (hwnd
);
5896 case CCM_SETVERSION
:
5897 return TOOLBAR_SetVersion (hwnd
, (INT
)wParam
);
5903 return TOOLBAR_Create (hwnd
, wParam
, lParam
);
5906 return TOOLBAR_Destroy (hwnd
, wParam
, lParam
);
5909 return TOOLBAR_EraseBackground (hwnd
, wParam
, lParam
);
5912 return TOOLBAR_GetFont (hwnd
, wParam
, lParam
);
5914 /* case WM_KEYDOWN: */
5915 /* case WM_KILLFOCUS: */
5917 case WM_LBUTTONDBLCLK
:
5918 return TOOLBAR_LButtonDblClk (hwnd
, wParam
, lParam
);
5920 case WM_LBUTTONDOWN
:
5921 return TOOLBAR_LButtonDown (hwnd
, wParam
, lParam
);
5924 return TOOLBAR_LButtonUp (hwnd
, wParam
, lParam
);
5927 return TOOLBAR_MouseMove (hwnd
, wParam
, lParam
);
5930 return TOOLBAR_MouseLeave (hwnd
, wParam
, lParam
);
5932 case WM_CAPTURECHANGED
:
5933 return TOOLBAR_CaptureChanged(hwnd
);
5936 return TOOLBAR_NCActivate (hwnd
, wParam
, lParam
);
5939 return TOOLBAR_NCCalcSize (hwnd
, wParam
, lParam
);
5942 return TOOLBAR_NCCreate (hwnd
, wParam
, lParam
);
5945 return TOOLBAR_NCPaint (hwnd
, wParam
, lParam
);
5948 return TOOLBAR_Notify (hwnd
, wParam
, lParam
);
5950 case WM_NOTIFYFORMAT
:
5951 TOOLBAR_NotifyFormatFake (hwnd
, wParam
, lParam
);
5954 return TOOLBAR_Paint (hwnd
, wParam
);
5957 return TOOLBAR_SetRedraw (hwnd
, wParam
, lParam
);
5960 return TOOLBAR_Size (hwnd
, wParam
, lParam
);
5962 case WM_STYLECHANGED
:
5963 return TOOLBAR_StyleChanged (hwnd
, (INT
)wParam
, (LPSTYLESTRUCT
)lParam
);
5965 case WM_SYSCOLORCHANGE
:
5966 return TOOLBAR_SysColorChange (hwnd
);
5968 /* case WM_WININICHANGE: */
5973 case WM_MEASUREITEM
:
5976 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5978 return SendMessageA (infoPtr
->hwndNotify
, uMsg
, wParam
, lParam
);
5980 return SendMessageA (GetParent (hwnd
), uMsg
, wParam
, lParam
);
5983 /* We see this in Outlook Express 5.x and just does DefWindowProc */
5984 case PGM_FORWARDMOUSE
:
5985 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
5988 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
5989 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
5990 uMsg
, wParam
, lParam
);
5991 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
5998 TOOLBAR_Register (void)
6002 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
6003 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
6004 wndClass
.lpfnWndProc
= (WNDPROC
)ToolbarWindowProc
;
6005 wndClass
.cbClsExtra
= 0;
6006 wndClass
.cbWndExtra
= sizeof(TOOLBAR_INFO
*);
6007 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
6008 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
6009 wndClass
.lpszClassName
= TOOLBARCLASSNAMEA
;
6011 RegisterClassA (&wndClass
);
6016 TOOLBAR_Unregister (void)
6018 UnregisterClassA (TOOLBARCLASSNAMEA
, NULL
);
6021 static HIMAGELIST
TOOLBAR_InsertImageList(PIMLENTRY
**pies
, INT
*cies
, HIMAGELIST himl
, INT id
)
6026 /* Check if the entry already exists */
6027 c
= TOOLBAR_GetImageListEntry(*pies
, *cies
, id
);
6029 /* If this is a new entry we must create it and insert into the array */
6034 c
= (PIMLENTRY
) COMCTL32_Alloc(sizeof(IMLENTRY
));
6037 pnies
= COMCTL32_Alloc((*cies
+ 1) * sizeof(PIMLENTRY
));
6038 memcpy(pnies
, *pies
, ((*cies
) * sizeof(PIMLENTRY
)));
6042 COMCTL32_Free(*pies
);
6053 static VOID
TOOLBAR_DeleteImageList(PIMLENTRY
**pies
, INT
*cies
)
6057 for (i
= 0; i
< *cies
; i
++)
6058 COMCTL32_Free((*pies
)[i
]);
6060 COMCTL32_Free(*pies
);
6067 static PIMLENTRY
TOOLBAR_GetImageListEntry(PIMLENTRY
*pies
, INT cies
, INT id
)
6075 for (i
= 0; i
< cies
; i
++)
6077 if (pies
[i
]->id
== id
)
6089 static HIMAGELIST
TOOLBAR_GetImageList(PIMLENTRY
*pies
, INT cies
, INT id
)
6091 HIMAGELIST himlDef
= 0;
6092 PIMLENTRY pie
= TOOLBAR_GetImageListEntry(pies
, cies
, id
);
6095 himlDef
= pie
->himl
;
6101 static BOOL
TOOLBAR_GetButtonInfo(TOOLBAR_INFO
*infoPtr
, NMTOOLBARW
*nmtb
)
6103 if (infoPtr
->bUnicode
)
6104 return TOOLBAR_SendNotify ((NMHDR
*) nmtb
, infoPtr
, TBN_GETBUTTONINFOW
);
6111 nmtba
.iItem
= nmtb
->iItem
;
6112 nmtba
.pszText
= Buffer
;
6113 nmtba
.cchText
= 256;
6114 ZeroMemory(nmtba
.pszText
, nmtba
.cchText
);
6116 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtba
, infoPtr
, TBN_GETBUTTONINFOA
))
6118 int ccht
= strlen(nmtba
.pszText
);
6120 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)nmtba
.pszText
, -1,
6121 nmtb
->pszText
, nmtb
->cchText
);
6123 memcpy(&nmtb
->tbButton
, &nmtba
.tbButton
, sizeof(TBBUTTON
));
6132 static BOOL
TOOLBAR_IsButtonRemovable(TOOLBAR_INFO
*infoPtr
,
6133 int iItem
, PCUSTOMBUTTON btnInfo
)
6138 memcpy(&nmtb
.tbButton
, &btnInfo
->btn
, sizeof(TBBUTTON
));
6140 return TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_QUERYDELETE
);