4 * Copyright 1998,1999 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Differences between MSDN and actual native control operation:
22 * 1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
23 * to the right of the bitmap. Otherwise, this style is
24 * identical to TBSTYLE_FLAT."
25 * As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
26 * you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
27 * is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
28 * *not* imply TBSTYLE_FLAT as documented. (GA 8/2001)
32 * - Button wrapping (under construction).
40 * - TBN_DELETINGBUTTON
47 * - Tooltip support (almost complete).
48 * - Fix TOOLBAR_SetButtonInfo32A/W.
49 * - iString of -1 is undocumented
50 * - Customization dialog:
52 * - Minor buglet in 'available buttons' list:
53 * Buttons are not listed in M$-like order. M$ seems to use a single
54 * internal list to store the button information of both listboxes.
55 * - Drag list support.
58 * - Run tests using Waite Group Windows95 API Bible Volume 2.
59 * The second cdrom contains executables addstr.exe, btncount.exe,
60 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
61 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
62 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
63 * setparnt.exe, setrows.exe, toolwnd.exe.
64 * - Microsofts controlspy examples.
65 * - Charles Petzold's 'Programming Windows': gadgets.exe
75 #include "wine/unicode.h"
78 #include "imagelist.h"
80 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(toolbar
);
109 } IMLENTRY
, *PIMLENTRY
;
113 DWORD dwStructSize
; /* size of TBBUTTON struct */
114 INT nHeight
; /* height of the toolbar */
115 INT nWidth
; /* width of the toolbar */
121 INT nRows
; /* number of button rows */
122 INT nMaxTextRows
; /* maximum number of text rows */
123 INT cxMin
; /* minimum button width */
124 INT cxMax
; /* maximum button width */
125 INT nNumButtons
; /* number of buttons */
126 INT nNumBitmaps
; /* number of bitmaps */
127 INT nNumStrings
; /* number of strings */
129 BOOL bUnicode
; /* ASCII (FALSE) or Unicode (TRUE)? */
130 BOOL bCaptured
; /* mouse captured? */
133 INT nHotItem
; /* index of the "hot" item */
134 DWORD dwBaseCustDraw
; /* CDRF_ response (w/o TBCDRF_) from PREPAINT */
135 DWORD dwItemCustDraw
; /* CDRF_ response (w/o TBCDRF_) from ITEMPREP */
136 DWORD dwItemCDFlag
; /* TBCDRF_ flags from last ITEMPREPAINT */
137 SIZE szPadding
; /* padding values around button */
139 HFONT hFont
; /* text font */
140 HIMAGELIST himlInt
; /* image list created internally */
141 PIMLENTRY
*himlDef
; /* default image list array */
142 INT cimlDef
; /* default image list array count */
143 PIMLENTRY
*himlHot
; /* hot image list array */
144 INT cimlHot
; /* hot image list array count */
145 PIMLENTRY
*himlDis
; /* disabled image list array */
146 INT cimlDis
; /* disabled image list array count */
147 HWND hwndToolTip
; /* handle to tool tip control */
148 HWND hwndNotify
; /* handle to the window that gets notifications */
149 HWND hwndSelf
; /* my own handle */
150 BOOL bTransparent
; /* background transparency flag */
151 BOOL bBtnTranspnt
; /* button transparency flag */
152 BOOL bAutoSize
; /* auto size deadlock indicator */
153 BOOL bAnchor
; /* anchor highlight enabled */
154 BOOL bNtfUnicode
; /* TRUE if NOTIFYs use {W} */
155 BOOL bDoRedraw
; /* Redraw status */
156 DWORD dwExStyle
; /* extended toolbar style */
157 DWORD dwDTFlags
; /* DrawText flags */
159 COLORREF clrInsertMark
; /* insert mark color */
160 COLORREF clrBtnHighlight
; /* color for Flat Separator */
161 COLORREF clrBtnShadow
; /* color for Flag Separator */
162 RECT rcBound
; /* bounding rectangle */
165 TBUTTON_INFO
*buttons
; /* pointer to button array */
166 LPWSTR
*strings
; /* pointer to string array */
167 TBITMAP_INFO
*bitmaps
;
168 } TOOLBAR_INFO
, *PTOOLBAR_INFO
;
171 /* used by customization dialog */
174 PTOOLBAR_INFO tbInfo
;
176 } CUSTDLG_INFO
, *PCUSTDLG_INFO
;
184 } CUSTOMBUTTON
, *PCUSTOMBUTTON
;
193 #define SEPARATOR_WIDTH 8
195 #define BOTTOM_BORDER 2
196 #define DDARROW_WIDTH 11
197 #define ARROW_HEIGHT 3
199 /* gap between edge of button and image with TBSTYLE_LIST */
200 #define LIST_IMAGE_OFFSET 3
201 /* gap between bitmap and text (always present) */
202 #define LIST_TEXT_OFFSET 2
203 /* how wide to treat the bitmap if it isn't present */
204 #define LIST_IMAGE_ABSENT_WIDTH 2
206 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
207 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
208 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
210 /* Used to find undocumented extended styles */
211 #define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \
212 TBSTYLE_EX_UNDOC1 | \
213 TBSTYLE_EX_MIXEDBUTTONS | \
214 TBSTYLE_EX_HIDECLIPPEDBUTTONS)
216 #define GETIBITMAP(infoPtr, i) (infoPtr->iVersion >= 5 ? LOWORD(i) : i)
217 #define GETHIMLID(infoPtr, i) (infoPtr->iVersion >= 5 ? HIWORD(i) : 0)
218 #define GETDEFIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDef, infoPtr->cimlDef, id)
219 #define GETHOTIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlHot, infoPtr->cimlHot, id)
220 #define GETDISIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDis, infoPtr->cimlDis, id)
222 static BOOL
TOOLBAR_GetButtonInfo(TOOLBAR_INFO
*infoPtr
, NMTOOLBARW
*nmtb
);
223 static BOOL
TOOLBAR_IsButtonRemovable(TOOLBAR_INFO
*infoPtr
, int iItem
, PCUSTOMBUTTON btnInfo
);
224 static HIMAGELIST
TOOLBAR_GetImageList(PIMLENTRY
*pies
, INT cies
, INT id
);
225 static PIMLENTRY
TOOLBAR_GetImageListEntry(PIMLENTRY
*pies
, INT cies
, INT id
);
226 static VOID
TOOLBAR_DeleteImageList(PIMLENTRY
**pies
, INT
*cies
);
227 static HIMAGELIST
TOOLBAR_InsertImageList(PIMLENTRY
**pies
, INT
*cies
, HIMAGELIST himl
, INT id
);
230 TOOLBAR_NotifyFormat(TOOLBAR_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
);
234 TOOLBAR_GetText(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
)
236 LPWSTR lpText
= NULL
;
238 /* FIXME: iString == -1 is undocumented */
239 if ((HIWORD(btnPtr
->iString
) != 0) && (btnPtr
->iString
!= -1))
240 lpText
= (LPWSTR
)btnPtr
->iString
;
241 else if ((btnPtr
->iString
>= 0) && (btnPtr
->iString
< infoPtr
->nNumStrings
))
242 lpText
= infoPtr
->strings
[btnPtr
->iString
];
248 TOOLBAR_DumpButton(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*bP
, INT btn_num
, BOOL internal
)
250 if (TRACE_ON(toolbar
)){
251 TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08x\n",
252 btn_num
, bP
->idCommand
, GETIBITMAP(infoPtr
, bP
->iBitmap
),
253 bP
->fsState
, bP
->fsStyle
, bP
->dwData
, bP
->iString
);
254 TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr
,bP
)));
256 TRACE("button %d id %d, hot=%s, row=%d, rect=(%ld,%ld)-(%ld,%ld)\n",
257 btn_num
, bP
->idCommand
,
258 (bP
->bHot
) ? "TRUE":"FALSE", bP
->nRow
,
259 bP
->rect
.left
, bP
->rect
.top
,
260 bP
->rect
.right
, bP
->rect
.bottom
);
266 TOOLBAR_DumpToolbar(TOOLBAR_INFO
*iP
, INT line
)
268 if (TRACE_ON(toolbar
)) {
272 dwStyle
= GetWindowLongA (iP
->hwndSelf
, GWL_STYLE
);
273 TRACE("toolbar %p at line %d, exStyle=%08lx, buttons=%d, bitmaps=%d, strings=%d, style=%08lx\n",
275 iP
->dwExStyle
, iP
->nNumButtons
, iP
->nNumBitmaps
,
276 iP
->nNumStrings
, dwStyle
);
277 TRACE("toolbar %p at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p, redrawable=%s\n",
279 iP
->himlInt
, iP
->himlDef
, iP
->himlHot
, iP
->himlDis
,
280 (iP
->bDoRedraw
) ? "TRUE" : "FALSE");
281 for(i
=0; i
<iP
->nNumButtons
; i
++) {
282 TOOLBAR_DumpButton(iP
, &iP
->buttons
[i
], i
, TRUE
);
288 /***********************************************************************
291 * This function validates that the styles set are implemented and
292 * issues FIXME's warning of possible problems. In a perfect world this
293 * function should be null.
296 TOOLBAR_CheckStyle (HWND hwnd
, DWORD dwStyle
)
298 if (dwStyle
& TBSTYLE_ALTDRAG
)
299 FIXME("[%p] TBSTYLE_ALTDRAG not implemented\n", hwnd
);
300 if (dwStyle
& TBSTYLE_REGISTERDROP
)
301 FIXME("[%p] TBSTYLE_REGISTERDROP not implemented\n", hwnd
);
306 TOOLBAR_SendNotify (NMHDR
*nmhdr
, TOOLBAR_INFO
*infoPtr
, UINT code
)
308 if(!IsWindow(infoPtr
->hwndSelf
))
309 return 0; /* we have just been destroyed */
311 nmhdr
->idFrom
= GetDlgCtrlID (infoPtr
->hwndSelf
);
312 nmhdr
->hwndFrom
= infoPtr
->hwndSelf
;
315 TRACE("to window %p, code=%08x, %s\n", infoPtr
->hwndNotify
, code
,
316 (infoPtr
->bNtfUnicode
) ? "via Unicode" : "via ANSI");
318 if (infoPtr
->bNtfUnicode
)
319 return SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
320 (WPARAM
) nmhdr
->idFrom
, (LPARAM
)nmhdr
);
322 return SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
323 (WPARAM
) nmhdr
->idFrom
, (LPARAM
)nmhdr
);
326 /***********************************************************************
327 * TOOLBAR_GetBitmapIndex
329 * This function returns the bitmap index associated with a button.
330 * If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO
331 * is issued to retrieve the index.
334 TOOLBAR_GetBitmapIndex(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
)
336 INT ret
= btnPtr
->iBitmap
;
338 if (ret
== I_IMAGECALLBACK
) {
339 /* issue TBN_GETDISPINFO */
342 nmgd
.idCommand
= btnPtr
->idCommand
;
343 nmgd
.lParam
= btnPtr
->dwData
;
344 nmgd
.dwMask
= TBNF_IMAGE
;
345 TOOLBAR_SendNotify ((NMHDR
*) &nmgd
, infoPtr
,
346 (infoPtr
->bNtfUnicode
) ? TBN_GETDISPINFOW
:
348 if (nmgd
.dwMask
& TBNF_DI_SETITEM
) {
349 btnPtr
->iBitmap
= nmgd
.iImage
;
352 TRACE("TBN_GETDISPINFOA returned bitmap id %d, mask=%08lx, nNumBitmaps=%d\n",
353 ret
, nmgd
.dwMask
, infoPtr
->nNumBitmaps
);
356 if (ret
!= I_IMAGENONE
)
357 ret
= GETIBITMAP(infoPtr
, ret
);
364 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO
*infoPtr
, INT index
)
367 INT id
= GETHIMLID(infoPtr
, index
);
368 INT iBitmap
= GETIBITMAP(infoPtr
, index
);
370 if (((himl
= GETDEFIMAGELIST(infoPtr
, id
)) &&
371 iBitmap
>= 0 && iBitmap
< ImageList_GetImageCount(himl
)) ||
372 (index
== I_IMAGECALLBACK
))
379 /***********************************************************************
380 * TOOLBAR_DrawImageList
382 * This function validates the bitmap index (including I_IMAGECALLBACK
383 * functionality). It then draws the image via the ImageList_Draw
384 * function. It returns TRUE if the image was drawn, FALSE otherwise.
387 TOOLBAR_DrawImageList (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
, IMAGE_LIST_TYPE imagelist
,
388 HDC hdc
, UINT left
, UINT top
, UINT draw_flags
)
393 if (!TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
394 if (btnPtr
->iBitmap
== I_IMAGENONE
) return FALSE
;
395 ERR("index %d is not valid, max %d\n",
396 btnPtr
->iBitmap
, infoPtr
->nNumBitmaps
);
400 if ((index
= TOOLBAR_GetBitmapIndex(infoPtr
, btnPtr
)) < 0) {
401 if ((index
== I_IMAGECALLBACK
) ||
402 (index
== I_IMAGENONE
)) return FALSE
;
403 ERR("TBN_GETDISPINFO returned invalid index %d\n",
410 case IMAGE_LIST_DEFAULT
:
411 himl
= GETDEFIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
414 himl
= GETHOTIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
416 case IMAGE_LIST_DISABLED
:
417 himl
= GETDISIMAGELIST(infoPtr
, GETHIMLID(infoPtr
, btnPtr
->iBitmap
));
421 FIXME("Shouldn't reach here\n");
426 TRACE("no image list, returning FALSE\n");
430 TRACE("drawing index=%d, himl=%p, left=%d, top=%d, flags=%08x\n",
431 index
, himl
, left
, top
, draw_flags
);
433 ImageList_Draw (himl
, index
, hdc
, left
, top
, draw_flags
);
438 /***********************************************************************
439 * TOOLBAR_TestImageExist
441 * This function is similar to TOOLBAR_DrawImageList, except it does not
442 * draw the image. The I_IMAGECALLBACK functionality is implemented.
445 TOOLBAR_TestImageExist (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
, HIMAGELIST himl
)
449 if (!himl
) return FALSE
;
451 if (!TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
452 if (btnPtr
->iBitmap
== I_IMAGENONE
) return FALSE
;
453 ERR("index %d is not valid, max %d\n",
454 btnPtr
->iBitmap
, infoPtr
->nNumBitmaps
);
458 if ((index
= TOOLBAR_GetBitmapIndex(infoPtr
, btnPtr
)) < 0) {
459 if ((index
== I_IMAGECALLBACK
) ||
460 (index
== I_IMAGENONE
)) return FALSE
;
461 ERR("TBN_GETDISPINFO returned invalid index %d\n",
470 TOOLBAR_DrawFlatSeparator (LPRECT lpRect
, HDC hdc
, TOOLBAR_INFO
*infoPtr
)
473 COLORREF oldcolor
, newcolor
;
475 myrect
.left
= (lpRect
->left
+ lpRect
->right
) / 2 - 1;
476 myrect
.right
= myrect
.left
+ 1;
477 myrect
.top
= lpRect
->top
+ 2;
478 myrect
.bottom
= lpRect
->bottom
- 2;
480 newcolor
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
481 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
482 oldcolor
= SetBkColor (hdc
, newcolor
);
483 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
485 myrect
.left
= myrect
.right
;
486 myrect
.right
= myrect
.left
+ 1;
488 newcolor
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
489 comctl32_color
.clrBtnHighlight
: infoPtr
->clrBtnHighlight
;
490 SetBkColor (hdc
, newcolor
);
491 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
493 SetBkColor (hdc
, oldcolor
);
497 /***********************************************************************
498 * TOOLBAR_DrawDDFlatSeparator
500 * This function draws the separator that was flaged as BTNS_DROPDOWN.
501 * In this case, the separator is a pixel high line of COLOR_BTNSHADOW,
502 * followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators
503 * are horizontal as opposed to the vertical separators for not dropdown
506 * FIXME: It is possible that the height of each line is really SM_CYBORDER.
509 TOOLBAR_DrawDDFlatSeparator (LPRECT lpRect
, HDC hdc
, TBUTTON_INFO
*btnPtr
, TOOLBAR_INFO
*infoPtr
)
512 COLORREF oldcolor
, newcolor
;
514 myrect
.left
= lpRect
->left
;
515 myrect
.right
= lpRect
->right
;
516 myrect
.top
= lpRect
->top
+ (lpRect
->bottom
- lpRect
->top
- 2)/2;
517 myrect
.bottom
= myrect
.top
+ 1;
519 InflateRect (&myrect
, -2, 0);
521 TRACE("rect=(%ld,%ld)-(%ld,%ld)\n",
522 myrect
.left
, myrect
.top
, myrect
.right
, myrect
.bottom
);
524 newcolor
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
525 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
526 oldcolor
= SetBkColor (hdc
, newcolor
);
527 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
529 myrect
.top
= myrect
.bottom
;
530 myrect
.bottom
= myrect
.top
+ 1;
532 newcolor
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
533 comctl32_color
.clrBtnHighlight
: infoPtr
->clrBtnHighlight
;
534 SetBkColor (hdc
, newcolor
);
535 ExtTextOutA (hdc
, 0, 0, ETO_OPAQUE
, &myrect
, 0, 0, 0);
537 SetBkColor (hdc
, oldcolor
);
542 TOOLBAR_DrawArrow (HDC hdc
, INT left
, INT top
, INT colorRef
)
547 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
548 hOldPen
= SelectObject ( hdc
, hPen
);
551 MoveToEx (hdc
, x
, y
, NULL
);
552 LineTo (hdc
, x
+5, y
++); x
++;
553 MoveToEx (hdc
, x
, y
, NULL
);
554 LineTo (hdc
, x
+3, y
++); x
++;
555 MoveToEx (hdc
, x
, y
, NULL
);
556 LineTo (hdc
, x
+1, y
++);
557 SelectObject( hdc
, hOldPen
);
558 DeleteObject( hPen
);
562 * Draw the text string for this button.
563 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
564 * is non-zero, so we can simply check himlDef to see if we have
568 TOOLBAR_DrawString (TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
569 HDC hdc
, DWORD dwStyle
,
570 RECT
*rcText
, LPWSTR lpText
, NMTBCUSTOMDRAW
*tbcd
)
574 UINT state
= tbcd
->nmcd
.uItemState
;
578 TRACE("string=%s rect=(%ld,%ld)-(%ld,%ld)\n", debugstr_w(lpText
),
579 rcText
->left
, rcText
->top
, rcText
->right
, rcText
->bottom
);
581 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
582 if ((state
& CDIS_HOT
) && (infoPtr
->dwItemCDFlag
& TBCDRF_HILITEHOTTRACK
)) {
583 clrOld
= SetTextColor (hdc
, tbcd
->clrTextHighlight
);
585 else if (state
& CDIS_DISABLED
) {
586 clrOld
= SetTextColor (hdc
, tbcd
->clrBtnHighlight
);
587 OffsetRect (rcText
, 1, 1);
588 DrawTextW (hdc
, lpText
, -1, rcText
, infoPtr
->dwDTFlags
);
589 SetTextColor (hdc
, comctl32_color
.clr3dShadow
);
590 OffsetRect (rcText
, -1, -1);
592 else if (state
& CDIS_INDETERMINATE
) {
593 clrOld
= SetTextColor (hdc
, comctl32_color
.clr3dShadow
);
596 clrOld
= SetTextColor (hdc
, tbcd
->clrText
);
599 DrawTextW (hdc
, lpText
, -1, rcText
, infoPtr
->dwDTFlags
);
600 SetTextColor (hdc
, clrOld
);
601 SelectObject (hdc
, hOldFont
);
607 TOOLBAR_DrawPattern (HDC hdc
, LPRECT lpRect
)
609 HBRUSH hbr
= SelectObject (hdc
, COMCTL32_hPattern55AABrush
);
610 INT cx
= lpRect
->right
- lpRect
->left
;
611 INT cy
= lpRect
->bottom
- lpRect
->top
;
612 PatBlt (hdc
, lpRect
->left
, lpRect
->top
, cx
, cy
, 0x00FA0089);
613 SelectObject (hdc
, hbr
);
617 static void TOOLBAR_DrawMasked(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
618 HDC hdc
, INT x
, INT y
)
620 HIMAGELIST himl
= GETDEFIMAGELIST(infoPtr
, 0);
625 HBITMAP hbmMask
, hbmImage
;
626 HDC hdcMask
, hdcImage
;
628 ImageList_GetIconSize(himl
, &cx
, &cy
);
630 /* Create src image */
631 hdcImage
= CreateCompatibleDC(hdc
);
632 hbmImage
= CreateBitmap(cx
, cy
, GetDeviceCaps(hdc
,PLANES
),
633 GetDeviceCaps(hdc
,BITSPIXEL
), NULL
);
634 SelectObject(hdcImage
, hbmImage
);
635 ImageList_DrawEx(himl
, btnPtr
->iBitmap
, hdcImage
, 0, 0, cx
, cy
,
636 RGB(0xff, 0xff, 0xff), RGB(0,0,0), ILD_NORMAL
);
639 hdcMask
= CreateCompatibleDC(0);
640 hbmMask
= CreateBitmap(cx
, cy
, 1, 1, NULL
);
641 SelectObject(hdcMask
, hbmMask
);
643 /* Remove the background and all white pixels */
644 SetBkColor(hdcImage
, ImageList_GetBkColor(himl
));
645 BitBlt(hdcMask
, 0, 0, cx
, cy
, hdcImage
, 0, 0, SRCCOPY
);
646 SetBkColor(hdcImage
, RGB(0xff, 0xff, 0xff));
647 BitBlt(hdcMask
, 0, 0, cx
, cy
, hdcImage
, 0, 0, NOTSRCERASE
);
649 /* draw the new mask 'etched' to hdc */
650 SetBkColor(hdc
, RGB(255, 255, 255));
651 SelectObject(hdc
, GetSysColorBrush(COLOR_3DHILIGHT
));
652 BitBlt(hdc
, x
+ 1, y
+ 1, cx
, cy
, hdcMask
, 0, 0, 0xE20746);
653 SelectObject(hdc
, GetSysColorBrush(COLOR_3DSHADOW
));
654 BitBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, 0, 0, 0xE20746);
657 DeleteObject(hbmImage
);
659 DeleteObject (hbmMask
);
666 TOOLBAR_TranslateState(TBUTTON_INFO
*btnPtr
)
670 retstate
|= (btnPtr
->fsState
& TBSTATE_CHECKED
) ? CDIS_CHECKED
: 0;
671 retstate
|= (btnPtr
->fsState
& TBSTATE_PRESSED
) ? CDIS_SELECTED
: 0;
672 retstate
|= (btnPtr
->fsState
& TBSTATE_ENABLED
) ? 0 : CDIS_DISABLED
;
673 retstate
|= (btnPtr
->fsState
& TBSTATE_MARKED
) ? CDIS_MARKED
: 0;
674 retstate
|= (btnPtr
->bHot
) ? CDIS_HOT
: 0;
675 retstate
|= (btnPtr
->fsState
& TBSTATE_INDETERMINATE
) ? CDIS_INDETERMINATE
: 0;
676 /* FIXME: don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT */
677 /* don't test TBSTATE_HIDDEN */
683 TOOLBAR_DrawButton (HWND hwnd
, TBUTTON_INFO
*btnPtr
, HDC hdc
)
685 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
686 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
687 BOOL hasDropDownArrow
= TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
) &&
688 (btnPtr
->fsStyle
& BTNS_DROPDOWN
);
689 RECT rc
, rcArrow
, rcBitmap
, rcText
, rcFill
;
690 LPWSTR lpText
= NULL
;
695 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
699 CopyRect (&rcFill
, &rc
);
700 CopyRect (&rcArrow
, &rc
);
701 CopyRect(&rcBitmap
, &rc
);
703 /* get a pointer to the text */
704 lpText
= TOOLBAR_GetText(infoPtr
, btnPtr
);
706 if (hasDropDownArrow
)
708 if (dwStyle
& TBSTYLE_FLAT
)
709 rc
.right
= max(rc
.left
, rc
.right
- DDARROW_WIDTH
);
711 rc
.right
= max(rc
.left
, rc
.right
- DDARROW_WIDTH
- 2);
712 rcArrow
.left
= rc
.right
;
715 /* copy text rect after adjusting for drop-down arrow
716 * so that text is centred in the rectangle not containing
718 CopyRect(&rcText
, &rc
);
720 /* Center the bitmap horizontally and vertically */
721 if (dwStyle
& TBSTYLE_LIST
)
722 rcBitmap
.left
+= LIST_IMAGE_OFFSET
;
724 rcBitmap
.left
+=(infoPtr
->nButtonWidth
- infoPtr
->nBitmapWidth
) / 2;
727 rcBitmap
.top
+=2; /* this looks to be the correct value from vmware comparison - cmm */
729 rcBitmap
.top
+=(infoPtr
->nButtonHeight
- infoPtr
->nBitmapHeight
) / 2;
731 TRACE("iBitmap: %d, start=(%ld,%ld) w=%d, h=%d\n",
732 btnPtr
->iBitmap
, rcBitmap
.left
, rcBitmap
.top
,
733 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
734 TRACE ("iString: %x\n", btnPtr
->iString
);
735 TRACE ("Stringtext: %s\n", debugstr_w(lpText
));
740 InflateRect (&rcText
, -3, -3);
742 if (GETDEFIMAGELIST(infoPtr
, 0) &&
743 TOOLBAR_IsValidBitmapIndex(infoPtr
,btnPtr
->iBitmap
)) {
744 /* The following test looked like this before
745 * I changed it. IE4 "Links" toolbar would not
746 * draw correctly with the original code. - GA 8/01
747 * ((dwStyle & TBSTYLE_LIST) &&
748 * ((btnPtr->fsStyle & BTNS_AUTOSIZE) == 0) &&
749 * (btnPtr->iBitmap != I_IMAGENONE))
751 if (dwStyle
& TBSTYLE_LIST
) {
752 /* LIST style w/ ICON offset is by matching native. */
753 /* Matches IE4 "Links" bar. - GA 8/01 */
754 rcText
.left
+= (infoPtr
->nBitmapWidth
+ LIST_TEXT_OFFSET
);
757 rcText
.top
+= infoPtr
->nBitmapHeight
+ 1;
761 if (dwStyle
& TBSTYLE_LIST
) {
762 /* LIST style w/o ICON offset is by matching native. */
763 /* Matches IE4 "menu" bar. - GA 8/01 */
764 rcText
.left
+= LIST_IMAGE_ABSENT_WIDTH
+ LIST_TEXT_OFFSET
;
768 if (btnPtr
->fsState
& (TBSTATE_PRESSED
| TBSTATE_CHECKED
))
769 OffsetRect (&rcText
, 1, 1);
772 /* Initialize fields in all cases, because we use these later */
773 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
774 tbcd
.clrText
= comctl32_color
.clrBtnText
;
775 tbcd
.clrTextHighlight
= comctl32_color
.clrHighlightText
;
776 tbcd
.clrBtnFace
= comctl32_color
.clrBtnFace
;
777 tbcd
.clrBtnHighlight
= comctl32_color
.clrBtnHighlight
;
778 tbcd
.clrMark
= comctl32_color
.clrHighlight
;
779 tbcd
.clrHighlightHotTrack
= 0;
780 tbcd
.nStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
781 tbcd
.nHLStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
782 /* MSDN says that this is the text rectangle. */
783 /* But (why always a but) tracing of v5.7 of native shows */
784 /* that this is really a *relative* rectangle based on the */
785 /* the nmcd.rc. Also the left and top are always 0 ignoring*/
786 /* any bitmap that might be present. */
787 tbcd
.rcText
.left
= 0;
789 tbcd
.rcText
.right
= rcText
.right
- rc
.left
;
790 tbcd
.rcText
.bottom
= rcText
.bottom
- rc
.top
;
791 /* we use this state later on to decide how to draw the buttons */
792 /* NOTE: applications can and do alter this to customize their */
794 tbcd
.nmcd
.uItemState
= TOOLBAR_TranslateState(btnPtr
);
796 /* FIXME: what should these be set to ????? */
797 tbcd
.hbrMonoDither
= 0;
801 /* Issue Item Prepaint notify */
802 infoPtr
->dwItemCustDraw
= 0;
803 infoPtr
->dwItemCDFlag
= 0;
804 if (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYITEMDRAW
)
806 tbcd
.nmcd
.dwDrawStage
= CDDS_ITEMPREPAINT
;
809 tbcd
.nmcd
.dwItemSpec
= btnPtr
->idCommand
;
810 tbcd
.nmcd
.lItemlParam
= btnPtr
->dwData
;
811 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
812 infoPtr
->dwItemCustDraw
= ntfret
& 0xffff;
813 infoPtr
->dwItemCDFlag
= ntfret
& 0xffff0000;
814 if (infoPtr
->dwItemCustDraw
& CDRF_SKIPDEFAULT
)
816 /* save the only part of the rect that the user can change */
817 rcText
.right
= tbcd
.rcText
.right
+ rc
.left
;
818 rcText
.bottom
= tbcd
.rcText
.bottom
+ rc
.top
;
821 if (!infoPtr
->bBtnTranspnt
)
822 FillRect( hdc
, &rcFill
, GetSysColorBrush(COLOR_BTNFACE
));
825 if (btnPtr
->fsStyle
& BTNS_SEP
) {
826 /* with the FLAT style, iBitmap is the width and has already */
827 /* been taken into consideration in calculating the width */
828 /* so now we need to draw the vertical separator */
829 /* empirical tests show that iBitmap can/will be non-zero */
830 /* when drawing the vertical bar... */
831 if ((dwStyle
& TBSTYLE_FLAT
) /* && (btnPtr->iBitmap == 0) */) {
832 if (btnPtr
->fsStyle
& BTNS_DROPDOWN
)
833 TOOLBAR_DrawDDFlatSeparator (&rc
, hdc
, btnPtr
, infoPtr
);
835 TOOLBAR_DrawFlatSeparator (&rc
, hdc
, infoPtr
);
837 else if (btnPtr
->fsStyle
!= BTNS_SEP
) {
838 FIXME("Draw some kind of separator: fsStyle=%x\n",
844 if ((dwStyle
& TBSTYLE_FLAT
) && (tbcd
.nmcd
.uItemState
& CDIS_HOT
))
846 if ( infoPtr
->dwItemCDFlag
& TBCDRF_HILITEHOTTRACK
)
850 oldclr
= SetBkColor(hdc
, tbcd
.clrHighlightHotTrack
);
851 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, 0);
852 if (hasDropDownArrow
)
853 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rcArrow
, NULL
, 0, 0);
854 SetBkColor(hdc
, oldclr
);
858 if (!(tbcd
.nmcd
.uItemState
& CDIS_DISABLED
) && !(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
860 DrawEdge (hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
861 if (hasDropDownArrow
)
862 DrawEdge (hdc
, &rcArrow
, BDR_RAISEDINNER
, BF_RECT
);
868 if (tbcd
.nmcd
.uItemState
& CDIS_DISABLED
) {
869 if (!(dwStyle
& TBSTYLE_FLAT
) && !(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
871 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
872 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
873 if (hasDropDownArrow
)
874 DrawEdge (hdc
, &rcArrow
, EDGE_RAISED
,
875 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
878 if (hasDropDownArrow
)
880 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
+1, rcArrow
.top
+1 + (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_3DHIGHLIGHT
);
881 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_3DSHADOW
);
884 if (!TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DISABLED
,
885 hdc
, rcBitmap
.left
, rcBitmap
.top
,
887 TOOLBAR_DrawMasked (infoPtr
, btnPtr
, hdc
, rcBitmap
.left
, rcBitmap
.top
);
889 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
890 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
894 /* pressed BTNS_BUTTON */
895 if (tbcd
.nmcd
.uItemState
& CDIS_SELECTED
) {
896 offset
= (infoPtr
->dwItemCDFlag
& TBCDRF_NOOFFSET
) ? 0 : 1;
897 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
899 if (dwStyle
& TBSTYLE_FLAT
)
901 DrawEdge (hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
902 if (hasDropDownArrow
)
903 DrawEdge (hdc
, &rcArrow
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
907 DrawEdge (hdc
, &rc
, EDGE_SUNKEN
, BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
908 if (hasDropDownArrow
)
909 DrawEdge (hdc
, &rcArrow
, EDGE_SUNKEN
, BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
913 if (hasDropDownArrow
)
914 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
+ offset
, rcArrow
.top
+ offset
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_WINDOWFRAME
);
916 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
917 hdc
, rcBitmap
.left
+offset
, rcBitmap
.top
+offset
,
920 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
921 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
925 /* checked BTNS_CHECK */
926 if ((tbcd
.nmcd
.uItemState
& CDIS_CHECKED
) &&
927 (btnPtr
->fsStyle
& BTNS_CHECK
)) {
928 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
930 if (dwStyle
& TBSTYLE_FLAT
)
931 DrawEdge (hdc
, &rc
, BDR_SUNKENOUTER
,
932 BF_RECT
| BF_ADJUST
);
934 DrawEdge (hdc
, &rc
, EDGE_SUNKEN
,
935 BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
938 TOOLBAR_DrawPattern (hdc
, &rc
);
940 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
941 hdc
, rcBitmap
.left
+1, rcBitmap
.top
+1,
944 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
945 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
950 if (tbcd
.nmcd
.uItemState
& CDIS_INDETERMINATE
) {
951 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
952 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
953 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
955 TOOLBAR_DrawPattern (hdc
, &rc
);
956 TOOLBAR_DrawMasked (infoPtr
, btnPtr
, hdc
, rcBitmap
.left
, rcBitmap
.top
);
957 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
958 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
963 if (dwStyle
& TBSTYLE_FLAT
)
965 if (hasDropDownArrow
)
966 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_WINDOWFRAME
);
968 if (tbcd
.nmcd
.uItemState
& CDIS_HOT
) {
969 /* if hot, attempt to draw with hot image list, if fails,
970 use default image list */
971 if (!TOOLBAR_DrawImageList (infoPtr
, btnPtr
,
974 rcBitmap
.top
, ILD_NORMAL
))
975 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
976 hdc
, rcBitmap
.left
, rcBitmap
.top
,
980 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
981 hdc
, rcBitmap
.left
, rcBitmap
.top
,
986 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
987 DrawEdge (hdc
, &rc
, EDGE_RAISED
,
988 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
990 if (hasDropDownArrow
)
992 if (!(infoPtr
->dwItemCDFlag
& TBCDRF_NOEDGES
))
993 DrawEdge (hdc
, &rcArrow
, EDGE_RAISED
,
994 BF_SOFT
| BF_RECT
| BF_MIDDLE
| BF_ADJUST
);
995 TOOLBAR_DrawArrow(hdc
, rcArrow
.left
, rcArrow
.top
+ (rcArrow
.bottom
- rcArrow
.top
- ARROW_HEIGHT
) / 2, COLOR_WINDOWFRAME
);
998 TOOLBAR_DrawImageList (infoPtr
, btnPtr
, IMAGE_LIST_DEFAULT
,
999 hdc
, rcBitmap
.left
, rcBitmap
.top
,
1004 if (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) || (btnPtr
->fsStyle
& BTNS_SHOWTEXT
))
1005 TOOLBAR_DrawString (infoPtr
, btnPtr
, hdc
, dwStyle
, &rcText
, lpText
, &tbcd
);
1008 if (infoPtr
->dwItemCustDraw
& CDRF_NOTIFYPOSTPAINT
)
1010 tbcd
.nmcd
.dwDrawStage
= CDDS_ITEMPOSTPAINT
;
1011 tbcd
.nmcd
.hdc
= hdc
;
1013 tbcd
.nmcd
.dwItemSpec
= btnPtr
->idCommand
;
1014 tbcd
.nmcd
.uItemState
= TOOLBAR_TranslateState(btnPtr
);
1015 tbcd
.nmcd
.lItemlParam
= btnPtr
->dwData
;
1016 tbcd
.rcText
= rcText
;
1017 tbcd
.nStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
1018 tbcd
.nHLStringBkMode
= (infoPtr
->bBtnTranspnt
) ? TRANSPARENT
: OPAQUE
;
1019 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1026 TOOLBAR_Refresh (HWND hwnd
, HDC hdc
, PAINTSTRUCT
* ps
)
1028 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1029 TBUTTON_INFO
*btnPtr
;
1030 INT i
, oldBKmode
= 0;
1031 RECT rcTemp
, rcClient
;
1032 NMTBCUSTOMDRAW tbcd
;
1035 /* if imagelist belongs to the app, it can be changed
1036 by the app after setting it */
1037 if (GETDEFIMAGELIST(infoPtr
, 0) != infoPtr
->himlInt
)
1039 infoPtr
->nNumBitmaps
= 0;
1040 for (i
= 0; i
< infoPtr
->cimlDef
; i
++)
1041 infoPtr
->nNumBitmaps
+= ImageList_GetImageCount(infoPtr
->himlDef
[i
]->himl
);
1044 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
1046 /* Send initial notify */
1047 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
1048 tbcd
.nmcd
.dwDrawStage
= CDDS_PREPAINT
;
1049 tbcd
.nmcd
.hdc
= hdc
;
1050 tbcd
.nmcd
.rc
= ps
->rcPaint
;
1051 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1052 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
1054 if (infoPtr
->bBtnTranspnt
)
1055 oldBKmode
= SetBkMode (hdc
, TRANSPARENT
);
1057 GetClientRect(hwnd
, &rcClient
);
1059 /* redraw necessary buttons */
1060 btnPtr
= infoPtr
->buttons
;
1061 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++)
1064 if (infoPtr
->dwExStyle
& TBSTYLE_EX_HIDECLIPPEDBUTTONS
)
1066 IntersectRect(&rcTemp
, &rcClient
, &btnPtr
->rect
);
1067 bDraw
= EqualRect(&rcTemp
, &btnPtr
->rect
);
1071 bDraw
&= IntersectRect(&rcTemp
, &(ps
->rcPaint
), &(btnPtr
->rect
));
1073 TOOLBAR_DrawButton (hwnd
, btnPtr
, hdc
);
1076 if (infoPtr
->bBtnTranspnt
&& (oldBKmode
!= TRANSPARENT
))
1077 SetBkMode (hdc
, oldBKmode
);
1079 if (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYPOSTPAINT
)
1081 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
1082 tbcd
.nmcd
.dwDrawStage
= CDDS_POSTPAINT
;
1083 tbcd
.nmcd
.hdc
= hdc
;
1084 tbcd
.nmcd
.rc
= ps
->rcPaint
;
1085 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
1089 /***********************************************************************
1090 * TOOLBAR_MeasureString
1092 * This function gets the width and height of a string in pixels. This
1093 * is done first by using GetTextExtentPoint to get the basic width
1094 * and height. The DrawText is called with DT_CALCRECT to get the exact
1095 * width. The reason is because the text may have more than one "&" (or
1096 * prefix characters as M$ likes to call them). The prefix character
1097 * indicates where the underline goes, except for the string "&&" which
1098 * is reduced to a single "&". GetTextExtentPoint does not process these
1099 * only DrawText does. Note that the BTNS_NOPREFIX is handled here.
1102 TOOLBAR_MeasureString(TOOLBAR_INFO
*infoPtr
, TBUTTON_INFO
*btnPtr
,
1103 HDC hdc
, LPSIZE lpSize
)
1110 if (!(btnPtr
->fsState
& TBSTATE_HIDDEN
) &&
1111 (!(infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) ||
1112 (btnPtr
->fsStyle
& BTNS_SHOWTEXT
)) )
1114 LPWSTR lpText
= TOOLBAR_GetText(infoPtr
, btnPtr
);
1116 if(lpText
!= NULL
) {
1117 /* first get size of all the text */
1118 GetTextExtentPoint32W (hdc
, lpText
, strlenW (lpText
), lpSize
);
1120 /* feed above size into the rectangle for DrawText */
1121 myrect
.left
= myrect
.top
= 0;
1122 myrect
.right
= lpSize
->cx
;
1123 myrect
.bottom
= lpSize
->cy
;
1125 /* Use DrawText to get true size as drawn (less pesky "&") */
1126 DrawTextW (hdc
, lpText
, -1, &myrect
, DT_VCENTER
| DT_SINGLELINE
|
1127 DT_CALCRECT
| ((btnPtr
->fsStyle
& BTNS_NOPREFIX
) ?
1130 /* feed back to caller */
1131 lpSize
->cx
= myrect
.right
;
1132 lpSize
->cy
= myrect
.bottom
;
1136 TRACE("string size %ld x %ld!\n", lpSize
->cx
, lpSize
->cy
);
1139 /***********************************************************************
1140 * TOOLBAR_CalcStrings
1142 * This function walks through each string and measures it and returns
1143 * the largest height and width to caller.
1146 TOOLBAR_CalcStrings (HWND hwnd
, LPSIZE lpSize
)
1148 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1149 TBUTTON_INFO
*btnPtr
;
1159 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
1161 btnPtr
= infoPtr
->buttons
;
1162 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1163 if(TOOLBAR_HasText(infoPtr
, btnPtr
))
1165 TOOLBAR_MeasureString(infoPtr
, btnPtr
, hdc
, &sz
);
1166 if (sz
.cx
> lpSize
->cx
)
1168 if (sz
.cy
> lpSize
->cy
)
1173 SelectObject (hdc
, hOldFont
);
1174 ReleaseDC (hwnd
, hdc
);
1176 TRACE("max string size %ld x %ld!\n", lpSize
->cx
, lpSize
->cy
);
1179 /***********************************************************************
1180 * TOOLBAR_WrapToolbar
1182 * This function walks through the buttons and separators in the
1183 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
1184 * wrapping should occur based on the width of the toolbar window.
1185 * It does *not* calculate button placement itself. That task
1186 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
1187 * the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE
1188 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
1190 * Note: TBSTYLE_WRAPABLE or TBSTYLE_EX_UNDOC1 can be used also to allow
1191 * vertical toolbar lists.
1195 TOOLBAR_WrapToolbar( HWND hwnd
, DWORD dwStyle
)
1197 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1198 TBUTTON_INFO
*btnPtr
;
1201 BOOL bWrap
, bButtonWrap
;
1203 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
1204 /* no layout is necessary. Applications may use this style */
1205 /* to perform their own layout on the toolbar. */
1206 if( !(dwStyle
& TBSTYLE_WRAPABLE
) &&
1207 !(infoPtr
->dwExStyle
& TBSTYLE_EX_UNDOC1
) ) return;
1209 btnPtr
= infoPtr
->buttons
;
1210 x
= infoPtr
->nIndent
;
1212 /* this can get the parents width, to know how far we can extend
1213 * this toolbar. We cannot use its height, as there may be multiple
1214 * toolbars in a rebar control
1216 GetClientRect( GetParent(hwnd
), &rc
);
1217 infoPtr
->nWidth
= rc
.right
- rc
.left
;
1218 bButtonWrap
= FALSE
;
1220 TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
1221 infoPtr
->nButtonWidth
, infoPtr
->nBitmapWidth
, infoPtr
->nWidth
,
1224 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++ )
1227 btnPtr
[i
].fsState
&= ~TBSTATE_WRAP
;
1229 if (btnPtr
[i
].fsState
& TBSTATE_HIDDEN
)
1232 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1233 /* it is the actual width of the separator. This is used for */
1234 /* custom controls in toolbars. */
1236 /* BTNS_DROPDOWN separators are treated as buttons for */
1237 /* width. - GA 8/01 */
1238 if ((btnPtr
[i
].fsStyle
& BTNS_SEP
) &&
1239 !(btnPtr
[i
].fsStyle
& BTNS_DROPDOWN
))
1240 cx
= (btnPtr
[i
].iBitmap
> 0) ?
1241 btnPtr
[i
].iBitmap
: SEPARATOR_WIDTH
;
1243 cx
= infoPtr
->nButtonWidth
;
1245 /* Two or more adjacent separators form a separator group. */
1246 /* The first separator in a group should be wrapped to the */
1247 /* next row if the previous wrapping is on a button. */
1249 (btnPtr
[i
].fsStyle
& BTNS_SEP
) &&
1250 (i
+ 1 < infoPtr
->nNumButtons
) &&
1251 (btnPtr
[i
+ 1].fsStyle
& BTNS_SEP
) )
1253 TRACE("wrap point 1 btn %d style %02x\n", i
, btnPtr
[i
].fsStyle
);
1254 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1255 x
= infoPtr
->nIndent
;
1257 bButtonWrap
= FALSE
;
1261 /* The layout makes sure the bitmap is visible, but not the button. */
1262 /* Test added to also wrap after a button that starts a row but */
1263 /* is bigger than the area. - GA 8/01 */
1264 if (( x
+ cx
- (infoPtr
->nButtonWidth
- infoPtr
->nBitmapWidth
) / 2
1265 > infoPtr
->nWidth
) ||
1266 ((x
== infoPtr
->nIndent
) && (cx
> infoPtr
->nWidth
)))
1268 BOOL bFound
= FALSE
;
1270 /* If the current button is a separator and not hidden, */
1271 /* go to the next until it reaches a non separator. */
1272 /* Wrap the last separator if it is before a button. */
1273 while( ( ((btnPtr
[i
].fsStyle
& BTNS_SEP
) &&
1274 !(btnPtr
[i
].fsStyle
& BTNS_DROPDOWN
)) ||
1275 (btnPtr
[i
].fsState
& TBSTATE_HIDDEN
) ) &&
1276 i
< infoPtr
->nNumButtons
)
1282 if( bFound
&& i
< infoPtr
->nNumButtons
)
1285 TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
1286 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1287 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1288 x
= infoPtr
->nIndent
;
1289 bButtonWrap
= FALSE
;
1292 else if ( i
>= infoPtr
->nNumButtons
)
1295 /* If the current button is not a separator, find the last */
1296 /* separator and wrap it. */
1297 for ( j
= i
- 1; j
>= 0 && !(btnPtr
[j
].fsState
& TBSTATE_WRAP
); j
--)
1299 if ((btnPtr
[j
].fsStyle
& BTNS_SEP
) &&
1300 !(btnPtr
[j
].fsState
& TBSTATE_HIDDEN
))
1304 TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
1305 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1306 x
= infoPtr
->nIndent
;
1307 btnPtr
[j
].fsState
|= TBSTATE_WRAP
;
1308 bButtonWrap
= FALSE
;
1313 /* If no separator available for wrapping, wrap one of */
1314 /* non-hidden previous button. */
1318 j
>= 0 && !(btnPtr
[j
].fsState
& TBSTATE_WRAP
); j
--)
1320 if (btnPtr
[j
].fsState
& TBSTATE_HIDDEN
)
1325 TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
1326 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1327 x
= infoPtr
->nIndent
;
1328 btnPtr
[j
].fsState
|= TBSTATE_WRAP
;
1334 /* If all above failed, wrap the current button. */
1337 TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
1338 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1339 btnPtr
[i
].fsState
|= TBSTATE_WRAP
;
1341 x
= infoPtr
->nIndent
;
1342 if (btnPtr
[i
].fsStyle
& BTNS_SEP
)
1343 bButtonWrap
= FALSE
;
1349 TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
1350 i
, btnPtr
[i
].fsStyle
, x
, cx
);
1357 /***********************************************************************
1358 * TOOLBAR_CalcToolbar
1360 * This function calculates button and separator placement. It first
1361 * calculates the button sizes, gets the toolbar window width and then
1362 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
1363 * on. It assigns a new location to each item and sends this location to
1364 * the tooltip window if appropriate. Finally, it updates the rcBound
1365 * rect and calculates the new required toolbar window height.
1369 TOOLBAR_CalcToolbar (HWND hwnd
)
1371 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
1372 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1373 TBUTTON_INFO
*btnPtr
;
1374 INT i
, nRows
, nSepRows
;
1378 BOOL usesBitmaps
= FALSE
;
1379 BOOL hasDropDownArrows
= TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
);
1381 TOOLBAR_CalcStrings (hwnd
, &sizeString
);
1383 for (i
= 0; i
< infoPtr
->nNumButtons
&& !usesBitmaps
; i
++)
1385 if (TOOLBAR_IsValidBitmapIndex(infoPtr
,infoPtr
->buttons
[i
].iBitmap
))
1388 if (dwStyle
& TBSTYLE_LIST
)
1390 infoPtr
->nButtonHeight
= max((usesBitmaps
) ? infoPtr
->nBitmapHeight
:
1391 0, sizeString
.cy
) + infoPtr
->szPadding
.cy
;
1392 infoPtr
->nButtonWidth
= ((usesBitmaps
) ? infoPtr
->nBitmapWidth
:
1393 0) + sizeString
.cx
+ 6;
1394 TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n",
1395 infoPtr
->nButtonWidth
, infoPtr
->nButtonHeight
, usesBitmaps
,
1396 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
1397 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
1400 if (sizeString
.cy
> 0)
1403 infoPtr
->nButtonHeight
= sizeString
.cy
+
1404 2 + /* this is the space to separate text from bitmap */
1405 infoPtr
->nBitmapHeight
+ 6;
1407 infoPtr
->nButtonHeight
= sizeString
.cy
+ 6;
1409 else if (infoPtr
->nButtonHeight
< infoPtr
->nBitmapHeight
+ 6)
1410 infoPtr
->nButtonHeight
= infoPtr
->nBitmapHeight
+ 6;
1412 if (sizeString
.cx
> infoPtr
->nBitmapWidth
)
1413 infoPtr
->nButtonWidth
= sizeString
.cx
+ 6;
1414 else if (infoPtr
->nButtonWidth
< infoPtr
->nBitmapWidth
+ 6)
1415 infoPtr
->nButtonWidth
= infoPtr
->nBitmapWidth
+ 6;
1418 if ( infoPtr
->cxMin
>= 0 && infoPtr
->nButtonWidth
< infoPtr
->cxMin
)
1419 infoPtr
->nButtonWidth
= infoPtr
->cxMin
;
1420 if ( infoPtr
->cxMax
> 0 && infoPtr
->nButtonWidth
> infoPtr
->cxMax
)
1421 infoPtr
->nButtonWidth
= infoPtr
->cxMax
;
1423 TOOLBAR_WrapToolbar( hwnd
, dwStyle
);
1425 x
= infoPtr
->nIndent
;
1429 * We will set the height below, and we set the width on entry
1430 * so we do not reset them here..
1433 GetClientRect( hwnd
, &rc
);
1434 /* get initial values for toolbar */
1435 infoPtr
->nWidth
= rc
.right
- rc
.left
;
1436 infoPtr
->nHeight
= rc
.bottom
- rc
.top
;
1439 /* from above, minimum is a button, and possible text */
1440 cx
= infoPtr
->nButtonWidth
;
1442 /* cannot use just ButtonHeight, we may have no buttons! */
1443 if (infoPtr
->nNumButtons
> 0)
1444 infoPtr
->nHeight
= infoPtr
->nButtonHeight
;
1446 cy
= infoPtr
->nHeight
;
1448 nRows
= nSepRows
= 0;
1450 infoPtr
->rcBound
.top
= y
;
1451 infoPtr
->rcBound
.left
= x
;
1452 infoPtr
->rcBound
.bottom
= y
+ cy
;
1453 infoPtr
->rcBound
.right
= x
;
1455 btnPtr
= infoPtr
->buttons
;
1457 /* do not base height/width on parent, if the parent is a */
1458 /* rebar control it could have multiple rows of toolbars */
1459 /* GetClientRect( GetParent(hwnd), &rc ); */
1460 /* cx = rc.right - rc.left; */
1461 /* cy = rc.bottom - rc.top; */
1463 TRACE("cy=%d\n", cy
);
1465 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++ )
1468 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
1470 SetRectEmpty (&btnPtr
->rect
);
1474 cy
= infoPtr
->nHeight
;
1476 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1477 /* it is the actual width of the separator. This is used for */
1478 /* custom controls in toolbars. */
1479 if (btnPtr
->fsStyle
& BTNS_SEP
) {
1480 if (btnPtr
->fsStyle
& BTNS_DROPDOWN
) {
1481 cy
= (btnPtr
->iBitmap
> 0) ?
1482 btnPtr
->iBitmap
: SEPARATOR_WIDTH
;
1483 cx
= infoPtr
->nButtonWidth
;
1486 cx
= (btnPtr
->iBitmap
> 0) ?
1487 btnPtr
->iBitmap
: SEPARATOR_WIDTH
;
1491 if ((infoPtr
->dwExStyle
& TBSTYLE_EX_MIXEDBUTTONS
) ||
1492 (btnPtr
->fsStyle
& BTNS_AUTOSIZE
))
1499 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
1501 TOOLBAR_MeasureString(infoPtr
, btnPtr
, hdc
, &sz
);
1503 SelectObject (hdc
, hOldFont
);
1504 ReleaseDC (hwnd
, hdc
);
1507 sz
.cx
+= 2*LIST_TEXT_OFFSET
;
1508 cx
= sz
.cx
+ 2*LIST_IMAGE_OFFSET
;
1509 if (TOOLBAR_TestImageExist (infoPtr
, btnPtr
, GETDEFIMAGELIST(infoPtr
,0)))
1511 if (dwStyle
& TBSTYLE_LIST
)
1512 cx
+= infoPtr
->nBitmapWidth
;
1513 else if (cx
< (infoPtr
->nBitmapWidth
+7))
1514 cx
= infoPtr
->nBitmapWidth
+7;
1516 else if (dwStyle
& TBSTYLE_LIST
)
1517 cx
+= LIST_IMAGE_ABSENT_WIDTH
;
1520 cx
= infoPtr
->nButtonWidth
;
1522 if (hasDropDownArrows
&& (btnPtr
->fsStyle
& BTNS_DROPDOWN
))
1523 cx
+= DDARROW_WIDTH
;
1525 if (btnPtr
->fsState
& TBSTATE_WRAP
)
1528 SetRect (&btnPtr
->rect
, x
, y
, x
+ cx
, y
+ cy
);
1530 if (infoPtr
->rcBound
.left
> x
)
1531 infoPtr
->rcBound
.left
= x
;
1532 if (infoPtr
->rcBound
.right
< x
+ cx
)
1533 infoPtr
->rcBound
.right
= x
+ cx
;
1534 if (infoPtr
->rcBound
.bottom
< y
+ cy
)
1535 infoPtr
->rcBound
.bottom
= y
+ cy
;
1537 /* Set the toolTip only for non-hidden, non-separator button */
1538 if (infoPtr
->hwndToolTip
&& !(btnPtr
->fsStyle
& BTNS_SEP
))
1542 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
1543 ti
.cbSize
= sizeof(TTTOOLINFOA
);
1545 ti
.uId
= btnPtr
->idCommand
;
1546 ti
.rect
= btnPtr
->rect
;
1547 SendMessageA (infoPtr
->hwndToolTip
, TTM_NEWTOOLRECTA
,
1551 /* btnPtr->nRow is zero based. The space between the rows is */
1552 /* also considered as a row. */
1553 btnPtr
->nRow
= nRows
+ nSepRows
;
1555 TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n",
1556 i
, btnPtr
->fsStyle
, bWrap
, nRows
, nSepRows
, btnPtr
->nRow
,
1561 if ( !(btnPtr
->fsStyle
& BTNS_SEP
) )
1565 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1566 /* it is the actual width of the separator. This is used for */
1567 /* custom controls in toolbars. */
1568 if ( !(btnPtr
->fsStyle
& BTNS_DROPDOWN
))
1569 y
+= cy
+ ( (btnPtr
->iBitmap
> 0 ) ?
1570 btnPtr
->iBitmap
: SEPARATOR_WIDTH
) * 2 /3;
1574 /* nSepRows is used to calculate the extra height follwoing */
1578 x
= infoPtr
->nIndent
;
1580 /* Increment row number unless this is the last button */
1581 /* and it has Wrap set. */
1582 if (i
!= infoPtr
->nNumButtons
-1)
1589 /* infoPtr->nRows is the number of rows on the toolbar */
1590 infoPtr
->nRows
= nRows
+ nSepRows
+ 1;
1593 /********************************************************************
1594 * The following while interesting, does not match the values *
1595 * created above for the button rectangles, nor the rcBound rect. *
1596 * We will comment it out and remove it later. *
1598 * The problem showed up as heights in the pager control that was *
1600 ********************************************************************/
1602 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
1604 infoPtr
->nHeight
= TOP_BORDER
+ (nRows
+ 1) * infoPtr
->nButtonHeight
+
1605 nSepRows
* (SEPARATOR_WIDTH
* 2 / 3) +
1606 nSepRows
* (infoPtr
->nBitmapHeight
+ 1) +
1610 infoPtr
->nHeight
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
1612 TRACE("toolbar height %d, button width %d\n", infoPtr
->nHeight
, infoPtr
->nButtonWidth
);
1617 TOOLBAR_InternalHitTest (HWND hwnd
, LPPOINT lpPt
)
1619 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
1620 TBUTTON_INFO
*btnPtr
;
1623 btnPtr
= infoPtr
->buttons
;
1624 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1625 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
1628 if (btnPtr
->fsStyle
& BTNS_SEP
) {
1629 if (PtInRect (&btnPtr
->rect
, *lpPt
)) {
1630 TRACE(" ON SEPARATOR %d!\n", i
);
1635 if (PtInRect (&btnPtr
->rect
, *lpPt
)) {
1636 TRACE(" ON BUTTON %d!\n", i
);
1642 TRACE(" NOWHERE!\n");
1648 TOOLBAR_GetButtonIndex (TOOLBAR_INFO
*infoPtr
, INT idCommand
, BOOL CommandIsIndex
)
1650 TBUTTON_INFO
*btnPtr
;
1653 if (CommandIsIndex
) {
1654 TRACE("command is really index command=%d\n", idCommand
);
1655 if (idCommand
>= infoPtr
->nNumButtons
) return -1;
1658 btnPtr
= infoPtr
->buttons
;
1659 for (i
= 0; i
< infoPtr
->nNumButtons
; i
++, btnPtr
++) {
1660 if (btnPtr
->idCommand
== idCommand
) {
1661 TRACE("command=%d index=%d\n", idCommand
, i
);
1665 TRACE("no index found for command=%d\n", idCommand
);
1671 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO
*infoPtr
, INT nIndex
)
1673 TBUTTON_INFO
*btnPtr
;
1676 if ((nIndex
< 0) || (nIndex
> infoPtr
->nNumButtons
))
1679 /* check index button */
1680 btnPtr
= &infoPtr
->buttons
[nIndex
];
1681 if ((btnPtr
->fsStyle
& BTNS_CHECKGROUP
) == BTNS_CHECKGROUP
) {
1682 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1686 /* check previous buttons */
1687 nRunIndex
= nIndex
- 1;
1688 while (nRunIndex
>= 0) {
1689 btnPtr
= &infoPtr
->buttons
[nRunIndex
];
1690 if ((btnPtr
->fsStyle
& BTNS_CHECKGROUP
) == BTNS_CHECKGROUP
) {
1691 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1699 /* check next buttons */
1700 nRunIndex
= nIndex
+ 1;
1701 while (nRunIndex
< infoPtr
->nNumButtons
) {
1702 btnPtr
= &infoPtr
->buttons
[nRunIndex
];
1703 if ((btnPtr
->fsStyle
& BTNS_CHECKGROUP
) == BTNS_CHECKGROUP
) {
1704 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
1717 TOOLBAR_RelayEvent (HWND hwndTip
, HWND hwndMsg
, UINT uMsg
,
1718 WPARAM wParam
, LPARAM lParam
)
1724 msg
.wParam
= wParam
;
1725 msg
.lParam
= lParam
;
1726 msg
.time
= GetMessageTime ();
1727 msg
.pt
.x
= LOWORD(GetMessagePos ());
1728 msg
.pt
.y
= HIWORD(GetMessagePos ());
1730 SendMessageA (hwndTip
, TTM_RELAYEVENT
, 0, (LPARAM
)&msg
);
1734 /***********************************************************************
1735 * TOOLBAR_CustomizeDialogProc
1736 * This function implements the toolbar customization dialog.
1738 static INT_PTR CALLBACK
1739 TOOLBAR_CustomizeDialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1741 PCUSTDLG_INFO custInfo
= (PCUSTDLG_INFO
)GetWindowLongA (hwnd
, DWL_USER
);
1742 PCUSTOMBUTTON btnInfo
;
1744 TOOLBAR_INFO
*infoPtr
= custInfo
? custInfo
->tbInfo
: NULL
;
1749 custInfo
= (PCUSTDLG_INFO
)lParam
;
1750 SetWindowLongA (hwnd
, DWL_USER
, (DWORD
)custInfo
);
1758 infoPtr
= custInfo
->tbInfo
;
1760 /* send TBN_QUERYINSERT notification */
1761 nmtb
.iItem
= custInfo
->tbInfo
->nNumButtons
;
1763 if (!TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_QUERYINSERT
))
1766 /* UNDOCUMENTED: dialog hwnd immediately follows NMHDR */
1767 nmtb
.iItem
= (int)hwnd
;
1768 /* Send TBN_INITCUSTOMIZE notification */
1769 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_INITCUSTOMIZE
) ==
1772 TRACE("TBNRF_HIDEHELP requested\n");
1773 ShowWindow(GetDlgItem(hwnd
, IDC_HELP_BTN
), SW_HIDE
);
1776 /* add items to 'toolbar buttons' list and check if removable */
1777 for (i
= 0; i
< custInfo
->tbInfo
->nNumButtons
; i
++)
1779 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1780 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1781 btnInfo
->btn
.fsStyle
= BTNS_SEP
;
1782 btnInfo
->bVirtual
= FALSE
;
1783 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1785 /* send TBN_QUERYDELETE notification */
1786 btnInfo
->bRemovable
= TOOLBAR_IsButtonRemovable(infoPtr
, i
, btnInfo
);
1788 index
= (int)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_ADDSTRING
, 0, 0);
1789 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1792 /* insert separator button into 'available buttons' list */
1793 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1794 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1795 btnInfo
->btn
.fsStyle
= BTNS_SEP
;
1796 btnInfo
->bVirtual
= FALSE
;
1797 btnInfo
->bRemovable
= TRUE
;
1798 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1799 index
= (int)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, (LPARAM
)btnInfo
);
1800 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1802 /* insert all buttons into dsa */
1805 /* send TBN_GETBUTTONINFO notification */
1808 nmtb
.pszText
= Buffer
;
1811 /* Clear previous button's text */
1812 ZeroMemory(nmtb
.pszText
, nmtb
.cchText
* sizeof(WCHAR
));
1814 if (!TOOLBAR_GetButtonInfo(infoPtr
, &nmtb
))
1817 TRACE("WM_INITDIALOG style: %x iItem(%d) idCommand(%d) iString(%d) %s\n",
1818 nmtb
.tbButton
.fsStyle
, i
,
1819 nmtb
.tbButton
.idCommand
,
1820 nmtb
.tbButton
.iString
,
1821 nmtb
.tbButton
.iString
>= 0 ? debugstr_w(infoPtr
->strings
[nmtb
.tbButton
.iString
])
1824 /* insert button into the apropriate list */
1825 index
= TOOLBAR_GetButtonIndex (custInfo
->tbInfo
, nmtb
.tbButton
.idCommand
, FALSE
);
1828 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1829 btnInfo
->bVirtual
= FALSE
;
1830 btnInfo
->bRemovable
= TRUE
;
1832 index
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, 0);
1833 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
,
1834 LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1838 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
,
1839 IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1842 memcpy (&btnInfo
->btn
, &nmtb
.tbButton
, sizeof(TBBUTTON
));
1843 if (!(nmtb
.tbButton
.fsStyle
& BTNS_SEP
))
1845 if (lstrlenW(nmtb
.pszText
))
1846 lstrcpyW(btnInfo
->text
, nmtb
.pszText
);
1847 else if (nmtb
.tbButton
.iString
>= 0 &&
1848 nmtb
.tbButton
.iString
< infoPtr
->nNumStrings
)
1850 lstrcpyW(btnInfo
->text
,
1851 infoPtr
->strings
[nmtb
.tbButton
.iString
]);
1856 /* select first item in the 'available' list */
1857 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, 0, 0);
1859 /* append 'virtual' separator button to the 'toolbar buttons' list */
1860 btnInfo
= (PCUSTOMBUTTON
)Alloc(sizeof(CUSTOMBUTTON
));
1861 memset (&btnInfo
->btn
, 0, sizeof(TBBUTTON
));
1862 btnInfo
->btn
.fsStyle
= BTNS_SEP
;
1863 btnInfo
->bVirtual
= TRUE
;
1864 btnInfo
->bRemovable
= FALSE
;
1865 LoadStringW (COMCTL32_hModule
, IDS_SEPARATOR
, btnInfo
->text
, 64);
1866 index
= (int)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_ADDSTRING
, 0, (LPARAM
)btnInfo
);
1867 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
1869 /* select last item in the 'toolbar' list */
1870 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
, 0);
1871 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETTOPINDEX
, index
, 0);
1873 /* set focus and disable buttons */
1874 PostMessageA (hwnd
, WM_USER
, 0, 0);
1879 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1880 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1881 EnableWindow (GetDlgItem (hwnd
,IDC_REMOVE_BTN
), FALSE
);
1882 SetFocus (GetDlgItem (hwnd
, IDC_TOOLBARBTN_LBOX
));
1886 EndDialog(hwnd
, FALSE
);
1890 switch (LOWORD(wParam
))
1892 case IDC_TOOLBARBTN_LBOX
:
1893 if (HIWORD(wParam
) == LBN_SELCHANGE
)
1895 PCUSTOMBUTTON btnInfo
;
1900 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1901 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1903 /* send TBN_QUERYINSERT notification */
1905 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1908 /* get list box item */
1909 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1911 if (index
== (count
- 1))
1913 /* last item (virtual separator) */
1914 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1915 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1917 else if (index
== (count
- 2))
1919 /* second last item (last non-virtual item) */
1920 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1921 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
1923 else if (index
== 0)
1926 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1927 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1931 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1932 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1935 EnableWindow (GetDlgItem (hwnd
,IDC_REMOVE_BTN
), btnInfo
->bRemovable
);
1939 case IDC_MOVEUP_BTN
:
1941 PCUSTOMBUTTON btnInfo
;
1945 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1946 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1947 TRACE("Move up: index %d\n", index
);
1949 /* send TBN_QUERYINSERT notification */
1952 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1955 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1957 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1958 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
-1, 0);
1959 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
-1, (LPARAM
)btnInfo
);
1960 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
-1 , 0);
1963 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), FALSE
);
1964 else if (index
>= (count
- 3))
1965 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), TRUE
);
1967 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
1968 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
-1, (LPARAM
)&(btnInfo
->btn
));
1973 case IDC_MOVEDN_BTN
: /* move down */
1975 PCUSTOMBUTTON btnInfo
;
1979 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
1980 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
1981 TRACE("Move up: index %d\n", index
);
1983 /* send TBN_QUERYINSERT notification */
1985 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
1988 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
1990 /* move button down */
1991 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
1992 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
+1, 0);
1993 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
+1, (LPARAM
)btnInfo
);
1994 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
+1 , 0);
1997 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEUP_BTN
), TRUE
);
1998 else if (index
>= (count
- 3))
1999 EnableWindow (GetDlgItem (hwnd
,IDC_MOVEDN_BTN
), FALSE
);
2001 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
2002 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
+1, (LPARAM
)&(btnInfo
->btn
));
2007 case IDC_REMOVE_BTN
: /* remove button */
2009 PCUSTOMBUTTON btnInfo
;
2012 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
2014 if (LB_ERR
== index
)
2017 TRACE("Remove: index %d\n", index
);
2019 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
,
2020 LB_GETITEMDATA
, index
, 0);
2022 /* send TBN_QUERYDELETE notification */
2023 if (TOOLBAR_IsButtonRemovable(infoPtr
, index
, btnInfo
))
2025 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
2026 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_DELETESTRING
, index
, 0);
2027 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETCURSEL
, index
, 0);
2029 SendMessageA (custInfo
->tbHwnd
, TB_DELETEBUTTON
, index
, 0);
2031 /* insert into 'available button' list */
2032 if (!(btnInfo
->btn
.fsStyle
& BTNS_SEP
))
2034 index
= (int)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_ADDSTRING
, 0, 0);
2035 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
2043 TOOLBAR_SendNotify(&nmtb
.hdr
, infoPtr
, TBN_CUSTHELP
);
2046 TOOLBAR_SendNotify(&nmtb
.hdr
, infoPtr
, TBN_RESET
);
2049 case IDOK
: /* Add button */
2054 count
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2055 index
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCURSEL
, 0, 0);
2056 TRACE("Add: index %d\n", index
);
2058 /* send TBN_QUERYINSERT notification */
2060 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
2063 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETITEMDATA
, index
, 0);
2067 /* remove from 'available buttons' list */
2068 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_DELETESTRING
, index
, 0);
2069 if (index
== count
-1)
2070 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, index
-1 , 0);
2072 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETCURSEL
, index
, 0);
2076 PCUSTOMBUTTON btnNew
;
2078 /* duplicate 'separator' button */
2079 btnNew
= (PCUSTOMBUTTON
)Alloc (sizeof(CUSTOMBUTTON
));
2080 memcpy (btnNew
, btnInfo
, sizeof(CUSTOMBUTTON
));
2084 /* insert into 'toolbar button' list */
2085 index
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCURSEL
, 0, 0);
2086 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_INSERTSTRING
, index
, 0);
2087 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, index
, (LPARAM
)btnInfo
);
2089 SendMessageA (custInfo
->tbHwnd
, TB_INSERTBUTTONA
, index
, (LPARAM
)&(btnInfo
->btn
));
2095 EndDialog(hwnd
, FALSE
);
2105 /* delete items from 'toolbar buttons' listbox*/
2106 count
= SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2107 for (i
= 0; i
< count
; i
++)
2109 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_GETITEMDATA
, i
, 0);
2111 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_SETITEMDATA
, 0, 0);
2113 SendDlgItemMessageA (hwnd
, IDC_TOOLBARBTN_LBOX
, LB_RESETCONTENT
, 0, 0);
2116 /* delete items from 'available buttons' listbox*/
2117 count
= SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETCOUNT
, 0, 0);
2118 for (i
= 0; i
< count
; i
++)
2120 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_GETITEMDATA
, i
, 0);
2122 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_SETITEMDATA
, i
, 0);
2124 SendDlgItemMessageA (hwnd
, IDC_AVAILBTN_LBOX
, LB_RESETCONTENT
, 0, 0);
2129 if (wParam
== IDC_AVAILBTN_LBOX
|| wParam
== IDC_TOOLBARBTN_LBOX
)
2131 LPDRAWITEMSTRUCT lpdis
= (LPDRAWITEMSTRUCT
)lParam
;
2132 DWORD dwStyle
= GetWindowLongA (infoPtr
->hwndSelf
, GWL_STYLE
);
2137 COLORREF oldText
= 0;
2141 btnInfo
= (PCUSTOMBUTTON
)SendDlgItemMessageA (hwnd
, wParam
, LB_GETITEMDATA
, (WPARAM
)lpdis
->itemID
, 0);
2142 if (btnInfo
== NULL
)
2144 FIXME("btnInfo invalid!\n");
2148 /* set colors and select objects */
2149 oldBk
= SetBkColor (lpdis
->hDC
, (lpdis
->itemState
& ODS_FOCUS
)?comctl32_color
.clrHighlight
:comctl32_color
.clrWindow
);
2150 if (btnInfo
->bVirtual
)
2151 oldText
= SetTextColor (lpdis
->hDC
, comctl32_color
.clrGrayText
);
2153 oldText
= SetTextColor (lpdis
->hDC
, (lpdis
->itemState
& ODS_FOCUS
)?comctl32_color
.clrHighlightText
:comctl32_color
.clrWindowText
);
2154 hPen
= CreatePen( PS_SOLID
, 1,
2155 GetSysColor( (lpdis
->itemState
& ODS_SELECTED
)?COLOR_HIGHLIGHT
:COLOR_WINDOW
));
2156 hOldPen
= SelectObject (lpdis
->hDC
, hPen
);
2157 hOldBrush
= SelectObject (lpdis
->hDC
, GetSysColorBrush ((lpdis
->itemState
& ODS_FOCUS
)?COLOR_HIGHLIGHT
:COLOR_WINDOW
));
2159 /* fill background rectangle */
2160 Rectangle (lpdis
->hDC
, lpdis
->rcItem
.left
, lpdis
->rcItem
.top
,
2161 lpdis
->rcItem
.right
, lpdis
->rcItem
.bottom
);
2163 /* calculate button and text rectangles */
2164 CopyRect (&rcButton
, &lpdis
->rcItem
);
2165 InflateRect (&rcButton
, -1, -1);
2166 CopyRect (&rcText
, &rcButton
);
2167 rcButton
.right
= rcButton
.left
+ custInfo
->tbInfo
->nBitmapWidth
+ 6;
2168 rcText
.left
= rcButton
.right
+ 2;
2170 /* draw focus rectangle */
2171 if (lpdis
->itemState
& ODS_FOCUS
)
2172 DrawFocusRect (lpdis
->hDC
, &lpdis
->rcItem
);
2175 if (!(dwStyle
& TBSTYLE_FLAT
))
2176 DrawEdge (lpdis
->hDC
, &rcButton
, EDGE_RAISED
, BF_RECT
|BF_MIDDLE
|BF_SOFT
);
2178 /* draw image and text */
2179 if ((btnInfo
->btn
.fsStyle
& BTNS_SEP
) == 0) {
2180 HIMAGELIST himl
= GETDEFIMAGELIST(infoPtr
, GETHIMLID(infoPtr
,
2181 btnInfo
->btn
.iBitmap
));
2182 ImageList_Draw (himl
, GETIBITMAP(infoPtr
, btnInfo
->btn
.iBitmap
),
2183 lpdis
->hDC
, rcButton
.left
+3, rcButton
.top
+3, ILD_NORMAL
);
2185 DrawTextW (lpdis
->hDC
, btnInfo
->text
, -1, &rcText
,
2186 DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
);
2188 /* delete objects and reset colors */
2189 SelectObject (lpdis
->hDC
, hOldBrush
);
2190 SelectObject (lpdis
->hDC
, hOldPen
);
2191 SetBkColor (lpdis
->hDC
, oldBk
);
2192 SetTextColor (lpdis
->hDC
, oldText
);
2193 DeleteObject( hPen
);
2198 case WM_MEASUREITEM
:
2199 if (wParam
== IDC_AVAILBTN_LBOX
|| wParam
== IDC_TOOLBARBTN_LBOX
)
2201 MEASUREITEMSTRUCT
*lpmis
= (MEASUREITEMSTRUCT
*)lParam
;
2203 if (custInfo
&& custInfo
->tbInfo
)
2204 lpmis
->itemHeight
= custInfo
->tbInfo
->nBitmapHeight
+ 8;
2206 lpmis
->itemHeight
= 15 + 8; /* default height */
2218 /***********************************************************************
2219 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
2223 TOOLBAR_AddBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2225 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2226 LPTBADDBITMAP lpAddBmp
= (LPTBADDBITMAP
)lParam
;
2227 INT nIndex
= 0, nButtons
, nCount
;
2231 TRACE("hwnd=%p wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2235 if (lpAddBmp
->hInst
== HINST_COMMCTRL
)
2237 if ((lpAddBmp
->nID
& ~1) == IDB_STD_SMALL_COLOR
)
2239 else if ((lpAddBmp
->nID
& ~1) == IDB_VIEW_SMALL_COLOR
)
2241 else if ((lpAddBmp
->nID
& ~1) == IDB_HIST_SMALL_COLOR
)
2246 TRACE ("adding %d internal bitmaps!\n", nButtons
);
2248 /* Windows resize all the buttons to the size of a newly added standard image */
2249 if (lpAddBmp
->nID
& 1)
2252 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
2253 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
2255 SendMessageA (hwnd
, TB_SETBITMAPSIZE
, 0,
2256 MAKELPARAM((WORD
)24, (WORD
)24));
2257 SendMessageA (hwnd
, TB_SETBUTTONSIZE
, 0,
2258 MAKELPARAM((WORD
)31, (WORD
)30));
2263 SendMessageA (hwnd
, TB_SETBITMAPSIZE
, 0,
2264 MAKELPARAM((WORD
)16, (WORD
)16));
2265 SendMessageA (hwnd
, TB_SETBUTTONSIZE
, 0,
2266 MAKELPARAM((WORD
)22, (WORD
)22));
2269 TOOLBAR_CalcToolbar (hwnd
);
2273 nButtons
= (INT
)wParam
;
2277 TRACE ("adding %d bitmaps!\n", nButtons
);
2280 if (!infoPtr
->cimlDef
) {
2281 /* create new default image list */
2282 TRACE ("creating default image list!\n");
2284 himlDef
= ImageList_Create (infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
,
2285 ILC_COLOR
| ILC_MASK
, nButtons
, 2);
2286 TOOLBAR_InsertImageList(&infoPtr
->himlDef
, &infoPtr
->cimlDef
, himlDef
, 0);
2287 infoPtr
->himlInt
= himlDef
;
2290 himlDef
= GETDEFIMAGELIST(infoPtr
, 0);
2294 WARN("No default image list available\n");
2298 nCount
= ImageList_GetImageCount(himlDef
);
2300 /* Add bitmaps to the default image list */
2301 if (lpAddBmp
->hInst
== NULL
)
2304 HBITMAP hOldBitmapBitmap
, hOldBitmapLoad
;
2305 HDC hdcImage
, hdcBitmap
;
2307 /* copy the bitmap before adding it so that the user's bitmap
2308 * doesn't get modified.
2310 GetObjectA ((HBITMAP
)lpAddBmp
->nID
, sizeof(BITMAP
), (LPVOID
)&bmp
);
2312 hdcImage
= CreateCompatibleDC(0);
2313 hdcBitmap
= CreateCompatibleDC(0);
2315 /* create new bitmap */
2316 hbmLoad
= CreateBitmap (bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
, bmp
.bmBitsPixel
, NULL
);
2317 hOldBitmapBitmap
= SelectObject(hdcBitmap
, (HBITMAP
)lpAddBmp
->nID
);
2318 hOldBitmapLoad
= SelectObject(hdcImage
, hbmLoad
);
2320 /* Copy the user's image */
2321 BitBlt (hdcImage
, 0, 0, bmp
.bmWidth
, bmp
.bmHeight
,
2322 hdcBitmap
, 0, 0, SRCCOPY
);
2324 SelectObject (hdcImage
, hOldBitmapLoad
);
2325 SelectObject (hdcBitmap
, hOldBitmapBitmap
);
2326 DeleteDC (hdcImage
);
2327 DeleteDC (hdcBitmap
);
2329 nIndex
= ImageList_AddMasked (himlDef
, hbmLoad
, comctl32_color
.clrBtnFace
);
2330 DeleteObject (hbmLoad
);
2332 else if (lpAddBmp
->hInst
== HINST_COMMCTRL
)
2334 /* Add system bitmaps */
2335 switch (lpAddBmp
->nID
)
2337 case IDB_STD_SMALL_COLOR
:
2338 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2339 MAKEINTRESOURCEA(IDB_STD_SMALL
));
2340 nIndex
= ImageList_AddMasked (himlDef
,
2341 hbmLoad
, comctl32_color
.clrBtnFace
);
2342 DeleteObject (hbmLoad
);
2345 case IDB_STD_LARGE_COLOR
:
2346 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2347 MAKEINTRESOURCEA(IDB_STD_LARGE
));
2348 nIndex
= ImageList_AddMasked (himlDef
,
2349 hbmLoad
, comctl32_color
.clrBtnFace
);
2350 DeleteObject (hbmLoad
);
2353 case IDB_VIEW_SMALL_COLOR
:
2354 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2355 MAKEINTRESOURCEA(IDB_VIEW_SMALL
));
2356 nIndex
= ImageList_AddMasked (himlDef
,
2357 hbmLoad
, comctl32_color
.clrBtnFace
);
2358 DeleteObject (hbmLoad
);
2361 case IDB_VIEW_LARGE_COLOR
:
2362 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2363 MAKEINTRESOURCEA(IDB_VIEW_LARGE
));
2364 nIndex
= ImageList_AddMasked (himlDef
,
2365 hbmLoad
, comctl32_color
.clrBtnFace
);
2366 DeleteObject (hbmLoad
);
2369 case IDB_HIST_SMALL_COLOR
:
2370 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2371 MAKEINTRESOURCEA(IDB_HIST_SMALL
));
2372 nIndex
= ImageList_AddMasked (himlDef
,
2373 hbmLoad
, comctl32_color
.clrBtnFace
);
2374 DeleteObject (hbmLoad
);
2377 case IDB_HIST_LARGE_COLOR
:
2378 hbmLoad
= LoadBitmapA (COMCTL32_hModule
,
2379 MAKEINTRESOURCEA(IDB_HIST_LARGE
));
2380 nIndex
= ImageList_AddMasked (himlDef
,
2381 hbmLoad
, comctl32_color
.clrBtnFace
);
2382 DeleteObject (hbmLoad
);
2386 nIndex
= ImageList_GetImageCount (himlDef
);
2387 ERR ("invalid imagelist!\n");
2393 hbmLoad
= LoadBitmapA (lpAddBmp
->hInst
, (LPSTR
)lpAddBmp
->nID
);
2394 nIndex
= ImageList_AddMasked (himlDef
, hbmLoad
, comctl32_color
.clrBtnFace
);
2395 DeleteObject (hbmLoad
);
2398 TRACE("Number of bitmap infos: %d\n", infoPtr
->nNumBitmapInfos
);
2400 if (infoPtr
->nNumBitmapInfos
== 0)
2402 infoPtr
->bitmaps
= Alloc(sizeof(TBITMAP_INFO
));
2406 TBITMAP_INFO
*oldBitmaps
= infoPtr
->bitmaps
;
2407 infoPtr
->bitmaps
= Alloc((infoPtr
->nNumBitmapInfos
+ 1) * sizeof(TBITMAP_INFO
));
2408 memcpy(&infoPtr
->bitmaps
[0], &oldBitmaps
[0], infoPtr
->nNumBitmapInfos
);
2411 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].nButtons
= nButtons
;
2412 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].hInst
= lpAddBmp
->hInst
;
2413 infoPtr
->bitmaps
[infoPtr
->nNumBitmapInfos
].nID
= lpAddBmp
->nID
;
2415 infoPtr
->nNumBitmapInfos
++;
2416 TRACE("Number of bitmap infos: %d\n", infoPtr
->nNumBitmapInfos
);
2420 INT imagecount
= ImageList_GetImageCount(himlDef
);
2422 if (infoPtr
->nNumBitmaps
+ nButtons
!= imagecount
)
2424 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",
2425 infoPtr
->nNumBitmaps
, nCount
, imagecount
- nCount
,
2426 infoPtr
->nNumBitmaps
+nButtons
,imagecount
);
2428 infoPtr
->nNumBitmaps
= imagecount
;
2431 infoPtr
->nNumBitmaps
+= nButtons
;
2434 InvalidateRect(hwnd
, NULL
, FALSE
);
2441 TOOLBAR_AddButtonsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2443 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2444 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
2445 INT nOldButtons
, nNewButtons
, nAddButtons
, nCount
;
2447 TRACE("adding %d buttons!\n", wParam
);
2449 nAddButtons
= (UINT
)wParam
;
2450 nOldButtons
= infoPtr
->nNumButtons
;
2451 nNewButtons
= nOldButtons
+ nAddButtons
;
2453 if (infoPtr
->nNumButtons
== 0) {
2455 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2458 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2460 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2461 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2462 nOldButtons
* sizeof(TBUTTON_INFO
));
2466 infoPtr
->nNumButtons
= nNewButtons
;
2468 /* insert new button data */
2469 for (nCount
= 0; nCount
< nAddButtons
; nCount
++) {
2470 TBUTTON_INFO
*btnPtr
= &infoPtr
->buttons
[nOldButtons
+nCount
];
2471 btnPtr
->iBitmap
= lpTbb
[nCount
].iBitmap
;
2472 btnPtr
->idCommand
= lpTbb
[nCount
].idCommand
;
2473 btnPtr
->fsState
= lpTbb
[nCount
].fsState
;
2474 btnPtr
->fsStyle
= lpTbb
[nCount
].fsStyle
;
2475 btnPtr
->dwData
= lpTbb
[nCount
].dwData
;
2476 if(HIWORD(lpTbb
[nCount
].iString
) && lpTbb
[nCount
].iString
!= -1)
2477 Str_SetPtrAtoW ((LPWSTR
*)&btnPtr
->iString
, (LPSTR
)lpTbb
[nCount
].iString
);
2479 btnPtr
->iString
= lpTbb
[nCount
].iString
;
2480 btnPtr
->bHot
= FALSE
;
2482 if ((infoPtr
->hwndToolTip
) && !(btnPtr
->fsStyle
& BTNS_SEP
)) {
2485 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
2486 ti
.cbSize
= sizeof (TTTOOLINFOA
);
2488 ti
.uId
= btnPtr
->idCommand
;
2490 ti
.lpszText
= LPSTR_TEXTCALLBACKA
;
2492 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
,
2497 TOOLBAR_CalcToolbar (hwnd
);
2499 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
2501 InvalidateRect(hwnd
, NULL
, FALSE
);
2508 TOOLBAR_AddButtonsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2510 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2511 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
2512 INT nOldButtons
, nNewButtons
, nAddButtons
, nCount
;
2514 TRACE("adding %d buttons!\n", wParam
);
2516 nAddButtons
= (UINT
)wParam
;
2517 nOldButtons
= infoPtr
->nNumButtons
;
2518 nNewButtons
= nOldButtons
+ nAddButtons
;
2520 if (infoPtr
->nNumButtons
== 0) {
2522 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2525 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
2527 Alloc (sizeof(TBUTTON_INFO
) * nNewButtons
);
2528 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
2529 nOldButtons
* sizeof(TBUTTON_INFO
));
2533 infoPtr
->nNumButtons
= nNewButtons
;
2535 /* insert new button data */
2536 for (nCount
= 0; nCount
< nAddButtons
; nCount
++) {
2537 TBUTTON_INFO
*btnPtr
= &infoPtr
->buttons
[nOldButtons
+nCount
];
2538 btnPtr
->iBitmap
= lpTbb
[nCount
].iBitmap
;
2539 btnPtr
->idCommand
= lpTbb
[nCount
].idCommand
;
2540 btnPtr
->fsState
= lpTbb
[nCount
].fsState
;
2541 btnPtr
->fsStyle
= lpTbb
[nCount
].fsStyle
;
2542 btnPtr
->dwData
= lpTbb
[nCount
].dwData
;
2543 if(HIWORD(lpTbb
[nCount
].iString
) && lpTbb
[nCount
].iString
!= -1)
2544 Str_SetPtrW ((LPWSTR
*)&btnPtr
->iString
, (LPWSTR
)lpTbb
[nCount
].iString
);
2546 btnPtr
->iString
= lpTbb
[nCount
].iString
;
2547 btnPtr
->bHot
= FALSE
;
2549 if ((infoPtr
->hwndToolTip
) && !(btnPtr
->fsStyle
& BTNS_SEP
)) {
2552 ZeroMemory (&ti
, sizeof(TTTOOLINFOW
));
2553 ti
.cbSize
= sizeof (TTTOOLINFOW
);
2555 ti
.uId
= btnPtr
->idCommand
;
2557 ti
.lpszText
= LPSTR_TEXTCALLBACKW
;
2560 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
,
2565 TOOLBAR_CalcToolbar (hwnd
);
2567 TOOLBAR_DumpToolbar (infoPtr
, __LINE__
);
2569 InvalidateRect(hwnd
, NULL
, FALSE
);
2576 TOOLBAR_AddStringA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2578 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2581 if ((wParam
) && (HIWORD(lParam
) == 0)) {
2584 TRACE("adding string from resource!\n");
2586 len
= LoadStringA ((HINSTANCE
)wParam
, (UINT
)lParam
,
2589 TRACE("len=%d \"%s\"\n", len
, szString
);
2590 nIndex
= infoPtr
->nNumStrings
;
2591 if (infoPtr
->nNumStrings
== 0) {
2593 Alloc (sizeof(LPWSTR
));
2596 LPWSTR
*oldStrings
= infoPtr
->strings
;
2598 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2599 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2600 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2604 /*Alloc zeros out the allocated memory*/
2605 Str_SetPtrAtoW (&infoPtr
->strings
[infoPtr
->nNumStrings
], szString
);
2606 infoPtr
->nNumStrings
++;
2609 LPSTR p
= (LPSTR
)lParam
;
2614 TRACE("adding string(s) from array!\n");
2616 nIndex
= infoPtr
->nNumStrings
;
2619 TRACE("len=%d \"%s\"\n", len
, p
);
2621 if (infoPtr
->nNumStrings
== 0) {
2623 Alloc (sizeof(LPWSTR
));
2626 LPWSTR
*oldStrings
= infoPtr
->strings
;
2628 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2629 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2630 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2634 Str_SetPtrAtoW (&infoPtr
->strings
[infoPtr
->nNumStrings
], p
);
2635 infoPtr
->nNumStrings
++;
2646 TOOLBAR_AddStringW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2648 #define MAX_RESOURCE_STRING_LENGTH 512
2649 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2652 if ((wParam
) && (HIWORD(lParam
) == 0)) {
2653 WCHAR szString
[MAX_RESOURCE_STRING_LENGTH
];
2655 TRACE("adding string from resource!\n");
2657 len
= LoadStringW ((HINSTANCE
)wParam
, (UINT
)lParam
,
2658 szString
, MAX_RESOURCE_STRING_LENGTH
);
2660 TRACE("len=%d %s\n", len
, debugstr_w(szString
));
2661 TRACE("First char: 0x%x\n", *szString
);
2662 if (szString
[0] == L
'|')
2664 PWSTR p
= szString
+ 1;
2666 nIndex
= infoPtr
->nNumStrings
;
2667 while (*p
!= L
'|' && *p
!= L
'\0') {
2670 if (infoPtr
->nNumStrings
== 0) {
2671 infoPtr
->strings
= Alloc (sizeof(LPWSTR
));
2675 LPWSTR
*oldStrings
= infoPtr
->strings
;
2676 infoPtr
->strings
= Alloc(sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2677 memcpy(&infoPtr
->strings
[0], &oldStrings
[0],
2678 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2682 np
=strchrW (p
, '|');
2690 TRACE("len=%d %s\n", len
, debugstr_w(p
));
2691 infoPtr
->strings
[infoPtr
->nNumStrings
] =
2692 Alloc (sizeof(WCHAR
)*(len
+1));
2693 lstrcpynW (infoPtr
->strings
[infoPtr
->nNumStrings
], p
, len
+1);
2694 infoPtr
->nNumStrings
++;
2701 nIndex
= infoPtr
->nNumStrings
;
2702 if (infoPtr
->nNumStrings
== 0) {
2704 Alloc (sizeof(LPWSTR
));
2707 LPWSTR
*oldStrings
= infoPtr
->strings
;
2709 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2710 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2711 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2715 Str_SetPtrW (&infoPtr
->strings
[infoPtr
->nNumStrings
], szString
);
2716 infoPtr
->nNumStrings
++;
2720 LPWSTR p
= (LPWSTR
)lParam
;
2725 TRACE("adding string(s) from array!\n");
2726 nIndex
= infoPtr
->nNumStrings
;
2730 TRACE("len=%d %s\n", len
, debugstr_w(p
));
2731 if (infoPtr
->nNumStrings
== 0) {
2733 Alloc (sizeof(LPWSTR
));
2736 LPWSTR
*oldStrings
= infoPtr
->strings
;
2738 Alloc (sizeof(LPWSTR
) * (infoPtr
->nNumStrings
+ 1));
2739 memcpy (&infoPtr
->strings
[0], &oldStrings
[0],
2740 sizeof(LPWSTR
) * infoPtr
->nNumStrings
);
2744 Str_SetPtrW (&infoPtr
->strings
[infoPtr
->nNumStrings
], p
);
2745 infoPtr
->nNumStrings
++;
2756 TOOLBAR_AutoSize (HWND hwnd
)
2758 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2759 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2765 UINT uPosFlags
= SWP_NOZORDER
;
2767 TRACE("resize forced, style=%lx!\n", dwStyle
);
2769 parent
= GetParent (hwnd
);
2770 GetClientRect(parent
, &parent_rect
);
2772 x
= parent_rect
.left
;
2773 y
= parent_rect
.top
;
2775 /* FIXME: we should be able to early out if nothing */
2776 /* has changed with nWidth != parent_rect width */
2778 if (dwStyle
& CCS_NORESIZE
) {
2779 uPosFlags
|= (SWP_NOSIZE
| SWP_NOMOVE
);
2782 TOOLBAR_CalcToolbar (hwnd
);
2785 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
2786 TOOLBAR_CalcToolbar (hwnd
);
2787 InvalidateRect( hwnd
, NULL
, TRUE
);
2788 cy
= infoPtr
->nHeight
;
2789 cx
= infoPtr
->nWidth
;
2791 if ((dwStyle
& CCS_BOTTOM
) == CCS_NOMOVEY
) {
2792 GetWindowRect(hwnd
, &window_rect
);
2793 ScreenToClient(parent
, (LPPOINT
)&window_rect
.left
);
2794 y
= window_rect
.top
;
2796 if ((dwStyle
& CCS_BOTTOM
) == CCS_BOTTOM
) {
2797 GetWindowRect(hwnd
, &window_rect
);
2798 y
= parent_rect
.bottom
- ( window_rect
.bottom
- window_rect
.top
);
2802 if (dwStyle
& CCS_NOPARENTALIGN
)
2803 uPosFlags
|= SWP_NOMOVE
;
2805 if (!(dwStyle
& CCS_NODIVIDER
))
2806 cy
+= GetSystemMetrics(SM_CYEDGE
);
2808 if (dwStyle
& WS_BORDER
)
2811 cy
+= GetSystemMetrics(SM_CYEDGE
);
2812 cx
+= GetSystemMetrics(SM_CYEDGE
);
2815 infoPtr
->bAutoSize
= TRUE
;
2816 SetWindowPos (hwnd
, HWND_TOP
, x
, y
, cx
, cy
, uPosFlags
);
2817 /* The following line makes sure that the infoPtr->bAutoSize is turned off
2818 * after the setwindowpos calls */
2819 infoPtr
->bAutoSize
= FALSE
;
2826 TOOLBAR_ButtonCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2828 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2830 return infoPtr
->nNumButtons
;
2835 TOOLBAR_ButtonStructSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2837 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2839 if (infoPtr
== NULL
) {
2840 ERR("(%p, 0x%x, 0x%lx)\n", hwnd
, wParam
, lParam
);
2841 ERR("infoPtr == NULL!\n");
2845 infoPtr
->dwStructSize
= (DWORD
)wParam
;
2852 TOOLBAR_ChangeBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2854 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2855 TBUTTON_INFO
*btnPtr
;
2858 TRACE("button %d, iBitmap now %d\n", wParam
, LOWORD(lParam
));
2860 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2864 btnPtr
= &infoPtr
->buttons
[nIndex
];
2865 btnPtr
->iBitmap
= LOWORD(lParam
);
2867 /* we HAVE to erase the background, the new bitmap could be */
2869 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
2876 TOOLBAR_CheckButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2878 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2879 TBUTTON_INFO
*btnPtr
;
2882 BOOL bChecked
= FALSE
;
2884 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2888 btnPtr
= &infoPtr
->buttons
[nIndex
];
2890 if (!(btnPtr
->fsStyle
& BTNS_CHECK
))
2893 bChecked
= (btnPtr
->fsState
& TBSTATE_CHECKED
) ? TRUE
: FALSE
;
2895 if (LOWORD(lParam
) == FALSE
)
2896 btnPtr
->fsState
&= ~TBSTATE_CHECKED
;
2898 if (btnPtr
->fsStyle
& BTNS_GROUP
) {
2900 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr
, nIndex
);
2901 if (nOldIndex
== nIndex
)
2903 if (nOldIndex
!= -1)
2904 infoPtr
->buttons
[nOldIndex
].fsState
&= ~TBSTATE_CHECKED
;
2906 btnPtr
->fsState
|= TBSTATE_CHECKED
;
2909 if( bChecked
!= LOWORD(lParam
) )
2911 if (nOldIndex
!= -1)
2913 InvalidateRect(hwnd
, &infoPtr
->buttons
[nOldIndex
].rect
,
2914 TOOLBAR_HasText(infoPtr
, &infoPtr
->buttons
[nOldIndex
]));
2916 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
2919 /* FIXME: Send a WM_NOTIFY?? */
2926 TOOLBAR_CommandToIndex (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2928 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2930 return TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
2935 TOOLBAR_Customize (HWND hwnd
)
2937 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2938 CUSTDLG_INFO custInfo
;
2944 custInfo
.tbInfo
= infoPtr
;
2945 custInfo
.tbHwnd
= hwnd
;
2947 /* send TBN_BEGINADJUST notification */
2948 TOOLBAR_SendNotify ((NMHDR
*) &nmhdr
, infoPtr
,
2951 if (!(hRes
= FindResourceA (COMCTL32_hModule
,
2952 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE
),
2956 if(!(template = (LPVOID
)LoadResource (COMCTL32_hModule
, hRes
)))
2959 ret
= DialogBoxIndirectParamA ((HINSTANCE
)GetWindowLongA(hwnd
, GWL_HINSTANCE
),
2960 (LPDLGTEMPLATEA
)template,
2962 TOOLBAR_CustomizeDialogProc
,
2965 /* send TBN_ENDADJUST notification */
2966 TOOLBAR_SendNotify ((NMHDR
*) &nmhdr
, infoPtr
,
2974 TOOLBAR_DeleteButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2976 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
2977 INT nIndex
= (INT
)wParam
;
2979 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
2982 if ((infoPtr
->hwndToolTip
) &&
2983 !(infoPtr
->buttons
[nIndex
].fsStyle
& BTNS_SEP
)) {
2986 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
2987 ti
.cbSize
= sizeof (TTTOOLINFOA
);
2989 ti
.uId
= infoPtr
->buttons
[nIndex
].idCommand
;
2991 SendMessageA (infoPtr
->hwndToolTip
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
2994 if (infoPtr
->nNumButtons
== 1) {
2995 TRACE(" simple delete!\n");
2996 Free (infoPtr
->buttons
);
2997 infoPtr
->buttons
= NULL
;
2998 infoPtr
->nNumButtons
= 0;
3001 TBUTTON_INFO
*oldButtons
= infoPtr
->buttons
;
3002 TRACE("complex delete! [nIndex=%d]\n", nIndex
);
3004 infoPtr
->nNumButtons
--;
3005 infoPtr
->buttons
= Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
3007 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
3008 nIndex
* sizeof(TBUTTON_INFO
));
3011 if (nIndex
< infoPtr
->nNumButtons
) {
3012 memcpy (&infoPtr
->buttons
[nIndex
], &oldButtons
[nIndex
+1],
3013 (infoPtr
->nNumButtons
- nIndex
) * sizeof(TBUTTON_INFO
));
3019 TOOLBAR_CalcToolbar (hwnd
);
3021 InvalidateRect (hwnd
, NULL
, TRUE
);
3028 TOOLBAR_EnableButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3030 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3031 TBUTTON_INFO
*btnPtr
;
3035 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3039 btnPtr
= &infoPtr
->buttons
[nIndex
];
3041 bState
= btnPtr
->fsState
& TBSTATE_ENABLED
;
3043 /* update the toolbar button state */
3044 if(LOWORD(lParam
) == FALSE
) {
3045 btnPtr
->fsState
&= ~(TBSTATE_ENABLED
| TBSTATE_PRESSED
);
3047 btnPtr
->fsState
|= TBSTATE_ENABLED
;
3050 /* redraw the button only if the state of the button changed */
3051 if(bState
!= (btnPtr
->fsState
& TBSTATE_ENABLED
))
3053 InvalidateRect(hwnd
, &btnPtr
->rect
,
3054 TOOLBAR_HasText(infoPtr
, btnPtr
));
3061 static inline LRESULT
3062 TOOLBAR_GetAnchorHighlight (HWND hwnd
)
3064 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3066 return infoPtr
->bAnchor
;
3071 TOOLBAR_GetBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3073 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3076 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3080 return infoPtr
->buttons
[nIndex
].iBitmap
;
3084 static inline LRESULT
3085 TOOLBAR_GetBitmapFlags (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3087 return (GetDeviceCaps (0, LOGPIXELSX
) >= 120) ? TBBF_LARGE
: 0;
3092 TOOLBAR_GetButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3094 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3095 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3096 INT nIndex
= (INT
)wParam
;
3097 TBUTTON_INFO
*btnPtr
;
3099 if (infoPtr
== NULL
)
3105 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3108 btnPtr
= &infoPtr
->buttons
[nIndex
];
3109 lpTbb
->iBitmap
= btnPtr
->iBitmap
;
3110 lpTbb
->idCommand
= btnPtr
->idCommand
;
3111 lpTbb
->fsState
= btnPtr
->fsState
;
3112 lpTbb
->fsStyle
= btnPtr
->fsStyle
;
3113 lpTbb
->bReserved
[0] = 0;
3114 lpTbb
->bReserved
[1] = 0;
3115 lpTbb
->dwData
= btnPtr
->dwData
;
3116 lpTbb
->iString
= btnPtr
->iString
;
3123 TOOLBAR_GetButtonInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3125 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3126 LPTBBUTTONINFOA lpTbInfo
= (LPTBBUTTONINFOA
)lParam
;
3127 TBUTTON_INFO
*btnPtr
;
3130 if (infoPtr
== NULL
)
3132 if (lpTbInfo
== NULL
)
3134 if (lpTbInfo
->cbSize
< sizeof(TBBUTTONINFOA
))
3137 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
3138 lpTbInfo
->dwMask
& 0x80000000);
3142 if (!(btnPtr
= &infoPtr
->buttons
[nIndex
])) return -1;
3144 if (lpTbInfo
->dwMask
& TBIF_COMMAND
)
3145 lpTbInfo
->idCommand
= btnPtr
->idCommand
;
3146 if (lpTbInfo
->dwMask
& TBIF_IMAGE
)
3147 lpTbInfo
->iImage
= btnPtr
->iBitmap
;
3148 if (lpTbInfo
->dwMask
& TBIF_LPARAM
)
3149 lpTbInfo
->lParam
= btnPtr
->dwData
;
3150 if (lpTbInfo
->dwMask
& TBIF_SIZE
)
3151 lpTbInfo
->cx
= (WORD
)(btnPtr
->rect
.right
- btnPtr
->rect
.left
);
3152 if (lpTbInfo
->dwMask
& TBIF_STATE
)
3153 lpTbInfo
->fsState
= btnPtr
->fsState
;
3154 if (lpTbInfo
->dwMask
& TBIF_STYLE
)
3155 lpTbInfo
->fsStyle
= btnPtr
->fsStyle
;
3156 if (lpTbInfo
->dwMask
& TBIF_TEXT
) {
3157 /* TB_GETBUTTONINFO doesn't retrieve text from the string list, so we
3158 can't use TOOLBAR_GetText here */
3160 if (HIWORD(btnPtr
->iString
) && (btnPtr
->iString
!= -1)) {
3161 lpText
= (LPWSTR
)btnPtr
->iString
;
3162 Str_GetPtrWtoA (lpText
, lpTbInfo
->pszText
,lpTbInfo
->cchText
);
3164 lpTbInfo
->pszText
[0] = '\0';
3171 TOOLBAR_GetButtonInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3173 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3174 LPTBBUTTONINFOW lpTbInfo
= (LPTBBUTTONINFOW
)lParam
;
3175 TBUTTON_INFO
*btnPtr
;
3178 if (infoPtr
== NULL
)
3180 if (lpTbInfo
== NULL
)
3182 if (lpTbInfo
->cbSize
< sizeof(TBBUTTONINFOW
))
3185 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
3186 lpTbInfo
->dwMask
& 0x80000000);
3190 btnPtr
= &infoPtr
->buttons
[nIndex
];
3195 if (lpTbInfo
->dwMask
& TBIF_COMMAND
)
3196 lpTbInfo
->idCommand
= btnPtr
->idCommand
;
3197 if (lpTbInfo
->dwMask
& TBIF_IMAGE
)
3198 lpTbInfo
->iImage
= btnPtr
->iBitmap
;
3199 if (lpTbInfo
->dwMask
& TBIF_LPARAM
)
3200 lpTbInfo
->lParam
= btnPtr
->dwData
;
3201 if (lpTbInfo
->dwMask
& TBIF_SIZE
)
3202 lpTbInfo
->cx
= (WORD
)(btnPtr
->rect
.right
- btnPtr
->rect
.left
);
3203 if (lpTbInfo
->dwMask
& TBIF_STATE
)
3204 lpTbInfo
->fsState
= btnPtr
->fsState
;
3205 if (lpTbInfo
->dwMask
& TBIF_STYLE
)
3206 lpTbInfo
->fsStyle
= btnPtr
->fsStyle
;
3207 if (lpTbInfo
->dwMask
& TBIF_TEXT
) {
3208 /* TB_GETBUTTONINFO doesn't retrieve text from the string list, so we
3209 can't use TOOLBAR_GetText here */
3211 if (HIWORD(btnPtr
->iString
) && (btnPtr
->iString
!= -1)) {
3212 lpText
= (LPWSTR
)btnPtr
->iString
;
3213 Str_GetPtrW (lpText
,lpTbInfo
->pszText
,lpTbInfo
->cchText
);
3215 lpTbInfo
->pszText
[0] = '\0';
3223 TOOLBAR_GetButtonSize (HWND hwnd
)
3225 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3227 if (infoPtr
->nNumButtons
> 0)
3228 return MAKELONG((WORD
)infoPtr
->nButtonWidth
,
3229 (WORD
)infoPtr
->nButtonHeight
);
3231 return MAKELONG(8,7);
3236 TOOLBAR_GetButtonTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3238 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3245 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3249 lpText
= TOOLBAR_GetText(infoPtr
,&infoPtr
->buttons
[nIndex
]);
3251 return WideCharToMultiByte( CP_ACP
, 0, lpText
, -1,
3252 (LPSTR
)lParam
, 0x7fffffff, NULL
, NULL
) - 1;
3257 TOOLBAR_GetButtonTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3259 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3266 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3270 lpText
= TOOLBAR_GetText(infoPtr
,&infoPtr
->buttons
[nIndex
]);
3272 strcpyW ((LPWSTR
)lParam
, lpText
);
3274 return strlenW (lpText
);
3279 TOOLBAR_GetDisabledImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3281 return (LRESULT
)GETDISIMAGELIST(TOOLBAR_GetInfoPtr (hwnd
), 0);
3285 inline static LRESULT
3286 TOOLBAR_GetExtendedStyle (HWND hwnd
)
3288 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3292 return infoPtr
->dwExStyle
;
3297 TOOLBAR_GetHotImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3299 return (LRESULT
)GETHOTIMAGELIST(TOOLBAR_GetInfoPtr (hwnd
), 0);
3304 TOOLBAR_GetHotItem (HWND hwnd
)
3306 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3308 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_FLAT
))
3311 if (infoPtr
->nHotItem
< 0)
3314 return (LRESULT
)infoPtr
->nHotItem
;
3319 TOOLBAR_GetDefImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3321 return (LRESULT
) GETDEFIMAGELIST(TOOLBAR_GetInfoPtr(hwnd
), 0);
3325 /* << TOOLBAR_GetInsertMark >> */
3326 /* << TOOLBAR_GetInsertMarkColor >> */
3330 TOOLBAR_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3332 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3333 TBUTTON_INFO
*btnPtr
;
3337 if (infoPtr
== NULL
)
3339 nIndex
= (INT
)wParam
;
3340 btnPtr
= &infoPtr
->buttons
[nIndex
];
3341 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3343 lpRect
= (LPRECT
)lParam
;
3346 if (btnPtr
->fsState
& TBSTATE_HIDDEN
)
3349 lpRect
->left
= btnPtr
->rect
.left
;
3350 lpRect
->right
= btnPtr
->rect
.right
;
3351 lpRect
->bottom
= btnPtr
->rect
.bottom
;
3352 lpRect
->top
= btnPtr
->rect
.top
;
3359 TOOLBAR_GetMaxSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3361 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3362 LPSIZE lpSize
= (LPSIZE
)lParam
;
3367 lpSize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
3368 lpSize
->cy
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
3370 TRACE("maximum size %ld x %ld\n",
3371 infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
,
3372 infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
);
3378 /* << TOOLBAR_GetObject >> */
3382 TOOLBAR_GetPadding (HWND hwnd
)
3384 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3387 oldPad
= MAKELONG(infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
3388 return (LRESULT
) oldPad
;
3393 TOOLBAR_GetRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3395 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3396 TBUTTON_INFO
*btnPtr
;
3400 if (infoPtr
== NULL
)
3402 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3403 btnPtr
= &infoPtr
->buttons
[nIndex
];
3404 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
3406 lpRect
= (LPRECT
)lParam
;
3410 lpRect
->left
= btnPtr
->rect
.left
;
3411 lpRect
->right
= btnPtr
->rect
.right
;
3412 lpRect
->bottom
= btnPtr
->rect
.bottom
;
3413 lpRect
->top
= btnPtr
->rect
.top
;
3420 TOOLBAR_GetRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3422 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3424 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_WRAPABLE
)
3425 return infoPtr
->nRows
;
3432 TOOLBAR_GetState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3434 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3437 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3441 return infoPtr
->buttons
[nIndex
].fsState
;
3446 TOOLBAR_GetStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3448 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3451 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3455 return infoPtr
->buttons
[nIndex
].fsStyle
;
3460 TOOLBAR_GetTextRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3462 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3464 if (infoPtr
== NULL
)
3467 return infoPtr
->nMaxTextRows
;
3472 TOOLBAR_GetToolTips (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3474 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3476 if (infoPtr
== NULL
)
3478 return (LRESULT
)infoPtr
->hwndToolTip
;
3483 TOOLBAR_GetUnicodeFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3485 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3487 TRACE("%s hwnd=%p stub!\n",
3488 infoPtr
->bUnicode
? "TRUE" : "FALSE", hwnd
);
3490 return infoPtr
->bUnicode
;
3494 inline static LRESULT
3495 TOOLBAR_GetVersion (HWND hwnd
)
3497 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3498 return infoPtr
->iVersion
;
3503 TOOLBAR_HideButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3505 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3506 TBUTTON_INFO
*btnPtr
;
3511 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3515 btnPtr
= &infoPtr
->buttons
[nIndex
];
3516 if (LOWORD(lParam
) == FALSE
)
3517 btnPtr
->fsState
&= ~TBSTATE_HIDDEN
;
3519 btnPtr
->fsState
|= TBSTATE_HIDDEN
;
3521 TOOLBAR_CalcToolbar (hwnd
);
3523 InvalidateRect (hwnd
, NULL
, TRUE
);
3529 inline static LRESULT
3530 TOOLBAR_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3532 return TOOLBAR_InternalHitTest (hwnd
, (LPPOINT
)lParam
);
3537 TOOLBAR_Indeterminate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3539 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3540 TBUTTON_INFO
*btnPtr
;
3543 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3547 btnPtr
= &infoPtr
->buttons
[nIndex
];
3548 if (LOWORD(lParam
) == FALSE
)
3549 btnPtr
->fsState
&= ~TBSTATE_INDETERMINATE
;
3551 btnPtr
->fsState
|= TBSTATE_INDETERMINATE
;
3553 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
3560 TOOLBAR_InsertButtonA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3562 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3563 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3564 INT nIndex
= (INT
)wParam
;
3565 TBUTTON_INFO
*oldButtons
;
3570 TOOLBAR_DumpButton(infoPtr
, (TBUTTON_INFO
*)lpTbb
, nIndex
, FALSE
);
3573 /* EPP: this seems to be an undocumented call (from my IE4)
3574 * I assume in that case that:
3575 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3576 * - index of insertion is at the end of existing buttons
3577 * I only see this happen with nIndex == -1, but it could have a special
3578 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3580 nIndex
= infoPtr
->nNumButtons
;
3582 } else if (nIndex
< 0)
3585 /* If the string passed is not an index, assume address of string
3586 and do our own AddString */
3587 if ((HIWORD(lpTbb
->iString
) != 0) && (lpTbb
->iString
!= -1)) {
3591 TRACE("string %s passed instead of index, adding string\n",
3592 debugstr_a((LPSTR
)lpTbb
->iString
));
3593 len
= strlen((LPSTR
)lpTbb
->iString
) + 2;
3595 strcpy(ptr
, (LPSTR
)lpTbb
->iString
);
3596 ptr
[len
- 1] = 0; /* ended by two '\0' */
3597 lpTbb
->iString
= TOOLBAR_AddStringA(hwnd
, 0, (LPARAM
)ptr
);
3601 TRACE("inserting button index=%d\n", nIndex
);
3602 if (nIndex
> infoPtr
->nNumButtons
) {
3603 nIndex
= infoPtr
->nNumButtons
;
3604 TRACE("adjust index=%d\n", nIndex
);
3607 oldButtons
= infoPtr
->buttons
;
3608 infoPtr
->nNumButtons
++;
3609 infoPtr
->buttons
= Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
3610 /* pre insert copy */
3612 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
3613 nIndex
* sizeof(TBUTTON_INFO
));
3616 /* insert new button */
3617 infoPtr
->buttons
[nIndex
].iBitmap
= lpTbb
->iBitmap
;
3618 infoPtr
->buttons
[nIndex
].idCommand
= lpTbb
->idCommand
;
3619 infoPtr
->buttons
[nIndex
].fsState
= lpTbb
->fsState
;
3620 infoPtr
->buttons
[nIndex
].fsStyle
= lpTbb
->fsStyle
;
3621 infoPtr
->buttons
[nIndex
].dwData
= lpTbb
->dwData
;
3622 /* if passed string and not index, then add string */
3623 if(HIWORD(lpTbb
->iString
) && lpTbb
->iString
!=-1) {
3624 Str_SetPtrAtoW ((LPWSTR
*)&infoPtr
->buttons
[nIndex
].iString
, (LPCSTR
)lpTbb
->iString
);
3627 infoPtr
->buttons
[nIndex
].iString
= lpTbb
->iString
;
3629 if ((infoPtr
->hwndToolTip
) && !(lpTbb
->fsStyle
& BTNS_SEP
)) {
3632 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
3633 ti
.cbSize
= sizeof (TTTOOLINFOA
);
3635 ti
.uId
= lpTbb
->idCommand
;
3637 ti
.lpszText
= LPSTR_TEXTCALLBACKA
;
3639 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
,
3643 /* post insert copy */
3644 if (nIndex
< infoPtr
->nNumButtons
- 1) {
3645 memcpy (&infoPtr
->buttons
[nIndex
+1], &oldButtons
[nIndex
],
3646 (infoPtr
->nNumButtons
- nIndex
- 1) * sizeof(TBUTTON_INFO
));
3651 TOOLBAR_CalcToolbar (hwnd
);
3653 InvalidateRect (hwnd
, NULL
, TRUE
);
3660 TOOLBAR_InsertButtonW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3662 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3663 LPTBBUTTON lpTbb
= (LPTBBUTTON
)lParam
;
3664 INT nIndex
= (INT
)wParam
;
3665 TBUTTON_INFO
*oldButtons
;
3670 TOOLBAR_DumpButton(infoPtr
, (TBUTTON_INFO
*)lpTbb
, nIndex
, FALSE
);
3673 /* EPP: this seems to be an undocumented call (from my IE4)
3674 * I assume in that case that:
3675 * - lpTbb->iString is a string pointer (not a string index in strings[] table
3676 * - index of insertion is at the end of existing buttons
3677 * I only see this happen with nIndex == -1, but it could have a special
3678 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3680 nIndex
= infoPtr
->nNumButtons
;
3682 } else if (nIndex
< 0)
3685 /* If the string passed is not an index, assume address of string
3686 and do our own AddString */
3687 if ((HIWORD(lpTbb
->iString
) != 0) && (lpTbb
->iString
!= -1)) {
3691 TRACE("string %s passed instead of index, adding string\n",
3692 debugstr_w((LPWSTR
)lpTbb
->iString
));
3693 len
= strlenW((LPWSTR
)lpTbb
->iString
) + 2;
3694 ptr
= Alloc(len
*sizeof(WCHAR
));
3695 strcpyW(ptr
, (LPWSTR
)lpTbb
->iString
);
3696 ptr
[len
- 1] = 0; /* ended by two '\0' */
3697 lpTbb
->iString
= TOOLBAR_AddStringW(hwnd
, 0, (LPARAM
)ptr
);
3701 TRACE("inserting button index=%d\n", nIndex
);
3702 if (nIndex
> infoPtr
->nNumButtons
) {
3703 nIndex
= infoPtr
->nNumButtons
;
3704 TRACE("adjust index=%d\n", nIndex
);
3707 oldButtons
= infoPtr
->buttons
;
3708 infoPtr
->nNumButtons
++;
3709 infoPtr
->buttons
= Alloc (sizeof (TBUTTON_INFO
) * infoPtr
->nNumButtons
);
3710 /* pre insert copy */
3712 memcpy (&infoPtr
->buttons
[0], &oldButtons
[0],
3713 nIndex
* sizeof(TBUTTON_INFO
));
3716 /* insert new button */
3717 infoPtr
->buttons
[nIndex
].iBitmap
= lpTbb
->iBitmap
;
3718 infoPtr
->buttons
[nIndex
].idCommand
= lpTbb
->idCommand
;
3719 infoPtr
->buttons
[nIndex
].fsState
= lpTbb
->fsState
;
3720 infoPtr
->buttons
[nIndex
].fsStyle
= lpTbb
->fsStyle
;
3721 infoPtr
->buttons
[nIndex
].dwData
= lpTbb
->dwData
;
3722 /* if passed string and not index, then add string */
3723 if(HIWORD(lpTbb
->iString
) && lpTbb
->iString
!=-1) {
3724 Str_SetPtrW ((LPWSTR
*)&infoPtr
->buttons
[nIndex
].iString
, (LPWSTR
)lpTbb
->iString
);
3727 infoPtr
->buttons
[nIndex
].iString
= lpTbb
->iString
;
3729 if ((infoPtr
->hwndToolTip
) && !(lpTbb
->fsStyle
& BTNS_SEP
)) {
3732 ZeroMemory (&ti
, sizeof(TTTOOLINFOW
));
3733 ti
.cbSize
= sizeof (TTTOOLINFOW
);
3735 ti
.uId
= lpTbb
->idCommand
;
3737 ti
.lpszText
= LPSTR_TEXTCALLBACKW
;
3739 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
,
3743 /* post insert copy */
3744 if (nIndex
< infoPtr
->nNumButtons
- 1) {
3745 memcpy (&infoPtr
->buttons
[nIndex
+1], &oldButtons
[nIndex
],
3746 (infoPtr
->nNumButtons
- nIndex
- 1) * sizeof(TBUTTON_INFO
));
3751 TOOLBAR_CalcToolbar (hwnd
);
3753 InvalidateRect (hwnd
, NULL
, TRUE
);
3759 /* << TOOLBAR_InsertMarkHitTest >> */
3763 TOOLBAR_IsButtonChecked (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3765 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3768 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3772 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_CHECKED
);
3777 TOOLBAR_IsButtonEnabled (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3779 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3782 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3786 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_ENABLED
);
3791 TOOLBAR_IsButtonHidden (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3793 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3796 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3800 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_HIDDEN
);
3805 TOOLBAR_IsButtonHighlighted (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3807 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3810 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3814 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_MARKED
);
3819 TOOLBAR_IsButtonIndeterminate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3821 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3824 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3828 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_INDETERMINATE
);
3833 TOOLBAR_IsButtonPressed (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3835 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3838 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3842 return (infoPtr
->buttons
[nIndex
].fsState
& TBSTATE_PRESSED
);
3846 /* << TOOLBAR_LoadImages >> */
3847 /* << TOOLBAR_MapAccelerator >> */
3848 /* << TOOLBAR_MarkButton >> */
3849 /* << TOOLBAR_MoveButton >> */
3853 TOOLBAR_PressButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3855 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3856 TBUTTON_INFO
*btnPtr
;
3859 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
3863 btnPtr
= &infoPtr
->buttons
[nIndex
];
3864 if (LOWORD(lParam
) == FALSE
)
3865 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
3867 btnPtr
->fsState
|= TBSTATE_PRESSED
;
3869 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
3874 /* FIXME: there might still be some confusion her between number of buttons
3875 * and number of bitmaps */
3877 TOOLBAR_ReplaceBitmap (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3879 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3880 LPTBREPLACEBITMAP lpReplace
= (LPTBREPLACEBITMAP
) lParam
;
3882 int i
= 0, nOldButtons
= 0, pos
= 0;
3883 int nOldBitmaps
, nNewBitmaps
;
3884 HIMAGELIST himlDef
= 0;
3886 TRACE("hInstOld %p nIDOld %x hInstNew %p nIDNew %x nButtons %x\n",
3887 lpReplace
->hInstOld
, lpReplace
->nIDOld
, lpReplace
->hInstNew
, lpReplace
->nIDNew
,
3888 lpReplace
->nButtons
);
3890 if (lpReplace
->hInstOld
== HINST_COMMCTRL
)
3892 FIXME("changing standard bitmaps not implemented\n");
3895 else if (lpReplace
->hInstOld
!= 0)
3897 FIXME("resources not in the current module not implemented\n");
3902 hBitmap
= (HBITMAP
) lpReplace
->nIDNew
;
3905 TRACE("To be replaced hInstOld %p nIDOld %x\n", lpReplace
->hInstOld
, lpReplace
->nIDOld
);
3906 for (i
= 0; i
< infoPtr
->nNumBitmapInfos
; i
++) {
3907 TBITMAP_INFO
*tbi
= &infoPtr
->bitmaps
[i
];
3908 TRACE("tbimapinfo %d hInstOld %p nIDOld %x\n", i
, tbi
->hInst
, tbi
->nID
);
3909 if (tbi
->hInst
== lpReplace
->hInstOld
&& tbi
->nID
== lpReplace
->nIDOld
)
3911 TRACE("Found: nButtons %d hInst %p nID %x\n", tbi
->nButtons
, tbi
->hInst
, tbi
->nID
);
3912 nOldButtons
= tbi
->nButtons
;
3913 tbi
->nButtons
= lpReplace
->nButtons
;
3914 tbi
->hInst
= lpReplace
->hInstNew
;
3915 tbi
->nID
= lpReplace
->nIDNew
;
3916 TRACE("tbimapinfo changed %d hInstOld %p nIDOld %x\n", i
, tbi
->hInst
, tbi
->nID
);
3919 pos
+= tbi
->nButtons
;
3922 if (nOldButtons
== 0)
3924 WARN("No hinst/bitmap found! hInst %p nID %x\n", lpReplace
->hInstOld
, lpReplace
->nIDOld
);
3928 himlDef
= GETDEFIMAGELIST(infoPtr
, 0); /* fixme: correct? */
3929 nOldBitmaps
= ImageList_GetImageCount(himlDef
);
3931 /* ImageList_Replace(GETDEFIMAGELIST(), pos, hBitmap, NULL); */
3933 for (i
= pos
+ nOldBitmaps
- 1; i
>= pos
; i
--)
3934 ImageList_Remove(himlDef
, i
);
3938 HBITMAP hOldBitmapBitmap
, hOldBitmapLoad
, hbmLoad
;
3939 HDC hdcImage
, hdcBitmap
;
3941 /* copy the bitmap before adding it so that the user's bitmap
3942 * doesn't get modified.
3944 GetObjectA (hBitmap
, sizeof(BITMAP
), (LPVOID
)&bmp
);
3946 hdcImage
= CreateCompatibleDC(0);
3947 hdcBitmap
= CreateCompatibleDC(0);
3949 /* create new bitmap */
3950 hbmLoad
= CreateBitmap (bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
, bmp
.bmBitsPixel
, NULL
);
3951 hOldBitmapBitmap
= SelectObject(hdcBitmap
, hBitmap
);
3952 hOldBitmapLoad
= SelectObject(hdcImage
, hbmLoad
);
3954 /* Copy the user's image */
3955 BitBlt (hdcImage
, 0, 0, bmp
.bmWidth
, bmp
.bmHeight
,
3956 hdcBitmap
, 0, 0, SRCCOPY
);
3958 SelectObject (hdcImage
, hOldBitmapLoad
);
3959 SelectObject (hdcBitmap
, hOldBitmapBitmap
);
3960 DeleteDC (hdcImage
);
3961 DeleteDC (hdcBitmap
);
3963 ImageList_AddMasked (himlDef
, hbmLoad
, comctl32_color
.clrBtnFace
);
3964 nNewBitmaps
= ImageList_GetImageCount(himlDef
);
3965 DeleteObject (hbmLoad
);
3968 infoPtr
->nNumBitmaps
= infoPtr
->nNumBitmaps
- nOldBitmaps
+ nNewBitmaps
;
3970 TRACE(" pos %d %d old bitmaps replaced by %d new ones.\n",
3971 pos
, nOldBitmaps
, nNewBitmaps
);
3973 InvalidateRect(hwnd
, NULL
, FALSE
);
3979 TOOLBAR_SaveRestoreA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3982 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
3983 LPTBSAVEPARAMSA lpSave
= (LPTBSAVEPARAMSA
)lParam
;
3985 if (lpSave
== NULL
) return 0;
3988 /* save toolbar information */
3989 FIXME("save to \"%s\" \"%s\"\n",
3990 lpSave
->pszSubKey
, lpSave
->pszValueName
);
3995 /* restore toolbar information */
3997 FIXME("restore from \"%s\" \"%s\"\n",
3998 lpSave
->pszSubKey
, lpSave
->pszValueName
);
4009 TOOLBAR_SaveRestoreW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4012 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4013 LPTBSAVEPARAMSW lpSave
= (LPTBSAVEPARAMSW
)lParam
;
4019 /* save toolbar information */
4020 FIXME("save to \"%s\" \"%s\"\n",
4021 lpSave
->pszSubKey
, lpSave
->pszValueName
);
4026 /* restore toolbar information */
4028 FIXME("restore from \"%s\" \"%s\"\n",
4029 lpSave
->pszSubKey
, lpSave
->pszValueName
);
4040 TOOLBAR_SetAnchorHighlight (HWND hwnd
, WPARAM wParam
)
4042 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4043 BOOL bOldAnchor
= infoPtr
->bAnchor
;
4045 infoPtr
->bAnchor
= (BOOL
)wParam
;
4047 return (LRESULT
)bOldAnchor
;
4052 TOOLBAR_SetBitmapSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4054 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4055 HIMAGELIST himlDef
= GETDEFIMAGELIST(infoPtr
, 0);
4057 if ((LOWORD(lParam
) <= 0) || (HIWORD(lParam
)<=0))
4060 if (infoPtr
->nNumButtons
> 0)
4061 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
4062 infoPtr
->nNumButtons
,
4063 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
,
4064 LOWORD(lParam
), HIWORD(lParam
));
4066 infoPtr
->nBitmapWidth
= (INT
)LOWORD(lParam
);
4067 infoPtr
->nBitmapHeight
= (INT
)HIWORD(lParam
);
4070 /* uses image list internals directly */
4072 himlDef
->cx
= infoPtr
->nBitmapWidth
;
4073 himlDef
->cy
= infoPtr
->nBitmapHeight
;
4081 TOOLBAR_SetButtonInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4083 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4084 LPTBBUTTONINFOA lptbbi
= (LPTBBUTTONINFOA
)lParam
;
4085 TBUTTON_INFO
*btnPtr
;
4090 if (lptbbi
->cbSize
< sizeof(TBBUTTONINFOA
))
4093 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
4094 lptbbi
->dwMask
& 0x80000000);
4098 btnPtr
= &infoPtr
->buttons
[nIndex
];
4099 if (lptbbi
->dwMask
& TBIF_COMMAND
)
4100 btnPtr
->idCommand
= lptbbi
->idCommand
;
4101 if (lptbbi
->dwMask
& TBIF_IMAGE
)
4102 btnPtr
->iBitmap
= lptbbi
->iImage
;
4103 if (lptbbi
->dwMask
& TBIF_LPARAM
)
4104 btnPtr
->dwData
= lptbbi
->lParam
;
4105 /* if (lptbbi->dwMask & TBIF_SIZE) */
4106 /* btnPtr->cx = lptbbi->cx; */
4107 if (lptbbi
->dwMask
& TBIF_STATE
)
4108 btnPtr
->fsState
= lptbbi
->fsState
;
4109 if (lptbbi
->dwMask
& TBIF_STYLE
)
4110 btnPtr
->fsStyle
= lptbbi
->fsStyle
;
4112 if ((lptbbi
->dwMask
& TBIF_TEXT
) && ((INT
)lptbbi
->pszText
!= -1)) {
4113 if ((HIWORD(btnPtr
->iString
) == 0) || (btnPtr
->iString
== -1))
4114 /* iString is index, zero it to make Str_SetPtr succeed */
4117 Str_SetPtrAtoW ((LPWSTR
*)&btnPtr
->iString
, lptbbi
->pszText
);
4124 TOOLBAR_SetButtonInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4126 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4127 LPTBBUTTONINFOW lptbbi
= (LPTBBUTTONINFOW
)lParam
;
4128 TBUTTON_INFO
*btnPtr
;
4133 if (lptbbi
->cbSize
< sizeof(TBBUTTONINFOW
))
4136 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
,
4137 lptbbi
->dwMask
& 0x80000000);
4141 btnPtr
= &infoPtr
->buttons
[nIndex
];
4142 if (lptbbi
->dwMask
& TBIF_COMMAND
)
4143 btnPtr
->idCommand
= lptbbi
->idCommand
;
4144 if (lptbbi
->dwMask
& TBIF_IMAGE
)
4145 btnPtr
->iBitmap
= lptbbi
->iImage
;
4146 if (lptbbi
->dwMask
& TBIF_LPARAM
)
4147 btnPtr
->dwData
= lptbbi
->lParam
;
4148 /* if (lptbbi->dwMask & TBIF_SIZE) */
4149 /* btnPtr->cx = lptbbi->cx; */
4150 if (lptbbi
->dwMask
& TBIF_STATE
)
4151 btnPtr
->fsState
= lptbbi
->fsState
;
4152 if (lptbbi
->dwMask
& TBIF_STYLE
)
4153 btnPtr
->fsStyle
= lptbbi
->fsStyle
;
4155 if ((lptbbi
->dwMask
& TBIF_TEXT
) && ((INT
)lptbbi
->pszText
!= -1)) {
4156 if ((HIWORD(btnPtr
->iString
) == 0) || (btnPtr
->iString
== -1))
4157 /* iString is index, zero it to make Str_SetPtr succeed */
4159 Str_SetPtrW ((LPWSTR
*)&btnPtr
->iString
, lptbbi
->pszText
);
4166 TOOLBAR_SetButtonSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4168 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4169 INT cx
= LOWORD(lParam
), cy
= HIWORD(lParam
);
4171 if ((cx
< 0) || (cy
< 0))
4173 ERR("invalid parameter 0x%08lx\n", (DWORD
)lParam
);
4177 /* The documentation claims you can only change the button size before
4178 * any button has been added. But this is wrong.
4179 * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding
4180 * it to the toolbar, and it checks that the return value is nonzero - mjm
4181 * Further testing shows that we must actually perform the change too.
4184 * The documentation also does not mention that if 0 is supplied for
4185 * either size, the system changes it to the default of 24 wide and
4186 * 22 high. Demonstarted in ControlSpy Toolbar. GLA 3/02
4188 infoPtr
->nButtonWidth
= (cx
) ? cx
: 24;
4189 infoPtr
->nButtonHeight
= (cy
) ? cy
: 22;
4195 TOOLBAR_SetButtonWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4197 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4199 if (infoPtr
== NULL
) {
4200 TRACE("Toolbar not initialized yet?????\n");
4204 /* if setting to current values, ignore */
4205 if ((infoPtr
->cxMin
== (INT
)LOWORD(lParam
)) &&
4206 (infoPtr
->cxMax
== (INT
)HIWORD(lParam
))) {
4207 TRACE("matches current width, min=%d, max=%d, no recalc\n",
4208 infoPtr
->cxMin
, infoPtr
->cxMax
);
4212 /* save new values */
4213 infoPtr
->cxMin
= (INT
)LOWORD(lParam
);
4214 infoPtr
->cxMax
= (INT
)HIWORD(lParam
);
4216 /* if both values are 0 then we are done */
4218 TRACE("setting both min and max to 0, norecalc\n");
4222 /* otherwise we need to recalc the toolbar and in some cases
4223 recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
4224 which doesn't actually draw - GA). */
4225 TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n",
4226 infoPtr
->nNumButtons
, infoPtr
->cxMin
, infoPtr
->cxMax
);
4228 TOOLBAR_CalcToolbar (hwnd
);
4230 InvalidateRect (hwnd
, NULL
, TRUE
);
4237 TOOLBAR_SetCmdId (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4239 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4240 INT nIndex
= (INT
)wParam
;
4242 if ((nIndex
< 0) || (nIndex
>= infoPtr
->nNumButtons
))
4245 infoPtr
->buttons
[nIndex
].idCommand
= (INT
)lParam
;
4247 if (infoPtr
->hwndToolTip
) {
4249 FIXME("change tool tip!\n");
4258 TOOLBAR_SetDisabledImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4260 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4261 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4262 HIMAGELIST himlTemp
;
4265 if (infoPtr
->iVersion
>= 5)
4268 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlDis
,
4269 &infoPtr
->cimlDis
, himl
, id
);
4271 /* FIXME: redraw ? */
4273 return (LRESULT
)himlTemp
;
4278 TOOLBAR_SetDrawTextFlags (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4280 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4283 dwTemp
= infoPtr
->dwDTFlags
;
4284 infoPtr
->dwDTFlags
=
4285 (infoPtr
->dwDTFlags
& (DWORD
)wParam
) | (DWORD
)lParam
;
4287 return (LRESULT
)dwTemp
;
4291 TOOLBAR_SetExtendedStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4293 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4296 dwTemp
= infoPtr
->dwExStyle
;
4297 infoPtr
->dwExStyle
|= (DWORD
)lParam
;
4299 TRACE("new style 0x%08lx\n", infoPtr
->dwExStyle
);
4301 if (infoPtr
->dwExStyle
& ~TBSTYLE_EX_ALL
)
4302 FIXME("Unknown Toolbar Extended Style 0x%08lx. Please report.\n",
4303 (infoPtr
->dwExStyle
& ~TBSTYLE_EX_ALL
));
4305 TOOLBAR_CalcToolbar (hwnd
);
4307 TOOLBAR_AutoSize(hwnd
);
4309 InvalidateRect(hwnd
, NULL
, FALSE
);
4311 return (LRESULT
)dwTemp
;
4316 TOOLBAR_SetHotImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4318 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4319 HIMAGELIST himlTemp
;
4320 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4323 if (infoPtr
->iVersion
>= 5)
4326 TRACE("hwnd = %p, himl = %p, id = %d\n", hwnd
, himl
, id
);
4328 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlHot
,
4329 &infoPtr
->cimlHot
, himl
, id
);
4331 /* FIXME: redraw ? */
4333 return (LRESULT
)himlTemp
;
4338 TOOLBAR_SetHotItem (HWND hwnd
, WPARAM wParam
)
4340 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4341 INT nOldHotItem
= infoPtr
->nHotItem
;
4342 TBUTTON_INFO
*btnPtr
;
4344 if ((INT
) wParam
< 0 || (INT
)wParam
> infoPtr
->nNumButtons
)
4347 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TBSTYLE_FLAT
)
4350 infoPtr
->nHotItem
= (INT
)wParam
;
4351 if ((INT
)wParam
>=0)
4353 btnPtr
= &infoPtr
->buttons
[(INT
)wParam
];
4354 btnPtr
->bHot
= TRUE
;
4355 InvalidateRect (hwnd
, &btnPtr
->rect
,
4356 TOOLBAR_HasText(infoPtr
, btnPtr
));
4360 btnPtr
= &infoPtr
->buttons
[nOldHotItem
];
4361 btnPtr
->bHot
= FALSE
;
4362 InvalidateRect (hwnd
, &btnPtr
->rect
,
4363 TOOLBAR_HasText(infoPtr
, btnPtr
));
4367 if (nOldHotItem
< 0)
4370 return (LRESULT
)nOldHotItem
;
4375 TOOLBAR_SetImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4377 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4378 HIMAGELIST himlTemp
;
4379 HIMAGELIST himl
= (HIMAGELIST
)lParam
;
4382 if (infoPtr
->iVersion
>= 5)
4385 himlTemp
= TOOLBAR_InsertImageList(&infoPtr
->himlDef
,
4386 &infoPtr
->cimlDef
, himl
, id
);
4388 infoPtr
->nNumBitmaps
= 0;
4389 for (i
= 0; i
< infoPtr
->cimlDef
; i
++)
4390 infoPtr
->nNumBitmaps
+= ImageList_GetImageCount(infoPtr
->himlDef
[i
]->himl
);
4392 ImageList_GetIconSize(himl
, &infoPtr
->nBitmapWidth
,
4393 &infoPtr
->nBitmapHeight
);
4394 TRACE("hwnd %p, new himl=%08x, count=%d, bitmap w=%d, h=%d\n",
4395 hwnd
, (INT
)infoPtr
->himlDef
, infoPtr
->nNumBitmaps
,
4396 infoPtr
->nBitmapWidth
, infoPtr
->nBitmapHeight
);
4398 /* FIXME: redraw ? */
4399 InvalidateRect(hwnd
, NULL
, TRUE
);
4401 return (LRESULT
)himlTemp
;
4406 TOOLBAR_SetIndent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4408 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4410 infoPtr
->nIndent
= (INT
)wParam
;
4414 /* process only on indent changing */
4415 if(infoPtr
->nIndent
!= (INT
)wParam
)
4417 infoPtr
->nIndent
= (INT
)wParam
;
4418 TOOLBAR_CalcToolbar (hwnd
);
4419 InvalidateRect(hwnd
, NULL
, FALSE
);
4426 /* << TOOLBAR_SetInsertMark >> */
4430 TOOLBAR_SetInsertMarkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4432 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4434 infoPtr
->clrInsertMark
= (COLORREF
)lParam
;
4436 /* FIXME : redraw ??*/
4443 TOOLBAR_SetMaxTextRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4445 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4447 if (infoPtr
== NULL
)
4450 infoPtr
->nMaxTextRows
= (INT
)wParam
;
4457 TOOLBAR_SetPadding (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4459 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4462 oldPad
= MAKELONG(infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
4463 infoPtr
->szPadding
.cx
= LOWORD((DWORD
)lParam
);
4464 infoPtr
->szPadding
.cy
= HIWORD((DWORD
)lParam
);
4465 FIXME("stub - nothing done with values, cx=%ld, cy=%ld\n",
4466 infoPtr
->szPadding
.cx
, infoPtr
->szPadding
.cy
);
4467 return (LRESULT
) oldPad
;
4472 TOOLBAR_SetParent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4474 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4479 if (infoPtr
== NULL
)
4481 hwndOldNotify
= infoPtr
->hwndNotify
;
4482 infoPtr
->hwndNotify
= (HWND
)wParam
;
4484 return (LRESULT
)hwndOldNotify
;
4489 TOOLBAR_SetRows (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4491 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4492 LPRECT lprc
= (LPRECT
)lParam
;
4496 if (LOWORD(wParam
) > 1) {
4497 FIXME("multiple rows not supported!\n");
4500 if(infoPtr
->nRows
!= LOWORD(wParam
))
4502 infoPtr
->nRows
= LOWORD(wParam
);
4504 /* recalculate toolbar */
4505 TOOLBAR_CalcToolbar (hwnd
);
4507 /* repaint toolbar */
4508 InvalidateRect(hwnd
, NULL
, FALSE
);
4511 /* return bounding rectangle */
4513 lprc
->left
= infoPtr
->rcBound
.left
;
4514 lprc
->right
= infoPtr
->rcBound
.right
;
4515 lprc
->top
= infoPtr
->rcBound
.top
;
4516 lprc
->bottom
= infoPtr
->rcBound
.bottom
;
4524 TOOLBAR_SetState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4526 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4527 TBUTTON_INFO
*btnPtr
;
4530 nIndex
= TOOLBAR_GetButtonIndex (infoPtr
, (INT
)wParam
, FALSE
);
4534 btnPtr
= &infoPtr
->buttons
[nIndex
];
4536 /* if hidden state has changed the invalidate entire window and recalc */
4537 if ((btnPtr
->fsState
& TBSTATE_HIDDEN
) != (LOWORD(lParam
) & TBSTATE_HIDDEN
)) {
4538 btnPtr
->fsState
= LOWORD(lParam
);
4539 TOOLBAR_CalcToolbar (hwnd
);
4540 InvalidateRect(hwnd
, 0, TOOLBAR_HasText(infoPtr
, btnPtr
));
4544 /* process state changing if current state doesn't match new state */
4545 if(btnPtr
->fsState
!= LOWORD(lParam
))
4547 btnPtr
->fsState
= LOWORD(lParam
);
4548 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
4557 TOOLBAR_SetStyle (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4559 SetWindowLongW(hwnd
, GWL_STYLE
, lParam
);
4565 inline static LRESULT
4566 TOOLBAR_SetToolTips (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4568 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4570 if (infoPtr
== NULL
)
4572 infoPtr
->hwndToolTip
= (HWND
)wParam
;
4578 TOOLBAR_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4580 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4583 TRACE("%s hwnd=%p stub!\n",
4584 ((BOOL
)wParam
) ? "TRUE" : "FALSE", hwnd
);
4586 bTemp
= infoPtr
->bUnicode
;
4587 infoPtr
->bUnicode
= (BOOL
)wParam
;
4594 TOOLBAR_GetColorScheme (HWND hwnd
, LPCOLORSCHEME lParam
)
4596 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4598 lParam
->clrBtnHighlight
= (infoPtr
->clrBtnHighlight
== CLR_DEFAULT
) ?
4599 comctl32_color
.clrBtnHighlight
:
4600 infoPtr
->clrBtnHighlight
;
4601 lParam
->clrBtnShadow
= (infoPtr
->clrBtnShadow
== CLR_DEFAULT
) ?
4602 comctl32_color
.clrBtnShadow
: infoPtr
->clrBtnShadow
;
4608 TOOLBAR_SetColorScheme (HWND hwnd
, LPCOLORSCHEME lParam
)
4610 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4612 TRACE("new colors Hl=%lx Shd=%lx, old colors Hl=%lx Shd=%lx\n",
4613 lParam
->clrBtnHighlight
, lParam
->clrBtnShadow
,
4614 infoPtr
->clrBtnHighlight
, infoPtr
->clrBtnShadow
);
4616 infoPtr
->clrBtnHighlight
= lParam
->clrBtnHighlight
;
4617 infoPtr
->clrBtnShadow
= lParam
->clrBtnShadow
;
4618 InvalidateRect(hwnd
, 0, 0);
4624 TOOLBAR_SetVersion (HWND hwnd
, INT iVersion
)
4626 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4627 INT iOldVersion
= infoPtr
->iVersion
;
4629 infoPtr
->iVersion
= iVersion
;
4631 if (infoPtr
->iVersion
>= 5)
4632 TOOLBAR_SetUnicodeFormat(hwnd
, (WPARAM
)TRUE
, (LPARAM
)0);
4638 /*********************************************************************/
4640 /* This is undocumented and appears to be a "Super" TB_SETHOTITEM */
4641 /* without the restriction of TBSTYLE_FLAT. This implementation is */
4642 /* based on relay traces of the native control and IE 5.5 */
4644 /*********************************************************************/
4646 TOOLBAR_Unkwn45E (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4648 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
4649 INT nOldHotItem
= infoPtr
->nHotItem
;
4650 TBUTTON_INFO
*btnPtr
;
4652 NMTBHOTITEM nmhotitem
;
4654 if ((INT
) wParam
< 0 || (INT
)wParam
> infoPtr
->nNumButtons
)
4657 infoPtr
->nHotItem
= (INT
)wParam
;
4658 if (nOldHotItem
!= infoPtr
->nHotItem
) {
4659 nmhotitem
.dwFlags
= (DWORD
)lParam
;
4660 if ( !(nmhotitem
.dwFlags
& HICF_ENTERING
) )
4661 nmhotitem
.idOld
= (nOldHotItem
>= 0) ?
4662 infoPtr
->buttons
[nOldHotItem
].idCommand
: 0;
4663 if ( !(nmhotitem
.dwFlags
& HICF_LEAVING
) )
4664 nmhotitem
.idNew
= (infoPtr
->nHotItem
>= 0) ?
4665 infoPtr
->buttons
[infoPtr
->nHotItem
].idCommand
: 0;
4666 no_hi
= TOOLBAR_SendNotify((NMHDR
*)&nmhotitem
, infoPtr
, TBN_HOTITEMCHANGE
);
4668 if ((INT
)wParam
>=0) {
4669 btnPtr
= &infoPtr
->buttons
[(INT
)wParam
];
4670 btnPtr
->bHot
= (no_hi
) ? FALSE
: TRUE
;
4671 InvalidateRect (hwnd
, &btnPtr
->rect
,
4672 TOOLBAR_HasText(infoPtr
, btnPtr
));
4674 if (nOldHotItem
>=0) {
4675 btnPtr
= &infoPtr
->buttons
[nOldHotItem
];
4676 btnPtr
->bHot
= FALSE
;
4677 InvalidateRect (hwnd
, &btnPtr
->rect
,
4678 TOOLBAR_HasText(infoPtr
, btnPtr
));
4681 TRACE("old item=%d, new item=%d, flags=%08lx, notify=%d\n",
4682 nOldHotItem
, infoPtr
->nHotItem
, (DWORD
)lParam
, no_hi
);
4684 if (nOldHotItem
< 0)
4687 return (LRESULT
)nOldHotItem
;
4692 TOOLBAR_Unkwn463 (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4694 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4695 LPSIZE lpsize
= (LPSIZE
)lParam
;
4701 * Testing shows the following:
4702 * wParam = 0 adjust cx value
4703 * = 1 set cy value to max size.
4704 * lParam pointer to SIZE structure
4707 TRACE("[0463] wParam %d, lParam 0x%08lx -> 0x%08lx 0x%08lx\n",
4708 wParam
, lParam
, lpsize
->cx
, lpsize
->cy
);
4712 if (lpsize
->cx
== -1) {
4713 /* **** this is wrong, native measures each button and sets it */
4714 lpsize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
4716 else if(HIWORD(lpsize
->cx
)) {
4718 HWND hwndParent
= GetParent(hwnd
);
4720 InvalidateRect(hwnd
, 0, 1);
4721 GetWindowRect(hwnd
, &rc
);
4722 MapWindowPoints(0, hwndParent
, (LPPOINT
)&rc
, 2);
4723 TRACE("mapped to (%ld,%ld)-(%ld,%ld)\n",
4724 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4725 lpsize
->cx
= max(rc
.right
-rc
.left
,
4726 infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
);
4729 lpsize
->cx
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
4733 lpsize
->cy
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
4734 /* lpsize->cy = infoPtr->nHeight; */
4737 ERR("Unknown wParam %d for Toolbar message [0463]. Please report\n",
4741 TRACE("[0463] set to -> 0x%08lx 0x%08lx\n",
4742 lpsize
->cx
, lpsize
->cy
);
4748 TOOLBAR_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4750 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4751 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
4754 /* initialize info structure */
4755 infoPtr
->nButtonHeight
= 22;
4756 infoPtr
->nButtonWidth
= 24;
4757 infoPtr
->nBitmapHeight
= 15;
4758 infoPtr
->nBitmapWidth
= 16;
4760 infoPtr
->nHeight
= infoPtr
->nButtonHeight
+ TOP_BORDER
+ BOTTOM_BORDER
;
4761 infoPtr
->nMaxTextRows
= 1;
4762 infoPtr
->cxMin
= -1;
4763 infoPtr
->cxMax
= -1;
4764 infoPtr
->nNumBitmaps
= 0;
4765 infoPtr
->nNumStrings
= 0;
4767 infoPtr
->bCaptured
= FALSE
;
4768 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
4769 infoPtr
->nButtonDown
= -1;
4770 infoPtr
->nOldHit
= -1;
4771 infoPtr
->nHotItem
= -2; /* It has to be initially different from nOldHit */
4772 infoPtr
->hwndNotify
= ((LPCREATESTRUCTW
)lParam
)->hwndParent
;
4773 infoPtr
->bTransparent
= (dwStyle
& TBSTYLE_TRANSPARENT
);
4774 infoPtr
->bBtnTranspnt
= (dwStyle
& (TBSTYLE_FLAT
| TBSTYLE_LIST
));
4775 infoPtr
->dwDTFlags
= (dwStyle
& TBSTYLE_LIST
) ? DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
: DT_CENTER
;
4776 infoPtr
->bAnchor
= FALSE
; /* no anchor highlighting */
4777 infoPtr
->iVersion
= 0;
4778 infoPtr
->hwndSelf
= hwnd
;
4779 infoPtr
->bDoRedraw
= TRUE
;
4780 infoPtr
->clrBtnHighlight
= CLR_DEFAULT
;
4781 infoPtr
->clrBtnShadow
= CLR_DEFAULT
;
4782 infoPtr
->szPadding
.cx
= 7;
4783 infoPtr
->szPadding
.cy
= 6;
4784 TOOLBAR_NotifyFormat(infoPtr
, (WPARAM
)hwnd
, (LPARAM
)NF_REQUERY
);
4786 SystemParametersInfoA (SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0);
4787 infoPtr
->hFont
= infoPtr
->hDefaultFont
= CreateFontIndirectA (&logFont
);
4789 if (dwStyle
& TBSTYLE_TOOLTIPS
) {
4790 /* Create tooltip control */
4791 infoPtr
->hwndToolTip
=
4792 CreateWindowExA (0, TOOLTIPS_CLASSA
, NULL
, 0,
4793 CW_USEDEFAULT
, CW_USEDEFAULT
,
4794 CW_USEDEFAULT
, CW_USEDEFAULT
,
4797 /* Send NM_TOOLTIPSCREATED notification */
4798 if (infoPtr
->hwndToolTip
) {
4799 NMTOOLTIPSCREATED nmttc
;
4801 nmttc
.hwndToolTips
= infoPtr
->hwndToolTip
;
4803 TOOLBAR_SendNotify ((NMHDR
*) &nmttc
, infoPtr
,
4804 NM_TOOLTIPSCREATED
);
4808 TOOLBAR_CheckStyle (hwnd
, dwStyle
);
4810 TOOLBAR_CalcToolbar(hwnd
);
4817 TOOLBAR_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4819 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4821 /* delete tooltip control */
4822 if (infoPtr
->hwndToolTip
)
4823 DestroyWindow (infoPtr
->hwndToolTip
);
4825 /* delete button data */
4826 if (infoPtr
->buttons
)
4827 Free (infoPtr
->buttons
);
4829 /* delete strings */
4830 if (infoPtr
->strings
) {
4832 for (i
= 0; i
< infoPtr
->nNumStrings
; i
++)
4833 if (infoPtr
->strings
[i
])
4834 Free (infoPtr
->strings
[i
]);
4836 Free (infoPtr
->strings
);
4839 /* destroy internal image list */
4840 if (infoPtr
->himlInt
)
4841 ImageList_Destroy (infoPtr
->himlInt
);
4843 TOOLBAR_DeleteImageList(&infoPtr
->himlDef
, &infoPtr
->cimlDef
);
4844 TOOLBAR_DeleteImageList(&infoPtr
->himlDis
, &infoPtr
->cimlDis
);
4845 TOOLBAR_DeleteImageList(&infoPtr
->himlHot
, &infoPtr
->cimlHot
);
4847 /* delete default font */
4849 DeleteObject (infoPtr
->hDefaultFont
);
4851 /* free toolbar info data */
4853 SetWindowLongA (hwnd
, 0, 0);
4860 TOOLBAR_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4862 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4863 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
4864 NMTBCUSTOMDRAW tbcd
;
4868 if (dwStyle
& TBSTYLE_CUSTOMERASE
) {
4869 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
4870 tbcd
.nmcd
.dwDrawStage
= CDDS_PREERASE
;
4871 tbcd
.nmcd
.hdc
= (HDC
)wParam
;
4872 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
4873 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
4875 /* FIXME: in general the return flags *can* be or'ed together */
4876 switch (infoPtr
->dwBaseCustDraw
)
4878 case CDRF_DODEFAULT
:
4880 case CDRF_SKIPDEFAULT
:
4883 FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4888 /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up
4889 * to my parent for processing.
4891 if (infoPtr
->bTransparent
) {
4893 HDC hdc
= (HDC
)wParam
;
4898 parent
= GetParent(hwnd
);
4899 MapWindowPoints(hwnd
, parent
, &pt
, 1);
4900 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
4901 ret
= SendMessageA (parent
, WM_ERASEBKGND
, wParam
, lParam
);
4902 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
4905 ret
= DefWindowProcA (hwnd
, WM_ERASEBKGND
, wParam
, lParam
);
4907 if ((dwStyle
& TBSTYLE_CUSTOMERASE
) &&
4908 (infoPtr
->dwBaseCustDraw
& CDRF_NOTIFYPOSTERASE
)) {
4909 ZeroMemory (&tbcd
, sizeof(NMTBCUSTOMDRAW
));
4910 tbcd
.nmcd
.dwDrawStage
= CDDS_POSTERASE
;
4911 tbcd
.nmcd
.hdc
= (HDC
)wParam
;
4912 ntfret
= TOOLBAR_SendNotify ((NMHDR
*)&tbcd
, infoPtr
, NM_CUSTOMDRAW
);
4913 infoPtr
->dwBaseCustDraw
= ntfret
& 0xffff;
4914 switch (infoPtr
->dwBaseCustDraw
)
4916 case CDRF_DODEFAULT
:
4918 case CDRF_SKIPDEFAULT
:
4921 FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4930 TOOLBAR_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4932 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4934 return (LRESULT
)infoPtr
->hFont
;
4939 TOOLBAR_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4941 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4942 TBUTTON_INFO
*btnPtr
;
4946 pt
.x
= (INT
)LOWORD(lParam
);
4947 pt
.y
= (INT
)HIWORD(lParam
);
4948 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
4951 btnPtr
= &infoPtr
->buttons
[nHit
];
4952 if (!(btnPtr
->fsState
& TBSTATE_ENABLED
))
4955 infoPtr
->bCaptured
= TRUE
;
4956 infoPtr
->nButtonDown
= nHit
;
4958 btnPtr
->fsState
|= TBSTATE_PRESSED
;
4960 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
4963 else if (GetWindowLongA (hwnd
, GWL_STYLE
) & CCS_ADJUSTABLE
)
4964 TOOLBAR_Customize (hwnd
);
4971 TOOLBAR_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
4973 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
4974 TBUTTON_INFO
*btnPtr
;
4979 if (infoPtr
->hwndToolTip
)
4980 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
4981 WM_LBUTTONDOWN
, wParam
, lParam
);
4983 pt
.x
= (INT
)LOWORD(lParam
);
4984 pt
.y
= (INT
)HIWORD(lParam
);
4985 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
4989 btnPtr
= &infoPtr
->buttons
[nHit
];
4990 infoPtr
->nOldHit
= nHit
;
4992 CopyRect(&arrowRect
, &btnPtr
->rect
);
4993 arrowRect
.left
= max(btnPtr
->rect
.left
, btnPtr
->rect
.right
- DDARROW_WIDTH
);
4995 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
4996 if ((btnPtr
->fsState
& TBSTATE_ENABLED
) && (btnPtr
->fsStyle
& BTNS_DROPDOWN
) &&
4997 ((TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
) && PtInRect(&arrowRect
, pt
)) ||
4998 (!TOOLBAR_HasDropDownArrows(infoPtr
->dwExStyle
))))
5002 * this time we must force a Redraw, so the btn is
5003 * painted down before CaptureChanged repaints it up
5005 RedrawWindow(hwnd
,&btnPtr
->rect
,0,
5006 RDW_ERASE
|RDW_INVALIDATE
|RDW_UPDATENOW
);
5008 nmtb
.iItem
= btnPtr
->idCommand
;
5009 memset(&nmtb
.tbButton
, 0, sizeof(TBBUTTON
));
5012 memset(&nmtb
.rcButton
, 0, sizeof(RECT
));
5013 res
= TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
5015 if (res
!= TBDDRET_TREATPRESSED
)
5016 /* ??? guess (GA) */
5018 /* otherwise drop through and process as pushed */
5020 /* SetCapture (hwnd); */
5021 infoPtr
->bCaptured
= TRUE
;
5022 infoPtr
->nButtonDown
= nHit
;
5024 btnPtr
->fsState
|= TBSTATE_PRESSED
;
5025 btnPtr
->bHot
= FALSE
;
5027 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
5028 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
, btnPtr
));
5032 /* native issues the TBN_BEGINDRAG here */
5033 nmtb
.iItem
= btnPtr
->idCommand
;
5034 nmtb
.tbButton
.iBitmap
= btnPtr
->iBitmap
;
5035 nmtb
.tbButton
.idCommand
= btnPtr
->idCommand
;
5036 nmtb
.tbButton
.fsState
= btnPtr
->fsState
;
5037 nmtb
.tbButton
.fsStyle
= btnPtr
->fsStyle
;
5038 nmtb
.tbButton
.dwData
= btnPtr
->dwData
;
5039 nmtb
.tbButton
.iString
= btnPtr
->iString
;
5040 nmtb
.cchText
= 0; /* !!! not correct */
5041 nmtb
.pszText
= 0; /* !!! not correct */
5042 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
5050 TOOLBAR_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5052 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5053 TBUTTON_INFO
*btnPtr
;
5057 BOOL bSendMessage
= TRUE
;
5062 if (infoPtr
->hwndToolTip
)
5063 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
5064 WM_LBUTTONUP
, wParam
, lParam
);
5066 pt
.x
= (INT
)LOWORD(lParam
);
5067 pt
.y
= (INT
)HIWORD(lParam
);
5068 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
5070 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
5071 /* if the cursor is still inside of the toolbar */
5072 if((infoPtr
->nHotItem
>= 0) && (nHit
!= -1))
5073 infoPtr
->buttons
[infoPtr
->nHotItem
].bHot
= TRUE
;
5075 if (0 <= infoPtr
->nButtonDown
) {
5076 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5077 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5079 if (btnPtr
->fsStyle
& BTNS_CHECK
) {
5080 if (btnPtr
->fsStyle
& BTNS_GROUP
) {
5081 nOldIndex
= TOOLBAR_GetCheckedGroupButtonIndex (infoPtr
,
5083 if (nOldIndex
== nHit
)
5084 bSendMessage
= FALSE
;
5085 if ((nOldIndex
!= nHit
) &&
5087 infoPtr
->buttons
[nOldIndex
].fsState
&= ~TBSTATE_CHECKED
;
5088 btnPtr
->fsState
|= TBSTATE_CHECKED
;
5091 if (btnPtr
->fsState
& TBSTATE_CHECKED
)
5092 btnPtr
->fsState
&= ~TBSTATE_CHECKED
;
5094 btnPtr
->fsState
|= TBSTATE_CHECKED
;
5098 if (nOldIndex
!= -1)
5100 InvalidateRect(hwnd
, &infoPtr
->buttons
[nOldIndex
].rect
,
5101 TOOLBAR_HasText(infoPtr
, &infoPtr
->buttons
[nOldIndex
]));
5105 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
5106 * that resets bCaptured and btn TBSTATE_PRESSED flags,
5107 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
5109 if ((infoPtr
->bCaptured
) && (infoPtr
->nButtonDown
>= 0))
5111 infoPtr
->nButtonDown
= -1;
5113 /* Issue NM_RELEASEDCAPTURE to parent to let him know it is released */
5114 TOOLBAR_SendNotify ((NMHDR
*) &hdr
, infoPtr
,
5115 NM_RELEASEDCAPTURE
);
5117 /* native issues TBN_ENDDRAG here, if _LBUTTONDOWN issued the
5120 nmtb
.iItem
= btnPtr
->idCommand
;
5121 nmtb
.tbButton
.iBitmap
= btnPtr
->iBitmap
;
5122 nmtb
.tbButton
.idCommand
= btnPtr
->idCommand
;
5123 nmtb
.tbButton
.fsState
= btnPtr
->fsState
;
5124 nmtb
.tbButton
.fsStyle
= btnPtr
->fsStyle
;
5125 nmtb
.tbButton
.dwData
= btnPtr
->dwData
;
5126 nmtb
.tbButton
.iString
= btnPtr
->iString
;
5127 nmtb
.cchText
= 0; /* !!! not correct */
5128 nmtb
.pszText
= 0; /* !!! not correct */
5129 TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
,
5132 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
5134 SendMessageA (infoPtr
->hwndNotify
, WM_COMMAND
,
5135 MAKEWPARAM(infoPtr
->buttons
[nHit
].idCommand
, 0), (LPARAM
)hwnd
);
5137 /* !!! Undocumented - toolbar at 4.71 level and above sends
5138 * either NMRCLICK or NM_CLICK with the NMMOUSE structure.
5139 * Only NM_RCLICK is documented.
5141 nmmouse
.dwItemSpec
= btnPtr
->idCommand
;
5142 nmmouse
.dwItemData
= btnPtr
->dwData
;
5143 TOOLBAR_SendNotify ((NMHDR
*) &nmmouse
, infoPtr
, NM_CLICK
);
5150 TOOLBAR_CaptureChanged(HWND hwnd
)
5152 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5153 TBUTTON_INFO
*btnPtr
;
5155 infoPtr
->bCaptured
= FALSE
;
5157 if (infoPtr
->nButtonDown
>= 0)
5159 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5160 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5162 infoPtr
->nOldHit
= -1;
5164 if (btnPtr
->fsState
& TBSTATE_ENABLED
)
5165 InvalidateRect(hwnd
, &btnPtr
->rect
, TOOLBAR_HasText(infoPtr
,
5172 TOOLBAR_MouseLeave (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5174 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5175 TBUTTON_INFO
*hotBtnPtr
, *btnPtr
;
5178 if (infoPtr
->nOldHit
< 0)
5181 hotBtnPtr
= &infoPtr
->buttons
[infoPtr
->nOldHit
];
5183 /* Redraw the button if the last button we were over is the hot button and it
5185 if((infoPtr
->nOldHit
== infoPtr
->nHotItem
) && (hotBtnPtr
->fsState
& TBSTATE_ENABLED
))
5187 hotBtnPtr
->bHot
= FALSE
;
5188 rc1
= hotBtnPtr
->rect
;
5189 InflateRect (&rc1
, 1, 1);
5190 InvalidateRect (hwnd
, &rc1
, TOOLBAR_HasText(infoPtr
,
5194 /* If the last button we were over is depressed then make it not */
5195 /* depressed and redraw it */
5196 if(infoPtr
->nOldHit
== infoPtr
->nButtonDown
)
5198 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5200 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5202 rc1
= hotBtnPtr
->rect
;
5203 InflateRect (&rc1
, 1, 1);
5204 InvalidateRect (hwnd
, &rc1
, TRUE
);
5207 infoPtr
->nOldHit
= -1; /* reset the old hit index as we've left the toolbar */
5208 infoPtr
->nHotItem
= -2; /* It has to be initially different from nOldHit */
5214 TOOLBAR_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5216 TBUTTON_INFO
*btnPtr
= NULL
, *oldBtnPtr
= NULL
;
5217 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5220 TRACKMOUSEEVENT trackinfo
;
5221 NMTBHOTITEM nmhotitem
;
5223 /* fill in the TRACKMOUSEEVENT struct */
5224 trackinfo
.cbSize
= sizeof(TRACKMOUSEEVENT
);
5225 trackinfo
.dwFlags
= TME_QUERY
;
5226 trackinfo
.hwndTrack
= hwnd
;
5227 trackinfo
.dwHoverTime
= HOVER_DEFAULT
;
5229 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
5230 _TrackMouseEvent(&trackinfo
);
5232 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
5233 if(!(trackinfo
.dwFlags
& TME_LEAVE
)) {
5234 trackinfo
.dwFlags
= TME_LEAVE
; /* notify upon leaving */
5236 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
5237 /* and can properly deactivate the hot toolbar button */
5238 _TrackMouseEvent(&trackinfo
);
5241 if (infoPtr
->hwndToolTip
)
5242 TOOLBAR_RelayEvent (infoPtr
->hwndToolTip
, hwnd
,
5243 WM_MOUSEMOVE
, wParam
, lParam
);
5245 pt
.x
= (INT
)LOWORD(lParam
);
5246 pt
.y
= (INT
)HIWORD(lParam
);
5248 nHit
= TOOLBAR_InternalHitTest (hwnd
, &pt
);
5250 if (infoPtr
->nOldHit
!= nHit
)
5252 /* Remove the effect of an old hot button if the button was
5253 drawn with the hot button effect */
5254 if(infoPtr
->nOldHit
>= 0 && infoPtr
->nOldHit
== infoPtr
->nHotItem
)
5256 oldBtnPtr
= &infoPtr
->buttons
[infoPtr
->nOldHit
];
5257 oldBtnPtr
->bHot
= FALSE
;
5260 /* It's not a separator or in nowhere. It's a hot button. */
5263 btnPtr
= &infoPtr
->buttons
[nHit
];
5265 infoPtr
->nHotItem
= nHit
;
5267 btnPtr
->bHot
= TRUE
;
5270 nmhotitem
.dwFlags
= HICF_MOUSE
;
5272 nmhotitem
.idOld
= oldBtnPtr
->idCommand
;
5274 nmhotitem
.dwFlags
|= HICF_ENTERING
;
5276 nmhotitem
.idNew
= btnPtr
->idCommand
;
5278 nmhotitem
.dwFlags
|= HICF_LEAVING
;
5279 TOOLBAR_SendNotify((NMHDR
*)&nmhotitem
, infoPtr
, TBN_HOTITEMCHANGE
);
5281 /* now invalidate the old and new buttons so they will be painted */
5283 InvalidateRect (hwnd
, &oldBtnPtr
->rect
,
5284 TOOLBAR_HasText(infoPtr
, oldBtnPtr
));
5286 InvalidateRect(hwnd
, &btnPtr
->rect
,
5287 TOOLBAR_HasText(infoPtr
, btnPtr
));
5289 if (infoPtr
->bCaptured
) {
5290 btnPtr
= &infoPtr
->buttons
[infoPtr
->nButtonDown
];
5291 if (infoPtr
->nOldHit
== infoPtr
->nButtonDown
) {
5292 btnPtr
->fsState
&= ~TBSTATE_PRESSED
;
5293 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
5295 else if (nHit
== infoPtr
->nButtonDown
) {
5296 btnPtr
->fsState
|= TBSTATE_PRESSED
;
5297 InvalidateRect(hwnd
, &btnPtr
->rect
, TRUE
);
5300 infoPtr
->nOldHit
= nHit
;
5306 inline static LRESULT
5307 TOOLBAR_NCActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5309 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
5310 return DefWindowProcA (hwnd
, WM_NCACTIVATE
, wParam
, lParam
);
5312 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
5316 inline static LRESULT
5317 TOOLBAR_NCCalcSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5319 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & CCS_NODIVIDER
))
5320 ((LPRECT
)lParam
)->top
+= GetSystemMetrics(SM_CYEDGE
);
5322 return DefWindowProcA (hwnd
, WM_NCCALCSIZE
, wParam
, lParam
);
5327 TOOLBAR_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5329 TOOLBAR_INFO
*infoPtr
;
5330 LPCREATESTRUCTA cs
= (LPCREATESTRUCTA
)lParam
;
5333 /* allocate memory for info structure */
5334 infoPtr
= (TOOLBAR_INFO
*)Alloc (sizeof(TOOLBAR_INFO
));
5335 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
5338 infoPtr
->dwStructSize
= sizeof(TBBUTTON
);
5341 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
5342 if (!GetWindowLongA (hwnd
, GWL_HINSTANCE
)) {
5343 HINSTANCE hInst
= (HINSTANCE
)GetWindowLongA (GetParent (hwnd
), GWL_HINSTANCE
);
5344 SetWindowLongA (hwnd
, GWL_HINSTANCE
, (DWORD
)hInst
);
5347 /* native control does:
5348 * Get a lot of colors and brushes
5350 * SystemParametersInfoA(0x1f, 0x3c, adr1, 0)
5351 * CreateFontIndirectA(adr1)
5352 * CreateBitmap(0x27, 0x24, 1, 1, 0)
5353 * hdc = GetDC(toolbar)
5354 * GetSystemMetrics(0x48)
5355 * fnt2=CreateFontA(0xe, 0, 0, 0, 0x190, 0, 0, 0, 0, 2,
5356 * 0, 0, 0, 0, "MARLETT")
5357 * oldfnt = SelectObject(hdc, fnt2)
5358 * GetCharWidthA(hdc, 0x36, 0x36, adr2)
5359 * GetTextMetricsA(hdc, adr3)
5360 * SelectObject(hdc, oldfnt)
5361 * DeleteObject(fnt2)
5363 * InvalidateRect(toolbar, 0, 1)
5364 * SetWindowLongA(toolbar, 0, addr)
5365 * SetWindowLongA(toolbar, -16, xxx) **sometimes**
5368 * ie 1 0x56000a4c 0x46000a4c 0x56008a4d
5369 * ie 2 0x4600094c 0x4600094c 0x4600894d
5370 * ie 3 0x56000b4c 0x46000b4c 0x56008b4d
5371 * rebar 0x50008844 0x40008844 0x50008845
5372 * pager 0x50000844 0x40000844 0x50008845
5373 * IC35mgr 0x5400084e **nochange**
5374 * on entry to _NCCREATE 0x5400084e
5375 * rowlist 0x5400004e **nochange**
5376 * on entry to _NCCREATE 0x5400004e
5380 /* I think the code below is a bug, but it is the way that the native
5381 * controls seem to work. The effect is that if the user of TBSTYLE_FLAT
5382 * forgets to specify TBSTYLE_TRANSPARENT but does specify either
5383 * CCS_TOP or CCS_BOTTOM (_NOMOVEY and _TOP), then the control
5384 * does *not* set TBSTYLE_TRANSPARENT even though it should!!!!
5385 * Some how, the only cases of this seem to be MFC programs.
5387 * Note also that the addition of _TRANSPARENT occurs *only* here. It
5388 * does not occur in the WM_STYLECHANGING routine.
5389 * (Guy Albertelli 9/2001)
5392 if ((cs
->style
& TBSTYLE_FLAT
) && !(cs
->style
& TBSTYLE_TRANSPARENT
))
5393 styleadd
|= TBSTYLE_TRANSPARENT
;
5394 if (!(cs
->style
& (CCS_TOP
| CCS_NOMOVEY
))) {
5395 styleadd
|= CCS_TOP
; /* default to top */
5396 SetWindowLongA (hwnd
, GWL_STYLE
, cs
->style
| styleadd
);
5399 return DefWindowProcA (hwnd
, WM_NCCREATE
, wParam
, lParam
);
5404 TOOLBAR_NCPaint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5406 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
5410 if (dwStyle
& WS_MINIMIZE
)
5411 return 0; /* Nothing to do */
5413 DefWindowProcA (hwnd
, WM_NCPAINT
, wParam
, lParam
);
5415 if (!(hdc
= GetDCEx (hwnd
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
5418 if (!(dwStyle
& CCS_NODIVIDER
))
5420 GetWindowRect (hwnd
, &rcWindow
);
5421 OffsetRect (&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
5422 if( dwStyle
& WS_BORDER
)
5423 OffsetRect (&rcWindow
, 1, 1);
5424 DrawEdge (hdc
, &rcWindow
, EDGE_ETCHED
, BF_TOP
);
5427 ReleaseDC( hwnd
, hdc
);
5433 inline static LRESULT
5434 TOOLBAR_Notify (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5436 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5437 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
5439 if (lpnmh
->code
== PGN_CALCSIZE
) {
5440 LPNMPGCALCSIZE lppgc
= (LPNMPGCALCSIZE
)lParam
;
5442 if (lppgc
->dwFlag
== PGF_CALCWIDTH
) {
5443 lppgc
->iWidth
= infoPtr
->rcBound
.right
- infoPtr
->rcBound
.left
;
5444 TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
5448 lppgc
->iHeight
= infoPtr
->rcBound
.bottom
- infoPtr
->rcBound
.top
;
5449 TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
5455 if (lpnmh
->code
== PGN_SCROLL
) {
5456 LPNMPGSCROLL lppgs
= (LPNMPGSCROLL
)lParam
;
5458 lppgs
->iScroll
= (lppgs
->iDir
& (PGF_SCROLLLEFT
| PGF_SCROLLRIGHT
)) ?
5459 infoPtr
->nButtonWidth
: infoPtr
->nButtonHeight
;
5460 TRACE("processed PGN_SCROLL, returning scroll=%d, dir=%d\n",
5461 lppgs
->iScroll
, lppgs
->iDir
);
5466 TRACE("passing WM_NOTIFY!\n");
5468 if ((infoPtr
->hwndToolTip
) && (lpnmh
->hwndFrom
== infoPtr
->hwndToolTip
)) {
5469 if (infoPtr
->bNtfUnicode
)
5470 return SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
5473 return SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
5477 if (lpnmh
->code
== TTN_GETDISPINFOA
) {
5478 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
5480 FIXME("retrieving ASCII string\n");
5483 else if (lpnmh
->code
== TTN_GETDISPINFOW
) {
5484 LPNMTTDISPINFOW lpdi
= (LPNMTTDISPINFOW
)lParam
;
5486 FIXME("retrieving UNICODE string\n");
5497 TOOLBAR_NotifyFormatFake(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5499 /* remove this routine when Toolbar is improved to pass infoPtr
5500 * around instead of hwnd.
5502 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
5503 return TOOLBAR_NotifyFormat(infoPtr
, wParam
, lParam
);
5508 TOOLBAR_NotifyFormat(TOOLBAR_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
5512 if (lParam
== NF_REQUERY
) {
5513 i
= SendMessageA(infoPtr
->hwndNotify
,
5514 WM_NOTIFYFORMAT
, (WPARAM
)infoPtr
->hwndSelf
, NF_QUERY
);
5515 if ((i
< NFR_ANSI
) || (i
> NFR_UNICODE
)) {
5516 ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n",
5520 infoPtr
->bNtfUnicode
= (i
== NFR_UNICODE
) ? 1 : 0;
5523 return (LRESULT
)((infoPtr
->bUnicode
) ? NFR_UNICODE
: NFR_ANSI
);
5528 TOOLBAR_Paint (HWND hwnd
, WPARAM wParam
)
5530 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr(hwnd
);
5534 /* fill ps.rcPaint with a default rect */
5535 memcpy(&(ps
.rcPaint
), &(infoPtr
->rcBound
), sizeof(infoPtr
->rcBound
));
5537 hdc
= wParam
==0 ? BeginPaint(hwnd
, &ps
) : (HDC
)wParam
;
5539 TRACE("psrect=(%ld,%ld)-(%ld,%ld)\n",
5540 ps
.rcPaint
.left
, ps
.rcPaint
.top
,
5541 ps
.rcPaint
.right
, ps
.rcPaint
.bottom
);
5543 TOOLBAR_Refresh (hwnd
, hdc
, &ps
);
5544 if (!wParam
) EndPaint (hwnd
, &ps
);
5551 TOOLBAR_SetRedraw (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5552 /*****************************************************
5555 * Handles the WM_SETREDRAW message.
5558 * According to testing V4.71 of COMCTL32 returns the
5559 * *previous* status of the redraw flag (either 0 or 1)
5560 * instead of the MSDN documented value of 0 if handled.
5561 * (For laughs see the "consistency" with same function
5564 *****************************************************/
5566 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5567 BOOL oldredraw
= infoPtr
->bDoRedraw
;
5569 TRACE("set to %s\n",
5570 (wParam
) ? "TRUE" : "FALSE");
5571 infoPtr
->bDoRedraw
= (BOOL
) wParam
;
5573 InvalidateRect (infoPtr
->hwndSelf
, 0, TRUE
);
5575 return (oldredraw
) ? 1 : 0;
5580 TOOLBAR_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5582 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5583 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
5592 /* Resize deadlock check */
5593 if (infoPtr
->bAutoSize
) {
5594 infoPtr
->bAutoSize
= FALSE
;
5598 /* FIXME: optimize to only update size if the new size doesn't */
5599 /* match the current size */
5601 flags
= (INT
) wParam
;
5603 /* FIXME for flags =
5604 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
5607 TRACE("sizing toolbar!\n");
5609 if (flags
== SIZE_RESTORED
) {
5610 /* width and height don't apply */
5611 parent
= GetParent (hwnd
);
5612 GetClientRect(parent
, &parent_rect
);
5613 x
= parent_rect
.left
;
5614 y
= parent_rect
.top
;
5616 if (dwStyle
& CCS_NORESIZE
) {
5617 uPosFlags
|= (SWP_NOSIZE
| SWP_NOMOVE
);
5620 * this sets the working width of the toolbar, and
5621 * Calc Toolbar will not adjust it, only the height
5623 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
5624 cy
= infoPtr
->nHeight
;
5625 cx
= infoPtr
->nWidth
;
5626 TOOLBAR_CalcToolbar (hwnd
);
5627 infoPtr
->nWidth
= cx
;
5628 infoPtr
->nHeight
= cy
;
5631 infoPtr
->nWidth
= parent_rect
.right
- parent_rect
.left
;
5632 TOOLBAR_CalcToolbar (hwnd
);
5633 cy
= infoPtr
->nHeight
;
5634 cx
= infoPtr
->nWidth
;
5636 if ((dwStyle
& CCS_BOTTOM
) == CCS_NOMOVEY
) {
5637 GetWindowRect(hwnd
, &window_rect
);
5638 ScreenToClient(parent
, (LPPOINT
)&window_rect
.left
);
5639 y
= window_rect
.top
;
5641 if ((dwStyle
& CCS_BOTTOM
) == CCS_BOTTOM
) {
5642 GetWindowRect(hwnd
, &window_rect
);
5643 y
= parent_rect
.bottom
-
5644 ( window_rect
.bottom
- window_rect
.top
);
5648 if (dwStyle
& CCS_NOPARENTALIGN
) {
5649 uPosFlags
|= SWP_NOMOVE
;
5650 cy
= infoPtr
->nHeight
;
5651 cx
= infoPtr
->nWidth
;
5654 if (!(dwStyle
& CCS_NODIVIDER
))
5655 cy
+= GetSystemMetrics(SM_CYEDGE
);
5657 if (dwStyle
& WS_BORDER
)
5660 cy
+= GetSystemMetrics(SM_CYEDGE
);
5661 cx
+= GetSystemMetrics(SM_CYEDGE
);
5664 SetWindowPos (hwnd
, 0, x
, y
, cx
, cy
, uPosFlags
| SWP_NOZORDER
);
5671 TOOLBAR_StyleChanged (HWND hwnd
, INT nType
, LPSTYLESTRUCT lpStyle
)
5673 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5675 if (nType
== GWL_STYLE
) {
5676 if (lpStyle
->styleNew
& TBSTYLE_LIST
) {
5677 infoPtr
->dwDTFlags
= DT_LEFT
| DT_VCENTER
| DT_SINGLELINE
;
5680 infoPtr
->dwDTFlags
= DT_CENTER
;
5682 infoPtr
->bTransparent
= (lpStyle
->styleNew
& TBSTYLE_TRANSPARENT
);
5683 infoPtr
->bBtnTranspnt
= (lpStyle
->styleNew
&
5684 (TBSTYLE_FLAT
| TBSTYLE_LIST
));
5685 TOOLBAR_CheckStyle (hwnd
, lpStyle
->styleNew
);
5687 TRACE("new style 0x%08lx\n", lpStyle
->styleNew
);
5690 TOOLBAR_CalcToolbar(hwnd
);
5692 TOOLBAR_AutoSize (hwnd
);
5694 InvalidateRect(hwnd
, NULL
, FALSE
);
5701 TOOLBAR_SysColorChange (HWND hwnd
)
5703 COMCTL32_RefreshSysColors();
5710 static LRESULT WINAPI
5711 ToolbarWindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
5713 TOOLBAR_INFO
*infoPtr
= TOOLBAR_GetInfoPtr (hwnd
);
5715 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n",
5716 hwnd
, uMsg
, /* SPY_GetMsgName(uMsg), */ wParam
, lParam
);
5718 if (!TOOLBAR_GetInfoPtr(hwnd
) && (uMsg
!= WM_NCCREATE
))
5719 return DefWindowProcA( hwnd
, uMsg
, wParam
, lParam
);
5724 return TOOLBAR_AddBitmap (hwnd
, wParam
, lParam
);
5726 case TB_ADDBUTTONSA
:
5727 return TOOLBAR_AddButtonsA (hwnd
, wParam
, lParam
);
5729 case TB_ADDBUTTONSW
:
5730 return TOOLBAR_AddButtonsW (hwnd
, wParam
, lParam
);
5733 return TOOLBAR_AddStringA (hwnd
, wParam
, lParam
);
5736 return TOOLBAR_AddStringW (hwnd
, wParam
, lParam
);
5739 return TOOLBAR_AutoSize (hwnd
);
5741 case TB_BUTTONCOUNT
:
5742 return TOOLBAR_ButtonCount (hwnd
, wParam
, lParam
);
5744 case TB_BUTTONSTRUCTSIZE
:
5745 return TOOLBAR_ButtonStructSize (hwnd
, wParam
, lParam
);
5747 case TB_CHANGEBITMAP
:
5748 return TOOLBAR_ChangeBitmap (hwnd
, wParam
, lParam
);
5750 case TB_CHECKBUTTON
:
5751 return TOOLBAR_CheckButton (hwnd
, wParam
, lParam
);
5753 case TB_COMMANDTOINDEX
:
5754 return TOOLBAR_CommandToIndex (hwnd
, wParam
, lParam
);
5757 return TOOLBAR_Customize (hwnd
);
5759 case TB_DELETEBUTTON
:
5760 return TOOLBAR_DeleteButton (hwnd
, wParam
, lParam
);
5762 case TB_ENABLEBUTTON
:
5763 return TOOLBAR_EnableButton (hwnd
, wParam
, lParam
);
5765 case TB_GETANCHORHIGHLIGHT
:
5766 return TOOLBAR_GetAnchorHighlight (hwnd
);
5769 return TOOLBAR_GetBitmap (hwnd
, wParam
, lParam
);
5771 case TB_GETBITMAPFLAGS
:
5772 return TOOLBAR_GetBitmapFlags (hwnd
, wParam
, lParam
);
5775 return TOOLBAR_GetButton (hwnd
, wParam
, lParam
);
5777 case TB_GETBUTTONINFOA
:
5778 return TOOLBAR_GetButtonInfoA (hwnd
, wParam
, lParam
);
5780 case TB_GETBUTTONINFOW
:
5781 return TOOLBAR_GetButtonInfoW (hwnd
, wParam
, lParam
);
5783 case TB_GETBUTTONSIZE
:
5784 return TOOLBAR_GetButtonSize (hwnd
);
5786 case TB_GETBUTTONTEXTA
:
5787 return TOOLBAR_GetButtonTextA (hwnd
, wParam
, lParam
);
5789 case TB_GETBUTTONTEXTW
:
5790 return TOOLBAR_GetButtonTextW (hwnd
, wParam
, lParam
);
5792 case TB_GETDISABLEDIMAGELIST
:
5793 return TOOLBAR_GetDisabledImageList (hwnd
, wParam
, lParam
);
5795 case TB_GETEXTENDEDSTYLE
:
5796 return TOOLBAR_GetExtendedStyle (hwnd
);
5798 case TB_GETHOTIMAGELIST
:
5799 return TOOLBAR_GetHotImageList (hwnd
, wParam
, lParam
);
5802 return TOOLBAR_GetHotItem (hwnd
);
5804 case TB_GETIMAGELIST
:
5805 return TOOLBAR_GetDefImageList (hwnd
, wParam
, lParam
);
5807 /* case TB_GETINSERTMARK: */ /* 4.71 */
5808 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
5810 case TB_GETITEMRECT
:
5811 return TOOLBAR_GetItemRect (hwnd
, wParam
, lParam
);
5814 return TOOLBAR_GetMaxSize (hwnd
, wParam
, lParam
);
5816 /* case TB_GETOBJECT: */ /* 4.71 */
5819 return TOOLBAR_GetPadding (hwnd
);
5822 return TOOLBAR_GetRect (hwnd
, wParam
, lParam
);
5825 return TOOLBAR_GetRows (hwnd
, wParam
, lParam
);
5828 return TOOLBAR_GetState (hwnd
, wParam
, lParam
);
5831 return TOOLBAR_GetStyle (hwnd
, wParam
, lParam
);
5833 case TB_GETTEXTROWS
:
5834 return TOOLBAR_GetTextRows (hwnd
, wParam
, lParam
);
5836 case TB_GETTOOLTIPS
:
5837 return TOOLBAR_GetToolTips (hwnd
, wParam
, lParam
);
5839 case TB_GETUNICODEFORMAT
:
5840 return TOOLBAR_GetUnicodeFormat (hwnd
, wParam
, lParam
);
5843 return TOOLBAR_HideButton (hwnd
, wParam
, lParam
);
5846 return TOOLBAR_HitTest (hwnd
, wParam
, lParam
);
5848 case TB_INDETERMINATE
:
5849 return TOOLBAR_Indeterminate (hwnd
, wParam
, lParam
);
5851 case TB_INSERTBUTTONA
:
5852 return TOOLBAR_InsertButtonA (hwnd
, wParam
, lParam
);
5854 case TB_INSERTBUTTONW
:
5855 return TOOLBAR_InsertButtonW (hwnd
, wParam
, lParam
);
5857 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
5859 case TB_ISBUTTONCHECKED
:
5860 return TOOLBAR_IsButtonChecked (hwnd
, wParam
, lParam
);
5862 case TB_ISBUTTONENABLED
:
5863 return TOOLBAR_IsButtonEnabled (hwnd
, wParam
, lParam
);
5865 case TB_ISBUTTONHIDDEN
:
5866 return TOOLBAR_IsButtonHidden (hwnd
, wParam
, lParam
);
5868 case TB_ISBUTTONHIGHLIGHTED
:
5869 return TOOLBAR_IsButtonHighlighted (hwnd
, wParam
, lParam
);
5871 case TB_ISBUTTONINDETERMINATE
:
5872 return TOOLBAR_IsButtonIndeterminate (hwnd
, wParam
, lParam
);
5874 case TB_ISBUTTONPRESSED
:
5875 return TOOLBAR_IsButtonPressed (hwnd
, wParam
, lParam
);
5877 case TB_LOADIMAGES
: /* 4.70 */
5878 FIXME("missing standard imagelists\n");
5881 /* case TB_MAPACCELERATORA: */ /* 4.71 */
5882 /* case TB_MAPACCELERATORW: */ /* 4.71 */
5883 /* case TB_MARKBUTTON: */ /* 4.71 */
5884 /* case TB_MOVEBUTTON: */ /* 4.71 */
5886 case TB_PRESSBUTTON
:
5887 return TOOLBAR_PressButton (hwnd
, wParam
, lParam
);
5889 case TB_REPLACEBITMAP
:
5890 return TOOLBAR_ReplaceBitmap (hwnd
, wParam
, lParam
);
5892 case TB_SAVERESTOREA
:
5893 return TOOLBAR_SaveRestoreA (hwnd
, wParam
, lParam
);
5895 case TB_SAVERESTOREW
:
5896 return TOOLBAR_SaveRestoreW (hwnd
, wParam
, lParam
);
5898 case TB_SETANCHORHIGHLIGHT
:
5899 return TOOLBAR_SetAnchorHighlight (hwnd
, wParam
);
5901 case TB_SETBITMAPSIZE
:
5902 return TOOLBAR_SetBitmapSize (hwnd
, wParam
, lParam
);
5904 case TB_SETBUTTONINFOA
:
5905 return TOOLBAR_SetButtonInfoA (hwnd
, wParam
, lParam
);
5907 case TB_SETBUTTONINFOW
:
5908 return TOOLBAR_SetButtonInfoW (hwnd
, wParam
, lParam
);
5910 case TB_SETBUTTONSIZE
:
5911 return TOOLBAR_SetButtonSize (hwnd
, wParam
, lParam
);
5913 case TB_SETBUTTONWIDTH
:
5914 return TOOLBAR_SetButtonWidth (hwnd
, wParam
, lParam
);
5917 return TOOLBAR_SetCmdId (hwnd
, wParam
, lParam
);
5919 case TB_SETDISABLEDIMAGELIST
:
5920 return TOOLBAR_SetDisabledImageList (hwnd
, wParam
, lParam
);
5922 case TB_SETDRAWTEXTFLAGS
:
5923 return TOOLBAR_SetDrawTextFlags (hwnd
, wParam
, lParam
);
5925 case TB_SETEXTENDEDSTYLE
:
5926 return TOOLBAR_SetExtendedStyle (hwnd
, wParam
, lParam
);
5928 case TB_SETHOTIMAGELIST
:
5929 return TOOLBAR_SetHotImageList (hwnd
, wParam
, lParam
);
5932 return TOOLBAR_SetHotItem (hwnd
, wParam
);
5934 case TB_SETIMAGELIST
:
5935 return TOOLBAR_SetImageList (hwnd
, wParam
, lParam
);
5938 return TOOLBAR_SetIndent (hwnd
, wParam
, lParam
);
5940 /* case TB_SETINSERTMARK: */ /* 4.71 */
5942 case TB_SETINSERTMARKCOLOR
:
5943 return TOOLBAR_SetInsertMarkColor (hwnd
, wParam
, lParam
);
5945 case TB_SETMAXTEXTROWS
:
5946 return TOOLBAR_SetMaxTextRows (hwnd
, wParam
, lParam
);
5949 return TOOLBAR_SetPadding (hwnd
, wParam
, lParam
);
5952 return TOOLBAR_SetParent (hwnd
, wParam
, lParam
);
5955 return TOOLBAR_SetRows (hwnd
, wParam
, lParam
);
5958 return TOOLBAR_SetState (hwnd
, wParam
, lParam
);
5961 return TOOLBAR_SetStyle (hwnd
, wParam
, lParam
);
5963 case TB_SETTOOLTIPS
:
5964 return TOOLBAR_SetToolTips (hwnd
, wParam
, lParam
);
5966 case TB_SETUNICODEFORMAT
:
5967 return TOOLBAR_SetUnicodeFormat (hwnd
, wParam
, lParam
);
5970 return TOOLBAR_Unkwn45E (hwnd
, wParam
, lParam
);
5973 return TOOLBAR_Unkwn463 (hwnd
, wParam
, lParam
);
5976 /* Common Control Messages */
5978 /* case TB_GETCOLORSCHEME: */ /* identical to CCM_ */
5979 case CCM_GETCOLORSCHEME
:
5980 return TOOLBAR_GetColorScheme (hwnd
, (LPCOLORSCHEME
)lParam
);
5982 /* case TB_SETCOLORSCHEME: */ /* identical to CCM_ */
5983 case CCM_SETCOLORSCHEME
:
5984 return TOOLBAR_SetColorScheme (hwnd
, (LPCOLORSCHEME
)lParam
);
5986 case CCM_GETVERSION
:
5987 return TOOLBAR_GetVersion (hwnd
);
5989 case CCM_SETVERSION
:
5990 return TOOLBAR_SetVersion (hwnd
, (INT
)wParam
);
5996 return TOOLBAR_Create (hwnd
, wParam
, lParam
);
5999 return TOOLBAR_Destroy (hwnd
, wParam
, lParam
);
6002 return TOOLBAR_EraseBackground (hwnd
, wParam
, lParam
);
6005 return TOOLBAR_GetFont (hwnd
, wParam
, lParam
);
6007 /* case WM_KEYDOWN: */
6008 /* case WM_KILLFOCUS: */
6010 case WM_LBUTTONDBLCLK
:
6011 return TOOLBAR_LButtonDblClk (hwnd
, wParam
, lParam
);
6013 case WM_LBUTTONDOWN
:
6014 return TOOLBAR_LButtonDown (hwnd
, wParam
, lParam
);
6017 return TOOLBAR_LButtonUp (hwnd
, wParam
, lParam
);
6020 return TOOLBAR_MouseMove (hwnd
, wParam
, lParam
);
6023 return TOOLBAR_MouseLeave (hwnd
, wParam
, lParam
);
6025 case WM_CAPTURECHANGED
:
6026 return TOOLBAR_CaptureChanged(hwnd
);
6029 return TOOLBAR_NCActivate (hwnd
, wParam
, lParam
);
6032 return TOOLBAR_NCCalcSize (hwnd
, wParam
, lParam
);
6035 return TOOLBAR_NCCreate (hwnd
, wParam
, lParam
);
6038 return TOOLBAR_NCPaint (hwnd
, wParam
, lParam
);
6041 return TOOLBAR_Notify (hwnd
, wParam
, lParam
);
6043 case WM_NOTIFYFORMAT
:
6044 return TOOLBAR_NotifyFormatFake (hwnd
, wParam
, lParam
);
6047 return TOOLBAR_Paint (hwnd
, wParam
);
6050 return TOOLBAR_SetRedraw (hwnd
, wParam
, lParam
);
6053 return TOOLBAR_Size (hwnd
, wParam
, lParam
);
6055 case WM_STYLECHANGED
:
6056 return TOOLBAR_StyleChanged (hwnd
, (INT
)wParam
, (LPSTYLESTRUCT
)lParam
);
6058 case WM_SYSCOLORCHANGE
:
6059 return TOOLBAR_SysColorChange (hwnd
);
6061 /* case WM_WININICHANGE: */
6066 case WM_MEASUREITEM
:
6068 return SendMessageA (infoPtr
->hwndNotify
, uMsg
, wParam
, lParam
);
6070 /* We see this in Outlook Express 5.x and just does DefWindowProc */
6071 case PGM_FORWARDMOUSE
:
6072 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
6075 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
6076 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
6077 uMsg
, wParam
, lParam
);
6078 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
6085 TOOLBAR_Register (void)
6089 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
6090 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
6091 wndClass
.lpfnWndProc
= (WNDPROC
)ToolbarWindowProc
;
6092 wndClass
.cbClsExtra
= 0;
6093 wndClass
.cbWndExtra
= sizeof(TOOLBAR_INFO
*);
6094 wndClass
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
6095 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
6096 wndClass
.lpszClassName
= TOOLBARCLASSNAMEA
;
6098 RegisterClassA (&wndClass
);
6103 TOOLBAR_Unregister (void)
6105 UnregisterClassA (TOOLBARCLASSNAMEA
, NULL
);
6108 static HIMAGELIST
TOOLBAR_InsertImageList(PIMLENTRY
**pies
, INT
*cies
, HIMAGELIST himl
, INT id
)
6113 /* Check if the entry already exists */
6114 c
= TOOLBAR_GetImageListEntry(*pies
, *cies
, id
);
6116 /* If this is a new entry we must create it and insert into the array */
6121 c
= (PIMLENTRY
) Alloc(sizeof(IMLENTRY
));
6124 pnies
= Alloc((*cies
+ 1) * sizeof(PIMLENTRY
));
6125 memcpy(pnies
, *pies
, ((*cies
) * sizeof(PIMLENTRY
)));
6140 static VOID
TOOLBAR_DeleteImageList(PIMLENTRY
**pies
, INT
*cies
)
6144 for (i
= 0; i
< *cies
; i
++)
6154 static PIMLENTRY
TOOLBAR_GetImageListEntry(PIMLENTRY
*pies
, INT cies
, INT id
)
6162 for (i
= 0; i
< cies
; i
++)
6164 if (pies
[i
]->id
== id
)
6176 static HIMAGELIST
TOOLBAR_GetImageList(PIMLENTRY
*pies
, INT cies
, INT id
)
6178 HIMAGELIST himlDef
= 0;
6179 PIMLENTRY pie
= TOOLBAR_GetImageListEntry(pies
, cies
, id
);
6182 himlDef
= pie
->himl
;
6188 static BOOL
TOOLBAR_GetButtonInfo(TOOLBAR_INFO
*infoPtr
, NMTOOLBARW
*nmtb
)
6190 if (infoPtr
->bUnicode
)
6191 return TOOLBAR_SendNotify ((NMHDR
*) nmtb
, infoPtr
, TBN_GETBUTTONINFOW
);
6198 nmtba
.iItem
= nmtb
->iItem
;
6199 nmtba
.pszText
= Buffer
;
6200 nmtba
.cchText
= 256;
6201 ZeroMemory(nmtba
.pszText
, nmtba
.cchText
);
6203 if (TOOLBAR_SendNotify ((NMHDR
*) &nmtba
, infoPtr
, TBN_GETBUTTONINFOA
))
6205 int ccht
= strlen(nmtba
.pszText
);
6207 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)nmtba
.pszText
, -1,
6208 nmtb
->pszText
, nmtb
->cchText
);
6210 memcpy(&nmtb
->tbButton
, &nmtba
.tbButton
, sizeof(TBBUTTON
));
6219 static BOOL
TOOLBAR_IsButtonRemovable(TOOLBAR_INFO
*infoPtr
,
6220 int iItem
, PCUSTOMBUTTON btnInfo
)
6225 memcpy(&nmtb
.tbButton
, &btnInfo
->btn
, sizeof(TBBUTTON
));
6227 return TOOLBAR_SendNotify ((NMHDR
*) &nmtb
, infoPtr
, TBN_QUERYDELETE
);