Removed unnecessary calls of TOOLBAR_CalcToolbar() (which would be
[wine.git] / dlls / comctl32 / toolbar.c
blob483958ba5bf9b6c51bfa50ff9a6508f2ee4ebfd9
1 /*
2 * Toolbar control
4 * Copyright 1998,1999 Eric Kohl
6 * TODO:
7 * - A little bug in TOOLBAR_DrawMasked()
8 * - Button wrapping (under construction).
9 * - Messages.
10 * - Notifications (under construction).
11 * - Fix TB_SETROWS.
12 * - Tooltip support (almost complete).
13 * - Unicode suppport (under construction).
14 * - Fix TOOLBAR_SetButtonInfo32A/W.
15 * - Customize dialog (under construction).
16 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
17 * - I_IMAGECALLBACK support.
18 * - iString of -1 is undocumented
20 * Testing:
21 * - Run tests using Waite Group Windows95 API Bible Volume 2.
22 * The second cdrom contains executables addstr.exe, btncount.exe,
23 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
24 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
25 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
26 * setparnt.exe, setrows.exe, toolwnd.exe.
27 * - Microsofts controlspy examples.
30 #include <string.h>
32 #include "winbase.h"
33 #include "windef.h"
34 #include "wingdi.h"
35 #include "winuser.h"
36 #include "wine/unicode.h"
37 #include "wine/winestring.h"
38 #include "commctrl.h"
39 #include "imagelist.h"
40 #include "cache.h"
41 #include "comctl32.h"
42 #include "debugtools.h"
44 DEFAULT_DEBUG_CHANNEL(toolbar);
46 typedef struct
48 INT iBitmap;
49 INT idCommand;
50 BYTE fsState;
51 BYTE fsStyle;
52 DWORD dwData;
53 INT iString;
55 BOOL bHot;
56 INT nRow;
57 RECT rect;
58 } TBUTTON_INFO;
60 typedef struct
62 DWORD dwStructSize; /* size of TBBUTTON struct */
63 INT nHeight; /* height of the toolbar */
64 INT nWidth; /* width of the toolbar */
65 INT nButtonHeight;
66 INT nButtonWidth;
67 INT nBitmapHeight;
68 INT nBitmapWidth;
69 INT nIndent;
70 INT nRows; /* number of button rows */
71 INT nMaxTextRows; /* maximum number of text rows */
72 INT cxMin; /* minimum button width */
73 INT cxMax; /* maximum button width */
74 INT nNumButtons; /* number of buttons */
75 INT nNumBitmaps; /* number of bitmaps */
76 INT nNumStrings; /* number of strings */
77 BOOL bUnicode; /* ASCII (FALSE) or Unicode (TRUE)? */
78 BOOL bCaptured; /* mouse captured? */
79 INT nButtonDown;
80 INT nOldHit;
81 INT nHotItem; /* index of the "hot" item */
82 HFONT hFont; /* text font */
83 HIMAGELIST himlInt; /* image list created internally */
84 HIMAGELIST himlDef; /* default image list */
85 HIMAGELIST himlHot; /* hot image list */
86 HIMAGELIST himlDis; /* disabled image list */
87 HWND hwndToolTip; /* handle to tool tip control */
88 HWND hwndNotify; /* handle to the window that gets notifications */
89 BOOL bTransparent; /* background transparency flag */
90 BOOL bAutoSize; /* auto size deadlock indicator */
91 BOOL bAnchor; /* anchor highlight enabled */
92 DWORD dwExStyle; /* extended toolbar style */
93 DWORD dwDTFlags; /* DrawText flags */
95 COLORREF clrInsertMark; /* insert mark color */
96 RECT rcBound; /* bounding rectangle */
97 INT iVersion;
99 TBUTTON_INFO *buttons; /* pointer to button array */
100 LPWSTR *strings; /* pointer to string array */
101 } TOOLBAR_INFO;
103 #define SEPARATOR_WIDTH 8
104 #define TOP_BORDER 2
105 #define BOTTOM_BORDER 2
106 #define DDARROW_WIDTH 11
108 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
109 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
110 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
112 static LPWSTR
113 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
115 LPWSTR lpText = NULL;
117 /* FIXME: iString == -1 is undocumented */
118 if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
119 lpText = (LPWSTR)btnPtr->iString;
120 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
121 lpText = infoPtr->strings[btnPtr->iString];
123 return lpText;
126 static BOOL
127 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
129 if ((index>=0) && (index < infoPtr->nNumBitmaps))
130 return TRUE;
131 else
132 return FALSE;
136 static void
137 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
139 INT x = (lpRect->left + lpRect->right) / 2 - 1;
140 INT yBottom = lpRect->bottom - 3;
141 INT yTop = lpRect->top + 1;
143 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
144 MoveToEx (hdc, x, yBottom, NULL);
145 LineTo (hdc, x, yTop);
146 x++;
147 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
148 MoveToEx (hdc, x, yBottom, NULL);
149 LineTo (hdc, x, yTop);
152 static void
153 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
155 INT x, y;
156 SelectObject ( hdc, GetSysColorPen (colorRef));
157 x = left + 2;
158 y = top + 8;
159 MoveToEx (hdc, x, y, NULL);
160 LineTo (hdc, x+5, y++); x++;
161 MoveToEx (hdc, x, y, NULL);
162 LineTo (hdc, x+3, y++); x++;
163 MoveToEx (hdc, x, y, NULL);
164 LineTo (hdc, x+1, y++);
168 * Draw the text string for this button.
169 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
170 * is non-zero, so we can simply check himlDef to see if we have
171 * an image list
173 static void
174 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
175 HDC hdc, INT nState, DWORD dwStyle)
177 RECT rcText = btnPtr->rect;
178 HFONT hOldFont;
179 INT nOldBkMode;
180 COLORREF clrOld;
181 LPWSTR lpText = NULL;
182 HIMAGELIST himl = infoPtr->himlDef;
184 TRACE ("iString: %x\n", btnPtr->iString);
186 /* get a pointer to the text */
187 lpText = TOOLBAR_GetText(infoPtr, btnPtr);
189 TRACE ("lpText: \"%s\"\n", debugstr_w(lpText));
191 /* draw text */
192 if (lpText) {
194 InflateRect (&rcText, -3, -3);
196 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
197 if ((dwStyle & TBSTYLE_LIST) &&
198 ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
199 (btnPtr->iBitmap != I_IMAGENONE)) {
200 rcText.left += infoPtr->nBitmapWidth;
202 else {
203 rcText.top += infoPtr->nBitmapHeight;
207 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
208 OffsetRect (&rcText, 1, 1);
210 hOldFont = SelectObject (hdc, infoPtr->hFont);
211 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
212 if (!(nState & TBSTATE_ENABLED)) {
213 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
214 OffsetRect (&rcText, 1, 1);
215 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
216 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
217 OffsetRect (&rcText, -1, -1);
218 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
220 else if (nState & TBSTATE_INDETERMINATE) {
221 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
222 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
224 else {
225 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
226 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
229 SetTextColor (hdc, clrOld);
230 SelectObject (hdc, hOldFont);
231 if (nOldBkMode != TRANSPARENT)
232 SetBkMode (hdc, nOldBkMode);
237 static void
238 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
240 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
241 INT cx = lpRect->right - lpRect->left;
242 INT cy = lpRect->bottom - lpRect->top;
243 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
244 SelectObject (hdc, hbr);
248 static void
249 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
250 HDC hdc, INT x, INT y)
252 /* FIXME: this function is a hack since it uses image list
253 internals directly */
255 HIMAGELIST himl = infoPtr->himlDef;
256 HBITMAP hbmMask;
257 HDC hdcImageList;
258 HDC hdcMask;
260 if (!himl)
261 return;
263 /* create new dc's */
264 hdcImageList = CreateCompatibleDC (0);
265 hdcMask = CreateCompatibleDC (0);
267 /* create new bitmap */
268 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
269 SelectObject (hdcMask, hbmMask);
271 /* copy the mask bitmap */
272 SelectObject (hdcImageList, himl->hbmMask);
273 SetBkColor (hdcImageList, RGB(255, 255, 255));
274 SetTextColor (hdcImageList, RGB(0, 0, 0));
275 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
276 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
278 #if 0
279 /* add white mask from image */
280 SelectObject (hdcImageList, himl->hbmImage);
281 SetBkColor (hdcImageList, RGB(0, 0, 0));
282 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
283 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
284 #endif
286 /* draw the new mask */
287 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
288 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
289 hdcMask, 0, 0, 0xB8074A);
291 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
292 BitBlt (hdc, x, y, himl->cx, himl->cy,
293 hdcMask, 0, 0, 0xB8074A);
295 DeleteObject (hbmMask);
296 DeleteDC (hdcMask);
297 DeleteDC (hdcImageList);
301 static void
302 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
304 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
305 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
306 BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
307 (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
308 RECT rc, rcArrow, rcBitmap;
310 if (btnPtr->fsState & TBSTATE_HIDDEN)
311 return;
313 rc = btnPtr->rect;
314 CopyRect (&rcArrow, &rc);
315 CopyRect(&rcBitmap, &rc);
317 FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
319 if (hasDropDownArrow)
321 if (dwStyle & TBSTYLE_FLAT)
322 rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
323 else
324 rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
325 rcArrow.left = rc.right;
328 /* Center the bitmap horizontally and vertically */
329 rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
331 if(TOOLBAR_HasText(infoPtr, btnPtr))
332 rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
333 else
334 rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
336 TRACE("iBitmap: %d\n", btnPtr->iBitmap);
338 /* separator */
339 if (btnPtr->fsStyle & TBSTYLE_SEP) {
340 /* with the FLAT style, iBitmap is the width and has already */
341 /* been taken into consideration in calculating the width */
342 /* so now we need to draw the vertical separator */
343 /* empirical tests show that iBitmap can/will be non-zero */
344 /* when drawing the vertical bar... */
345 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
346 TOOLBAR_DrawFlatSeparator (&rc, hdc);
347 return;
350 /* disabled */
351 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
352 if (!(dwStyle & TBSTYLE_FLAT))
354 DrawEdge (hdc, &rc, EDGE_RAISED,
355 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
356 if (hasDropDownArrow)
357 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
358 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
361 if (hasDropDownArrow)
363 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
364 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
367 if (infoPtr->himlDis &&
368 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
369 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
370 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
371 else
372 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
374 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
375 return;
378 /* pressed TBSTYLE_BUTTON */
379 if (btnPtr->fsState & TBSTATE_PRESSED) {
380 if (dwStyle & TBSTYLE_FLAT)
382 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
383 if (hasDropDownArrow)
384 DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
386 else
388 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
389 if (hasDropDownArrow)
390 DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
393 if (hasDropDownArrow)
394 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
396 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
397 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
398 rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
400 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
401 return;
404 /* checked TBSTYLE_CHECK */
405 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
406 (btnPtr->fsState & TBSTATE_CHECKED)) {
407 if (dwStyle & TBSTYLE_FLAT)
408 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
409 BF_RECT | BF_MIDDLE | BF_ADJUST);
410 else
411 DrawEdge (hdc, &rc, EDGE_SUNKEN,
412 BF_RECT | BF_MIDDLE | BF_ADJUST);
414 TOOLBAR_DrawPattern (hdc, &rc);
416 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
417 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
418 rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
419 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
420 return;
423 /* indeterminate */
424 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
425 DrawEdge (hdc, &rc, EDGE_RAISED,
426 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
428 TOOLBAR_DrawPattern (hdc, &rc);
429 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
430 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
431 return;
434 /* normal state */
435 if (dwStyle & TBSTYLE_FLAT)
437 if (btnPtr->bHot)
439 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
440 if (hasDropDownArrow)
441 DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
443 else
445 FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
446 if (hasDropDownArrow)
447 FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
450 if (hasDropDownArrow)
451 TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
453 if (btnPtr->bHot && infoPtr->himlHot &&
454 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
455 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
456 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
457 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
458 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
459 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
461 else
463 DrawEdge (hdc, &rc, EDGE_RAISED,
464 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
466 if (hasDropDownArrow)
468 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
469 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
470 TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
473 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
474 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
475 rcBitmap.left, rcBitmap.top, ILD_NORMAL);
478 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
482 static void
483 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
485 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
486 TBUTTON_INFO *btnPtr;
487 INT i;
488 RECT rcTemp;
490 /* redraw necessary buttons */
491 btnPtr = infoPtr->buttons;
492 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
494 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
495 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
499 static void
500 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
502 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
503 TBUTTON_INFO *btnPtr;
504 HDC hdc;
505 HFONT hOldFont;
507 lpSize->cx = 0;
508 lpSize->cy = 0;
509 hdc = GetDC (0);
510 hOldFont = SelectObject (hdc, infoPtr->hFont);
512 btnPtr = &infoPtr->buttons[index];
514 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
515 (btnPtr->iString > -1) &&
516 (btnPtr->iString < infoPtr->nNumStrings))
518 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
519 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
522 SelectObject (hdc, hOldFont);
523 ReleaseDC (0, hdc);
525 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
528 static void
529 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
531 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
532 TBUTTON_INFO *btnPtr;
533 INT i;
534 SIZE sz;
537 lpSize->cx = 0;
538 lpSize->cy = 0;
540 btnPtr = infoPtr->buttons;
541 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
542 if(TOOLBAR_HasText(infoPtr, btnPtr))
544 TOOLBAR_MeasureString(hwnd,i,&sz);
545 if (sz.cx > lpSize->cx)
546 lpSize->cx = sz.cx;
547 if (sz.cy > lpSize->cy)
548 lpSize->cy = sz.cy;
552 TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
555 /***********************************************************************
556 * TOOLBAR_WrapToolbar
558 * This function walks through the buttons and seperators in the
559 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
560 * wrapping should occur based on the width of the toolbar window.
561 * It does *not* calculate button placement itself. That task
562 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
563 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
564 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
567 static void
568 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
570 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
571 TBUTTON_INFO *btnPtr;
572 INT x, cx, i, j;
573 RECT rc;
574 BOOL bWrap, bButtonWrap;
576 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
577 /* no layout is necessary. Applications may use this style */
578 /* to perform their own layout on the toolbar. */
579 if( !(dwStyle & TBSTYLE_WRAPABLE) )
580 return;
582 btnPtr = infoPtr->buttons;
583 x = infoPtr->nIndent;
585 /* this can get the parents width, to know how far we can extend
586 * this toolbar. We cannot use its height, as there may be multiple
587 * toolbars in a rebar control
589 GetClientRect( GetParent(hwnd), &rc );
590 infoPtr->nWidth = rc.right - rc.left;
591 bButtonWrap = FALSE;
593 for (i = 0; i < infoPtr->nNumButtons; i++ )
595 bWrap = FALSE;
596 btnPtr[i].fsState &= ~TBSTATE_WRAP;
598 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
599 continue;
601 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
602 /* it is the actual width of the separator. This is used for */
603 /* custom controls in toolbars. */
604 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
605 cx = (btnPtr[i].iBitmap > 0) ?
606 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
607 else
608 cx = infoPtr->nButtonWidth;
610 /* Two or more adjacent separators form a separator group. */
611 /* The first separator in a group should be wrapped to the */
612 /* next row if the previous wrapping is on a button. */
613 if( bButtonWrap &&
614 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
615 (i + 1 < infoPtr->nNumButtons ) &&
616 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
618 btnPtr[i].fsState |= TBSTATE_WRAP;
619 x = infoPtr->nIndent;
620 i++;
621 bButtonWrap = FALSE;
622 continue;
625 /* The layout makes sure the bitmap is visible, but not the button. */
626 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
627 > infoPtr->nWidth )
629 BOOL bFound = FALSE;
631 /* If the current button is a separator and not hidden, */
632 /* go to the next until it reaches a non separator. */
633 /* Wrap the last separator if it is before a button. */
634 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
635 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
636 i < infoPtr->nNumButtons )
638 i++;
639 bFound = TRUE;
642 if( bFound && i < infoPtr->nNumButtons )
644 i--;
645 btnPtr[i].fsState |= TBSTATE_WRAP;
646 x = infoPtr->nIndent;
647 bButtonWrap = FALSE;
648 continue;
650 else if ( i >= infoPtr->nNumButtons)
651 break;
653 /* If the current button is not a separator, find the last */
654 /* separator and wrap it. */
655 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
657 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
658 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
660 bFound = TRUE;
661 i = j;
662 x = infoPtr->nIndent;
663 btnPtr[j].fsState |= TBSTATE_WRAP;
664 bButtonWrap = FALSE;
665 break;
669 /* If no separator available for wrapping, wrap one of */
670 /* non-hidden previous button. */
671 if (!bFound)
673 for ( j = i - 1;
674 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
676 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
677 continue;
679 bFound = TRUE;
680 i = j;
681 x = infoPtr->nIndent;
682 btnPtr[j].fsState |= TBSTATE_WRAP;
683 bButtonWrap = TRUE;
684 break;
688 /* If all above failed, wrap the current button. */
689 if (!bFound)
691 btnPtr[i].fsState |= TBSTATE_WRAP;
692 bFound = TRUE;
693 x = infoPtr->nIndent;
694 if (btnPtr[i].fsState & TBSTYLE_SEP )
695 bButtonWrap = FALSE;
696 else
697 bButtonWrap = TRUE;
700 else
701 x += cx;
706 /***********************************************************************
707 * TOOLBAR_CalcToolbar
709 * This function calculates button and separator placement. It first
710 * calculates the button sizes, gets the toolbar window width and then
711 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
712 * on. It assigns a new location to each item and sends this location to
713 * the tooltip window if appropriate. Finally, it updates the rcBound
714 * rect and calculates the new required toolbar window height.
717 static void
718 TOOLBAR_CalcToolbar (HWND hwnd)
720 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
721 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
722 TBUTTON_INFO *btnPtr;
723 INT i, nRows, nSepRows;
724 INT x, y, cx, cy;
725 SIZE sizeString;
726 BOOL bWrap;
727 BOOL usesBitmaps = FALSE;
728 BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
730 TOOLBAR_CalcStrings (hwnd, &sizeString);
732 if (dwStyle & TBSTYLE_LIST)
734 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
735 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
737 else {
738 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
740 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
741 usesBitmaps = TRUE;
744 if (sizeString.cy > 0)
746 if (usesBitmaps)
747 infoPtr->nButtonHeight = sizeString.cy +
748 infoPtr->nBitmapHeight + 6;
749 else
750 infoPtr->nButtonHeight = sizeString.cy + 6;
752 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
753 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
755 if (sizeString.cx > infoPtr->nBitmapWidth)
756 infoPtr->nButtonWidth = sizeString.cx + 6;
757 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
758 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
761 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
762 infoPtr->nButtonWidth = infoPtr->cxMin;
763 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
764 infoPtr->nButtonWidth = infoPtr->cxMax;
766 TOOLBAR_WrapToolbar( hwnd, dwStyle );
768 x = infoPtr->nIndent;
769 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
772 * We will set the height below, and we set the width on entry
773 * so we do not reset them here..
775 #if 0
776 GetClientRect( hwnd, &rc );
777 /* get initial values for toolbar */
778 infoPtr->nWidth = rc.right - rc.left;
779 infoPtr->nHeight = rc.bottom - rc.top;
780 #endif
782 /* from above, minimum is a button, and possible text */
783 cx = infoPtr->nButtonWidth;
785 /* cannot use just ButtonHeight, we may have no buttons! */
786 if (infoPtr->nNumButtons > 0)
787 infoPtr->nHeight = infoPtr->nButtonHeight;
789 cy = infoPtr->nHeight;
791 nRows = nSepRows = 0;
793 infoPtr->rcBound.top = y;
794 infoPtr->rcBound.left = x;
795 infoPtr->rcBound.bottom = y + cy;
796 infoPtr->rcBound.right = x;
798 btnPtr = infoPtr->buttons;
800 /* do not base height/width on parent, if the parent is a */
801 /* rebar control it could have multiple rows of toolbars */
802 /* GetClientRect( GetParent(hwnd), &rc ); */
803 /* cx = rc.right - rc.left; */
804 /* cy = rc.bottom - rc.top; */
806 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
808 bWrap = FALSE;
809 if (btnPtr->fsState & TBSTATE_HIDDEN)
811 SetRectEmpty (&btnPtr->rect);
812 continue;
815 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
816 /* it is the actual width of the separator. This is used for */
817 /* custom controls in toolbars. */
818 if (btnPtr->fsStyle & TBSTYLE_SEP)
819 cx = (btnPtr->iBitmap > 0) ?
820 btnPtr->iBitmap : SEPARATOR_WIDTH;
821 else
823 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
825 SIZE sz;
826 TOOLBAR_MeasureString(hwnd,i,&sz);
827 cx = sz.cx + 6;
829 else
830 cx = infoPtr->nButtonWidth;
832 if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
833 cx += DDARROW_WIDTH;
835 cy = infoPtr->nHeight;
837 if (btnPtr->fsState & TBSTATE_WRAP )
838 bWrap = TRUE;
840 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
842 if (infoPtr->rcBound.left > x)
843 infoPtr->rcBound.left = x;
844 if (infoPtr->rcBound.right < x + cx)
845 infoPtr->rcBound.right = x + cx;
846 if (infoPtr->rcBound.bottom < y + cy)
847 infoPtr->rcBound.bottom = y + cy;
849 /* Set the toolTip only for non-hidden, non-separator button */
850 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
852 TTTOOLINFOA ti;
854 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
855 ti.cbSize = sizeof(TTTOOLINFOA);
856 ti.hwnd = hwnd;
857 ti.uId = btnPtr->idCommand;
858 ti.rect = btnPtr->rect;
859 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
860 0, (LPARAM)&ti);
863 /* btnPtr->nRow is zero based. The space between the rows is */
864 /* also considered as a row. */
865 btnPtr->nRow = nRows + nSepRows;
866 if( bWrap )
868 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
869 y += cy;
870 else
872 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
873 /* it is the actual width of the separator. This is used for */
874 /* custom controls in toolbars. */
875 y += cy + ( (btnPtr->iBitmap > 0 ) ?
876 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
878 /* nSepRows is used to calculate the extra height follwoing */
879 /* the last row. */
880 nSepRows++;
882 x = infoPtr->nIndent;
883 nRows++;
885 else
886 x += cx;
889 /* infoPtr->nRows is the number of rows on the toolbar */
890 infoPtr->nRows = nRows + nSepRows + 1;
892 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
893 /* the last row. */
894 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
895 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
896 nSepRows * (infoPtr->nBitmapHeight + 1) +
897 BOTTOM_BORDER;
898 TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
902 static INT
903 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
905 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
906 TBUTTON_INFO *btnPtr;
907 INT i;
909 btnPtr = infoPtr->buttons;
910 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
911 if (btnPtr->fsState & TBSTATE_HIDDEN)
912 continue;
914 if (btnPtr->fsStyle & TBSTYLE_SEP) {
915 if (PtInRect (&btnPtr->rect, *lpPt)) {
916 TRACE(" ON SEPARATOR %d!\n", i);
917 return -i;
920 else {
921 if (PtInRect (&btnPtr->rect, *lpPt)) {
922 TRACE(" ON BUTTON %d!\n", i);
923 return i;
928 TRACE(" NOWHERE!\n");
929 return -1;
933 static INT
934 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
936 TBUTTON_INFO *btnPtr;
937 INT i;
939 btnPtr = infoPtr->buttons;
940 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
941 if (btnPtr->idCommand == idCommand) {
942 TRACE("command=%d index=%d\n", idCommand, i);
943 return i;
946 TRACE("no index found for command=%d\n", idCommand);
947 return -1;
951 static INT
952 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
954 TBUTTON_INFO *btnPtr;
955 INT nRunIndex;
957 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
958 return -1;
960 /* check index button */
961 btnPtr = &infoPtr->buttons[nIndex];
962 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
963 if (btnPtr->fsState & TBSTATE_CHECKED)
964 return nIndex;
967 /* check previous buttons */
968 nRunIndex = nIndex - 1;
969 while (nRunIndex >= 0) {
970 btnPtr = &infoPtr->buttons[nRunIndex];
971 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
972 if (btnPtr->fsState & TBSTATE_CHECKED)
973 return nRunIndex;
975 else
976 break;
977 nRunIndex--;
980 /* check next buttons */
981 nRunIndex = nIndex + 1;
982 while (nRunIndex < infoPtr->nNumButtons) {
983 btnPtr = &infoPtr->buttons[nRunIndex];
984 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
985 if (btnPtr->fsState & TBSTATE_CHECKED)
986 return nRunIndex;
988 else
989 break;
990 nRunIndex++;
993 return -1;
997 static VOID
998 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
999 WPARAM wParam, LPARAM lParam)
1001 MSG msg;
1003 msg.hwnd = hwndMsg;
1004 msg.message = uMsg;
1005 msg.wParam = wParam;
1006 msg.lParam = lParam;
1007 msg.time = GetMessageTime ();
1008 msg.pt.x = LOWORD(GetMessagePos ());
1009 msg.pt.y = HIWORD(GetMessagePos ());
1011 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1015 /***********************************************************************
1016 * TOOLBAR_CustomizeDialogProc
1017 * This function implements the toolbar customization dialog.
1019 static BOOL WINAPI
1020 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1022 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
1023 static HDSA hDsa = NULL;
1025 switch (uMsg)
1027 case WM_INITDIALOG:
1028 infoPtr = (TOOLBAR_INFO *)lParam;
1029 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
1031 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
1033 if (infoPtr)
1035 TBUTTON_INFO *btnPtr;
1036 INT i;
1038 /* insert 'virtual' separator button into 'available buttons' list */
1039 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1041 /* copy all buttons and append them to the right listbox */
1042 btnPtr = infoPtr->buttons;
1043 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
1045 DSA_InsertItem (hDsa, i, btnPtr);
1047 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
1048 if (btnPtr->fsState & TBSTATE_HIDDEN)
1050 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1052 else
1054 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
1058 /* append 'virtual' separator button to the 'toolbar buttons' list */
1059 /* TODO */
1061 return TRUE;
1063 case WM_CLOSE:
1064 EndDialog(hwnd, FALSE);
1065 return TRUE;
1067 case WM_COMMAND:
1068 switch (LOWORD(wParam))
1070 case IDCANCEL:
1071 EndDialog(hwnd, FALSE);
1072 break;
1074 return TRUE;
1076 case WM_DESTROY:
1077 if (hDsa)
1078 DSA_Destroy (hDsa);
1079 return TRUE;
1081 case WM_DRAWITEM:
1082 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1084 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1085 TBUTTON_INFO btnPtr;
1086 RECT rcButton;
1087 RECT rcText;
1088 HPEN hOldPen;
1089 HBRUSH hOldBrush;
1090 COLORREF oldText = 0;
1091 COLORREF oldBk = 0;
1093 FIXME("action: %x itemState: %x\n",
1094 lpdis->itemAction, lpdis->itemState);
1096 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
1098 if (lpdis->itemState & ODS_FOCUS)
1100 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
1101 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
1104 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1105 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1107 /* fill background rectangle */
1108 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1109 lpdis->rcItem.right, lpdis->rcItem.bottom);
1111 /* calculate button and text rectangles */
1112 CopyRect (&rcButton, &lpdis->rcItem);
1113 InflateRect (&rcButton, -1, -1);
1114 CopyRect (&rcText, &rcButton);
1115 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
1116 rcText.left = rcButton.right + 2;
1118 /* draw focus rectangle */
1119 if (lpdis->itemState & ODS_FOCUS)
1120 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1122 /* draw button */
1123 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1125 /* draw image and text */
1126 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
1128 /* virtual separator in the 'available' list */
1129 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
1130 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1132 else
1134 /* real button */
1136 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
1137 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
1139 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
1140 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1144 if (lpdis->itemState & ODS_FOCUS)
1146 SetBkColor (lpdis->hDC, oldBk);
1147 SetTextColor (lpdis->hDC, oldText);
1150 SelectObject (lpdis->hDC, hOldBrush);
1151 SelectObject (lpdis->hDC, hOldPen);
1153 return TRUE;
1155 return FALSE;
1157 case WM_MEASUREITEM:
1158 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1160 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1162 if (infoPtr)
1163 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
1164 else
1165 lpmis->itemHeight = 15 + 8; /* default height */
1167 return TRUE;
1169 return FALSE;
1171 default:
1172 return FALSE;
1177 /***********************************************************************
1178 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1181 static LRESULT
1182 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1184 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1185 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1186 INT nIndex = 0, nButtons, nCount;
1187 HBITMAP hbmLoad;
1189 TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1190 if (!lpAddBmp)
1191 return -1;
1193 if (lpAddBmp->hInst == HINST_COMMCTRL)
1195 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1196 nButtons = 15;
1197 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1198 nButtons = 13;
1199 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1200 nButtons = 5;
1201 else
1202 return -1;
1204 TRACE ("adding %d internal bitmaps!\n", nButtons);
1206 /* Windows resize all the buttons to the size of a newly added standard image */
1207 if (lpAddBmp->nID & 1)
1209 /* large icons */
1210 /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap
1211 * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this
1213 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1214 MAKELPARAM((WORD)24, (WORD)24));
1215 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1216 MAKELPARAM((WORD)31, (WORD)30));
1218 else
1220 /* small icons */
1221 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1222 MAKELPARAM((WORD)16, (WORD)16));
1223 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1224 MAKELPARAM((WORD)22, (WORD)22));
1227 else
1229 nButtons = (INT)wParam;
1230 if (nButtons <= 0)
1231 return -1;
1233 TRACE ("adding %d bitmaps!\n", nButtons);
1236 if (!(infoPtr->himlDef)) {
1237 /* create new default image list */
1238 TRACE ("creating default image list!\n");
1240 infoPtr->himlDef =
1241 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1242 ILC_COLOR | ILC_MASK, nButtons, 2);
1243 infoPtr->himlInt = infoPtr->himlDef;
1246 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1248 /* Add bitmaps to the default image list */
1249 if (lpAddBmp->hInst == (HINSTANCE)0)
1251 nIndex =
1252 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1253 CLR_DEFAULT);
1255 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1257 /* Add system bitmaps */
1258 switch (lpAddBmp->nID)
1260 case IDB_STD_SMALL_COLOR:
1261 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1262 MAKEINTRESOURCEA(IDB_STD_SMALL));
1263 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1264 hbmLoad, CLR_DEFAULT);
1265 DeleteObject (hbmLoad);
1266 break;
1268 case IDB_STD_LARGE_COLOR:
1269 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1270 MAKEINTRESOURCEA(IDB_STD_LARGE));
1271 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1272 hbmLoad, CLR_DEFAULT);
1273 DeleteObject (hbmLoad);
1274 break;
1276 case IDB_VIEW_SMALL_COLOR:
1277 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1278 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1279 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1280 hbmLoad, CLR_DEFAULT);
1281 DeleteObject (hbmLoad);
1282 break;
1284 case IDB_VIEW_LARGE_COLOR:
1285 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1286 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1287 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1288 hbmLoad, CLR_DEFAULT);
1289 DeleteObject (hbmLoad);
1290 break;
1292 case IDB_HIST_SMALL_COLOR:
1293 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1294 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1295 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1296 hbmLoad, CLR_DEFAULT);
1297 DeleteObject (hbmLoad);
1298 break;
1300 case IDB_HIST_LARGE_COLOR:
1301 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1302 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1303 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1304 hbmLoad, CLR_DEFAULT);
1305 DeleteObject (hbmLoad);
1306 break;
1308 default:
1309 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1310 ERR ("invalid imagelist!\n");
1311 break;
1314 else
1316 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1317 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1318 DeleteObject (hbmLoad);
1321 if (nIndex != -1)
1323 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1325 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1327 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",
1328 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1329 infoPtr->nNumBitmaps+nButtons,imagecount);
1331 infoPtr->nNumBitmaps = imagecount;
1333 else
1334 infoPtr->nNumBitmaps += nButtons;
1337 InvalidateRect(hwnd, NULL, FALSE);
1339 return nIndex;
1343 static LRESULT
1344 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1346 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1347 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1348 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1350 TRACE("adding %d buttons!\n", wParam);
1352 nAddButtons = (UINT)wParam;
1353 nOldButtons = infoPtr->nNumButtons;
1354 nNewButtons = nOldButtons + nAddButtons;
1356 if (infoPtr->nNumButtons == 0) {
1357 infoPtr->buttons =
1358 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1360 else {
1361 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1362 infoPtr->buttons =
1363 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1364 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1365 nOldButtons * sizeof(TBUTTON_INFO));
1366 COMCTL32_Free (oldButtons);
1369 infoPtr->nNumButtons = nNewButtons;
1371 /* insert new button data */
1372 for (nCount = 0; nCount < nAddButtons; nCount++) {
1373 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1374 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1375 btnPtr->idCommand = lpTbb[nCount].idCommand;
1376 btnPtr->fsState = lpTbb[nCount].fsState;
1377 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1378 btnPtr->dwData = lpTbb[nCount].dwData;
1379 btnPtr->iString = lpTbb[nCount].iString;
1380 btnPtr->bHot = FALSE;
1382 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1383 TTTOOLINFOA ti;
1385 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1386 ti.cbSize = sizeof (TTTOOLINFOA);
1387 ti.hwnd = hwnd;
1388 ti.uId = btnPtr->idCommand;
1389 ti.hinst = 0;
1390 ti.lpszText = LPSTR_TEXTCALLBACKA;
1392 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1393 0, (LPARAM)&ti);
1397 InvalidateRect(hwnd, NULL, FALSE);
1399 return TRUE;
1403 static LRESULT
1404 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1406 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1407 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1408 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1410 TRACE("adding %d buttons!\n", wParam);
1412 nAddButtons = (UINT)wParam;
1413 nOldButtons = infoPtr->nNumButtons;
1414 nNewButtons = nOldButtons + nAddButtons;
1416 if (infoPtr->nNumButtons == 0) {
1417 infoPtr->buttons =
1418 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1420 else {
1421 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1422 infoPtr->buttons =
1423 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1424 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1425 nOldButtons * sizeof(TBUTTON_INFO));
1426 COMCTL32_Free (oldButtons);
1429 infoPtr->nNumButtons = nNewButtons;
1431 /* insert new button data */
1432 for (nCount = 0; nCount < nAddButtons; nCount++) {
1433 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1434 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1435 btnPtr->idCommand = lpTbb[nCount].idCommand;
1436 btnPtr->fsState = lpTbb[nCount].fsState;
1437 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1438 btnPtr->dwData = lpTbb[nCount].dwData;
1439 btnPtr->iString = lpTbb[nCount].iString;
1440 btnPtr->bHot = FALSE;
1442 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1443 TTTOOLINFOW ti;
1445 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1446 ti.cbSize = sizeof (TTTOOLINFOW);
1447 ti.hwnd = hwnd;
1448 ti.uId = btnPtr->idCommand;
1449 ti.hinst = 0;
1450 ti.lpszText = LPSTR_TEXTCALLBACKW;
1452 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1453 0, (LPARAM)&ti);
1457 InvalidateRect(hwnd, NULL, FALSE);
1459 return TRUE;
1463 static LRESULT
1464 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1466 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1467 INT nIndex;
1469 if ((wParam) && (HIWORD(lParam) == 0)) {
1470 char szString[256];
1471 INT len;
1472 TRACE("adding string from resource!\n");
1474 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1475 szString, 256);
1477 TRACE("len=%d \"%s\"\n", len, szString);
1478 nIndex = infoPtr->nNumStrings;
1479 if (infoPtr->nNumStrings == 0) {
1480 infoPtr->strings =
1481 COMCTL32_Alloc (sizeof(LPWSTR));
1483 else {
1484 LPWSTR *oldStrings = infoPtr->strings;
1485 infoPtr->strings =
1486 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1487 memcpy (&infoPtr->strings[0], &oldStrings[0],
1488 sizeof(LPWSTR) * infoPtr->nNumStrings);
1489 COMCTL32_Free (oldStrings);
1492 infoPtr->strings[infoPtr->nNumStrings] =
1493 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1494 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1495 infoPtr->nNumStrings++;
1497 else {
1498 LPSTR p = (LPSTR)lParam;
1499 INT len;
1501 if (p == NULL)
1502 return -1;
1503 TRACE("adding string(s) from array!\n");
1505 nIndex = infoPtr->nNumStrings;
1506 while (*p) {
1507 len = lstrlenA (p);
1508 TRACE("len=%d \"%s\"\n", len, p);
1510 if (infoPtr->nNumStrings == 0) {
1511 infoPtr->strings =
1512 COMCTL32_Alloc (sizeof(LPWSTR));
1514 else {
1515 LPWSTR *oldStrings = infoPtr->strings;
1516 infoPtr->strings =
1517 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1518 memcpy (&infoPtr->strings[0], &oldStrings[0],
1519 sizeof(LPWSTR) * infoPtr->nNumStrings);
1520 COMCTL32_Free (oldStrings);
1523 infoPtr->strings[infoPtr->nNumStrings] =
1524 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1525 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1526 infoPtr->nNumStrings++;
1528 p += (len+1);
1532 return nIndex;
1536 static LRESULT
1537 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1539 #define MAX_RESOURCE_STRING_LENGTH 512
1540 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1541 INT nIndex;
1543 if ((wParam) && (HIWORD(lParam) == 0)) {
1544 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1545 INT len;
1546 TRACE("adding string from resource!\n");
1548 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1549 szString, MAX_RESOURCE_STRING_LENGTH);
1551 TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1552 TRACE("First char: 0x%x\n", *szString);
1553 if (szString[0] == L'|')
1555 PWSTR p = szString + 1;
1557 nIndex = infoPtr->nNumStrings;
1558 while (*p != L'|') {
1560 if (infoPtr->nNumStrings == 0) {
1561 infoPtr->strings =
1562 COMCTL32_Alloc (sizeof(LPWSTR));
1564 else {
1565 LPWSTR *oldStrings = infoPtr->strings;
1566 infoPtr->strings =
1567 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1568 memcpy (&infoPtr->strings[0], &oldStrings[0],
1569 sizeof(LPWSTR) * infoPtr->nNumStrings);
1570 COMCTL32_Free (oldStrings);
1573 len = COMCTL32_StrChrW (p, L'|') - p;
1574 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1575 infoPtr->strings[infoPtr->nNumStrings] =
1576 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1577 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1578 infoPtr->nNumStrings++;
1580 p += (len+1);
1583 else
1585 nIndex = infoPtr->nNumStrings;
1586 if (infoPtr->nNumStrings == 0) {
1587 infoPtr->strings =
1588 COMCTL32_Alloc (sizeof(LPWSTR));
1590 else {
1591 LPWSTR *oldStrings = infoPtr->strings;
1592 infoPtr->strings =
1593 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1594 memcpy (&infoPtr->strings[0], &oldStrings[0],
1595 sizeof(LPWSTR) * infoPtr->nNumStrings);
1596 COMCTL32_Free (oldStrings);
1599 infoPtr->strings[infoPtr->nNumStrings] =
1600 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1601 strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1602 infoPtr->nNumStrings++;
1605 else {
1606 LPWSTR p = (LPWSTR)lParam;
1607 INT len;
1609 if (p == NULL)
1610 return -1;
1611 TRACE("adding string(s) from array!\n");
1612 nIndex = infoPtr->nNumStrings;
1613 while (*p) {
1614 len = lstrlenW (p);
1616 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1617 if (infoPtr->nNumStrings == 0) {
1618 infoPtr->strings =
1619 COMCTL32_Alloc (sizeof(LPWSTR));
1621 else {
1622 LPWSTR *oldStrings = infoPtr->strings;
1623 infoPtr->strings =
1624 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1625 memcpy (&infoPtr->strings[0], &oldStrings[0],
1626 sizeof(LPWSTR) * infoPtr->nNumStrings);
1627 COMCTL32_Free (oldStrings);
1630 infoPtr->strings[infoPtr->nNumStrings] =
1631 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1632 strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1633 infoPtr->nNumStrings++;
1635 p += (len+1);
1639 return nIndex;
1643 static LRESULT
1644 TOOLBAR_AutoSize (HWND hwnd)
1646 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1647 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1648 RECT parent_rect;
1649 RECT window_rect;
1650 HWND parent;
1651 INT x, y;
1652 INT cx, cy;
1653 UINT uPosFlags = SWP_NOZORDER;
1655 TRACE("resize forced, style=%lx!\n", dwStyle);
1657 parent = GetParent (hwnd);
1658 GetClientRect(parent, &parent_rect);
1660 x = parent_rect.left;
1661 y = parent_rect.top;
1663 /* FIXME: we should be able to early out if nothing */
1664 /* has changed with nWidth != parent_rect width */
1666 if (dwStyle & CCS_NORESIZE) {
1667 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1668 cx = 0;
1669 cy = 0;
1671 else {
1672 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1673 InvalidateRect( hwnd, NULL, TRUE );
1674 cy = infoPtr->nHeight;
1675 cx = infoPtr->nWidth;
1677 if (dwStyle & CCS_NOMOVEY) {
1678 GetWindowRect(hwnd, &window_rect);
1679 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1680 y = window_rect.top;
1684 if (dwStyle & CCS_NOPARENTALIGN)
1685 uPosFlags |= SWP_NOMOVE;
1687 if (!(dwStyle & CCS_NODIVIDER))
1688 cy += GetSystemMetrics(SM_CYEDGE);
1690 if (dwStyle & WS_BORDER)
1692 x = y = 1;
1693 cy += GetSystemMetrics(SM_CYEDGE);
1694 cx += GetSystemMetrics(SM_CYEDGE);
1697 infoPtr->bAutoSize = TRUE;
1698 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1699 cx, cy, uPosFlags);
1700 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1701 * the setwindowpos calls */
1702 infoPtr->bAutoSize = FALSE;
1704 return 0;
1708 static LRESULT
1709 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1711 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1713 return infoPtr->nNumButtons;
1717 static LRESULT
1718 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1720 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1722 if (infoPtr == NULL) {
1723 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1724 ERR("infoPtr == NULL!\n");
1725 return 0;
1728 infoPtr->dwStructSize = (DWORD)wParam;
1730 return 0;
1734 static LRESULT
1735 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1737 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1738 TBUTTON_INFO *btnPtr;
1739 INT nIndex;
1741 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1742 if (nIndex == -1)
1743 return FALSE;
1745 btnPtr = &infoPtr->buttons[nIndex];
1746 btnPtr->iBitmap = LOWORD(lParam);
1748 /* we HAVE to erase the background, the new bitmap could be */
1749 /* transparent */
1750 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1752 return TRUE;
1756 static LRESULT
1757 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1759 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1760 TBUTTON_INFO *btnPtr;
1761 INT nIndex;
1762 INT nOldIndex = -1;
1763 BOOL bChecked = FALSE;
1765 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1766 if (nIndex == -1)
1767 return FALSE;
1769 btnPtr = &infoPtr->buttons[nIndex];
1771 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1772 return FALSE;
1774 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1776 if (LOWORD(lParam) == FALSE)
1777 btnPtr->fsState &= ~TBSTATE_CHECKED;
1778 else {
1779 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1780 nOldIndex =
1781 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1782 if (nOldIndex == nIndex)
1783 return 0;
1784 if (nOldIndex != -1)
1785 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1787 btnPtr->fsState |= TBSTATE_CHECKED;
1790 if( bChecked != LOWORD(lParam) )
1792 if (nOldIndex != -1)
1794 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
1795 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
1797 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1800 /* FIXME: Send a WM_NOTIFY?? */
1802 return TRUE;
1806 static LRESULT
1807 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1809 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1811 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1815 static LRESULT
1816 TOOLBAR_Customize (HWND hwnd)
1818 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1819 LRESULT ret;
1820 LPCVOID template;
1821 HRSRC hRes;
1822 NMHDR nmhdr;
1824 /* send TBN_BEGINADJUST notification */
1825 nmhdr.hwndFrom = hwnd;
1826 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1827 nmhdr.code = TBN_BEGINADJUST;
1829 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1830 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1832 if (!(hRes = FindResourceA (COMCTL32_hModule,
1833 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1834 RT_DIALOGA)))
1835 return FALSE;
1837 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1838 return FALSE;
1840 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1841 (LPDLGTEMPLATEA)template,
1842 hwnd,
1843 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1844 (LPARAM)infoPtr);
1846 /* send TBN_ENDADJUST notification */
1847 nmhdr.code = TBN_ENDADJUST;
1849 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1850 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1852 return ret;
1856 static LRESULT
1857 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1859 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1860 INT nIndex = (INT)wParam;
1862 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1863 return FALSE;
1865 if ((infoPtr->hwndToolTip) &&
1866 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1867 TTTOOLINFOA ti;
1869 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1870 ti.cbSize = sizeof (TTTOOLINFOA);
1871 ti.hwnd = hwnd;
1872 ti.uId = infoPtr->buttons[nIndex].idCommand;
1874 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1877 if (infoPtr->nNumButtons == 1) {
1878 TRACE(" simple delete!\n");
1879 COMCTL32_Free (infoPtr->buttons);
1880 infoPtr->buttons = NULL;
1881 infoPtr->nNumButtons = 0;
1883 else {
1884 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1885 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1887 infoPtr->nNumButtons--;
1888 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1889 if (nIndex > 0) {
1890 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1891 nIndex * sizeof(TBUTTON_INFO));
1894 if (nIndex < infoPtr->nNumButtons) {
1895 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1896 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1899 COMCTL32_Free (oldButtons);
1902 InvalidateRect (hwnd, NULL, TRUE);
1904 return TRUE;
1908 static LRESULT
1909 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1911 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1912 TBUTTON_INFO *btnPtr;
1913 INT nIndex;
1914 DWORD bState;
1916 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1917 if (nIndex == -1)
1918 return FALSE;
1920 btnPtr = &infoPtr->buttons[nIndex];
1922 bState = btnPtr->fsState & TBSTATE_ENABLED;
1924 /* update the toolbar button state */
1925 if(LOWORD(lParam) == FALSE) {
1926 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1927 } else {
1928 btnPtr->fsState |= TBSTATE_ENABLED;
1931 /* redraw the button only if the state of the button changed */
1932 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
1934 InvalidateRect(hwnd, &btnPtr->rect,
1935 TOOLBAR_HasText(infoPtr, btnPtr));
1938 return TRUE;
1942 static inline LRESULT
1943 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1945 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1947 return infoPtr->bAnchor;
1951 static LRESULT
1952 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1954 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1955 INT nIndex;
1957 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1958 if (nIndex == -1)
1959 return -1;
1961 return infoPtr->buttons[nIndex].iBitmap;
1965 static inline LRESULT
1966 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1968 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1972 static LRESULT
1973 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1975 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1976 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1977 INT nIndex = (INT)wParam;
1978 TBUTTON_INFO *btnPtr;
1980 if (infoPtr == NULL)
1981 return FALSE;
1983 if (lpTbb == NULL)
1984 return FALSE;
1986 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1987 return FALSE;
1989 btnPtr = &infoPtr->buttons[nIndex];
1990 lpTbb->iBitmap = btnPtr->iBitmap;
1991 lpTbb->idCommand = btnPtr->idCommand;
1992 lpTbb->fsState = btnPtr->fsState;
1993 lpTbb->fsStyle = btnPtr->fsStyle;
1994 lpTbb->dwData = btnPtr->dwData;
1995 lpTbb->iString = btnPtr->iString;
1997 return TRUE;
2001 static LRESULT
2002 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2004 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2005 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2006 TBUTTON_INFO *btnPtr;
2007 INT nIndex;
2009 if (infoPtr == NULL)
2010 return -1;
2011 if (lpTbInfo == NULL)
2012 return -1;
2013 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2014 return -1;
2016 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2017 if (nIndex == -1)
2018 return -1;
2020 btnPtr = &infoPtr->buttons[nIndex];
2022 if (lpTbInfo->dwMask & TBIF_COMMAND)
2023 lpTbInfo->idCommand = btnPtr->idCommand;
2024 if (lpTbInfo->dwMask & TBIF_IMAGE)
2025 lpTbInfo->iImage = btnPtr->iBitmap;
2026 if (lpTbInfo->dwMask & TBIF_LPARAM)
2027 lpTbInfo->lParam = btnPtr->dwData;
2028 if (lpTbInfo->dwMask & TBIF_SIZE)
2029 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2030 if (lpTbInfo->dwMask & TBIF_STATE)
2031 lpTbInfo->fsState = btnPtr->fsState;
2032 if (lpTbInfo->dwMask & TBIF_STYLE)
2033 lpTbInfo->fsStyle = btnPtr->fsStyle;
2034 if (lpTbInfo->dwMask & TBIF_TEXT) {
2035 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2037 lstrcpynWtoA (lpTbInfo->pszText,
2038 (LPWSTR)infoPtr->strings[btnPtr->iString],
2039 lpTbInfo->cchText);
2041 else lpTbInfo->pszText[0]=0;
2043 return nIndex;
2047 static LRESULT
2048 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2050 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2051 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2052 TBUTTON_INFO *btnPtr;
2053 INT nIndex;
2055 if (infoPtr == NULL)
2056 return -1;
2057 if (lpTbInfo == NULL)
2058 return -1;
2059 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2060 return -1;
2062 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2063 if (nIndex == -1)
2064 return -1;
2066 btnPtr = &infoPtr->buttons[nIndex];
2068 if (lpTbInfo->dwMask & TBIF_COMMAND)
2069 lpTbInfo->idCommand = btnPtr->idCommand;
2070 if (lpTbInfo->dwMask & TBIF_IMAGE)
2071 lpTbInfo->iImage = btnPtr->iBitmap;
2072 if (lpTbInfo->dwMask & TBIF_LPARAM)
2073 lpTbInfo->lParam = btnPtr->dwData;
2074 if (lpTbInfo->dwMask & TBIF_SIZE)
2075 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2076 if (lpTbInfo->dwMask & TBIF_STATE)
2077 lpTbInfo->fsState = btnPtr->fsState;
2078 if (lpTbInfo->dwMask & TBIF_STYLE)
2079 lpTbInfo->fsStyle = btnPtr->fsStyle;
2080 if (lpTbInfo->dwMask & TBIF_TEXT) {
2081 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2082 lstrcpynW (lpTbInfo->pszText,
2083 (LPWSTR)infoPtr->strings[btnPtr->iString],
2084 lpTbInfo->cchText);
2087 return nIndex;
2091 static LRESULT
2092 TOOLBAR_GetButtonSize (HWND hwnd)
2094 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2096 return MAKELONG((WORD)infoPtr->nButtonWidth,
2097 (WORD)infoPtr->nButtonHeight);
2101 static LRESULT
2102 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2104 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2105 INT nIndex, nStringIndex;
2107 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2108 if (nIndex == -1)
2109 return -1;
2111 nStringIndex = infoPtr->buttons[nIndex].iString;
2113 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2115 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2116 return -1;
2118 if (lParam == 0)
2119 return -1;
2121 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2123 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2127 static LRESULT
2128 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2130 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2131 INT nIndex, nStringIndex;
2133 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2134 if (nIndex == -1)
2135 return -1;
2137 nStringIndex = infoPtr->buttons[nIndex].iString;
2139 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2141 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2142 return -1;
2144 if (lParam == 0)
2145 return -1;
2147 strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2149 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2153 /* << TOOLBAR_GetColorScheme >> */
2156 static LRESULT
2157 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2159 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2161 return (LRESULT)infoPtr->himlDis;
2165 inline static LRESULT
2166 TOOLBAR_GetExtendedStyle (HWND hwnd)
2168 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2170 return infoPtr->dwExStyle;
2174 static LRESULT
2175 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2177 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2179 return (LRESULT)infoPtr->himlHot;
2183 static LRESULT
2184 TOOLBAR_GetHotItem (HWND hwnd)
2186 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2188 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2189 return -1;
2191 if (infoPtr->nHotItem < 0)
2192 return -1;
2194 return (LRESULT)infoPtr->nHotItem;
2198 static LRESULT
2199 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2201 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2203 return (LRESULT)infoPtr->himlDef;
2207 /* << TOOLBAR_GetInsertMark >> */
2208 /* << TOOLBAR_GetInsertMarkColor >> */
2211 static LRESULT
2212 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2214 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2215 TBUTTON_INFO *btnPtr;
2216 LPRECT lpRect;
2217 INT nIndex;
2219 if (infoPtr == NULL)
2220 return FALSE;
2221 nIndex = (INT)wParam;
2222 btnPtr = &infoPtr->buttons[nIndex];
2223 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2224 return FALSE;
2225 lpRect = (LPRECT)lParam;
2226 if (lpRect == NULL)
2227 return FALSE;
2228 if (btnPtr->fsState & TBSTATE_HIDDEN)
2229 return FALSE;
2231 lpRect->left = btnPtr->rect.left;
2232 lpRect->right = btnPtr->rect.right;
2233 lpRect->bottom = btnPtr->rect.bottom;
2234 lpRect->top = btnPtr->rect.top;
2236 return TRUE;
2240 static LRESULT
2241 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2243 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2244 LPSIZE lpSize = (LPSIZE)lParam;
2246 if (lpSize == NULL)
2247 return FALSE;
2249 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2250 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2252 TRACE("maximum size %d x %d\n",
2253 infoPtr->rcBound.right - infoPtr->rcBound.left,
2254 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2256 return TRUE;
2260 /* << TOOLBAR_GetObject >> */
2261 /* << TOOLBAR_GetPadding >> */
2264 static LRESULT
2265 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2267 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2268 TBUTTON_INFO *btnPtr;
2269 LPRECT lpRect;
2270 INT nIndex;
2272 if (infoPtr == NULL)
2273 return FALSE;
2274 nIndex = (INT)wParam;
2275 btnPtr = &infoPtr->buttons[nIndex];
2276 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2277 return FALSE;
2278 lpRect = (LPRECT)lParam;
2279 if (lpRect == NULL)
2280 return FALSE;
2282 lpRect->left = btnPtr->rect.left;
2283 lpRect->right = btnPtr->rect.right;
2284 lpRect->bottom = btnPtr->rect.bottom;
2285 lpRect->top = btnPtr->rect.top;
2287 return TRUE;
2291 static LRESULT
2292 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2294 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2296 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2297 return infoPtr->nRows;
2298 else
2299 return 1;
2303 static LRESULT
2304 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2306 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2307 INT nIndex;
2309 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2310 if (nIndex == -1)
2311 return -1;
2313 return infoPtr->buttons[nIndex].fsState;
2317 static LRESULT
2318 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2320 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2321 INT nIndex;
2323 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2324 if (nIndex == -1)
2325 return -1;
2327 return infoPtr->buttons[nIndex].fsStyle;
2331 static LRESULT
2332 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2334 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2336 if (infoPtr == NULL)
2337 return 0;
2339 return infoPtr->nMaxTextRows;
2343 static LRESULT
2344 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2346 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2348 if (infoPtr == NULL)
2349 return 0;
2350 return infoPtr->hwndToolTip;
2354 static LRESULT
2355 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2357 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2359 TRACE("%s hwnd=0x%x stub!\n",
2360 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2362 return infoPtr->bUnicode;
2366 inline static LRESULT
2367 TOOLBAR_GetVersion (HWND hwnd)
2369 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2370 return infoPtr->iVersion;
2374 static LRESULT
2375 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2377 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2378 TBUTTON_INFO *btnPtr;
2379 INT nIndex;
2381 TRACE("\n");
2383 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2384 if (nIndex == -1)
2385 return FALSE;
2387 btnPtr = &infoPtr->buttons[nIndex];
2388 if (LOWORD(lParam) == FALSE)
2389 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2390 else
2391 btnPtr->fsState |= TBSTATE_HIDDEN;
2393 InvalidateRect (hwnd, NULL, TRUE);
2395 return TRUE;
2399 inline static LRESULT
2400 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2402 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2406 static LRESULT
2407 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2409 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2410 TBUTTON_INFO *btnPtr;
2411 INT nIndex;
2413 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2414 if (nIndex == -1)
2415 return FALSE;
2417 btnPtr = &infoPtr->buttons[nIndex];
2418 if (LOWORD(lParam) == FALSE)
2419 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2420 else
2421 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2423 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2425 return TRUE;
2429 static LRESULT
2430 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2432 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2433 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2434 INT nIndex = (INT)wParam;
2435 TBUTTON_INFO *oldButtons;
2437 if (lpTbb == NULL)
2438 return FALSE;
2440 if (nIndex == -1) {
2441 /* EPP: this seems to be an undocumented call (from my IE4)
2442 * I assume in that case that:
2443 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2444 * - index of insertion is at the end of existing buttons
2445 * I only see this happen with nIndex == -1, but it could have a special
2446 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2448 int len;
2449 LPSTR ptr;
2451 if(lpTbb->iString) {
2452 len = lstrlenA((char*)lpTbb->iString) + 2;
2453 ptr = COMCTL32_Alloc(len);
2454 nIndex = infoPtr->nNumButtons;
2455 strcpy(ptr, (char*)lpTbb->iString);
2456 ptr[len - 1] = 0; /* ended by two '\0' */
2457 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2458 COMCTL32_Free(ptr);
2460 else {
2461 ERR("lpTbb->iString is NULL\n");
2462 return FALSE;
2465 } else if (nIndex < 0)
2466 return FALSE;
2468 TRACE("inserting button index=%d\n", nIndex);
2469 if (nIndex > infoPtr->nNumButtons) {
2470 nIndex = infoPtr->nNumButtons;
2471 TRACE("adjust index=%d\n", nIndex);
2474 oldButtons = infoPtr->buttons;
2475 infoPtr->nNumButtons++;
2476 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2477 /* pre insert copy */
2478 if (nIndex > 0) {
2479 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2480 nIndex * sizeof(TBUTTON_INFO));
2483 /* insert new button */
2484 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2485 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2486 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2487 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2488 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2489 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2491 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2492 TTTOOLINFOA ti;
2494 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2495 ti.cbSize = sizeof (TTTOOLINFOA);
2496 ti.hwnd = hwnd;
2497 ti.uId = lpTbb->idCommand;
2498 ti.hinst = 0;
2499 ti.lpszText = LPSTR_TEXTCALLBACKA;
2501 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2502 0, (LPARAM)&ti);
2505 /* post insert copy */
2506 if (nIndex < infoPtr->nNumButtons - 1) {
2507 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2508 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2511 COMCTL32_Free (oldButtons);
2513 InvalidateRect (hwnd, NULL, FALSE);
2515 return TRUE;
2519 static LRESULT
2520 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2522 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2523 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2524 INT nIndex = (INT)wParam;
2525 TBUTTON_INFO *oldButtons;
2527 if (lpTbb == NULL)
2528 return FALSE;
2529 if (nIndex < 0)
2530 return FALSE;
2532 TRACE("inserting button index=%d\n", nIndex);
2533 if (nIndex > infoPtr->nNumButtons) {
2534 nIndex = infoPtr->nNumButtons;
2535 TRACE("adjust index=%d\n", nIndex);
2538 oldButtons = infoPtr->buttons;
2539 infoPtr->nNumButtons++;
2540 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2541 /* pre insert copy */
2542 if (nIndex > 0) {
2543 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2544 nIndex * sizeof(TBUTTON_INFO));
2547 /* insert new button */
2548 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2549 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2550 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2551 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2552 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2553 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2555 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2556 TTTOOLINFOW ti;
2558 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2559 ti.cbSize = sizeof (TTTOOLINFOW);
2560 ti.hwnd = hwnd;
2561 ti.uId = lpTbb->idCommand;
2562 ti.hinst = 0;
2563 ti.lpszText = LPSTR_TEXTCALLBACKW;
2565 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2566 0, (LPARAM)&ti);
2569 /* post insert copy */
2570 if (nIndex < infoPtr->nNumButtons - 1) {
2571 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2572 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2575 COMCTL32_Free (oldButtons);
2577 InvalidateRect (hwnd, NULL, FALSE);
2579 return TRUE;
2583 /* << TOOLBAR_InsertMarkHitTest >> */
2586 static LRESULT
2587 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2589 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2590 INT nIndex;
2592 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2593 if (nIndex == -1)
2594 return FALSE;
2596 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2600 static LRESULT
2601 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2603 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2604 INT nIndex;
2606 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2607 if (nIndex == -1)
2608 return FALSE;
2610 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2614 static LRESULT
2615 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2617 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2618 INT nIndex;
2620 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2621 if (nIndex == -1)
2622 return FALSE;
2624 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2628 static LRESULT
2629 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2631 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2632 INT nIndex;
2634 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2635 if (nIndex == -1)
2636 return FALSE;
2638 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2642 static LRESULT
2643 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2645 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2646 INT nIndex;
2648 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2649 if (nIndex == -1)
2650 return FALSE;
2652 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2656 static LRESULT
2657 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2659 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2660 INT nIndex;
2662 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2663 if (nIndex == -1)
2664 return FALSE;
2666 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2670 /* << TOOLBAR_LoadImages >> */
2671 /* << TOOLBAR_MapAccelerator >> */
2672 /* << TOOLBAR_MarkButton >> */
2673 /* << TOOLBAR_MoveButton >> */
2676 static LRESULT
2677 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2679 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2680 TBUTTON_INFO *btnPtr;
2681 INT nIndex;
2683 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2684 if (nIndex == -1)
2685 return FALSE;
2687 btnPtr = &infoPtr->buttons[nIndex];
2688 if (LOWORD(lParam) == FALSE)
2689 btnPtr->fsState &= ~TBSTATE_PRESSED;
2690 else
2691 btnPtr->fsState |= TBSTATE_PRESSED;
2693 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2695 return TRUE;
2699 /* << TOOLBAR_ReplaceBitmap >> */
2702 static LRESULT
2703 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2705 #if 0
2706 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2707 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2709 if (lpSave == NULL) return 0;
2711 if ((BOOL)wParam) {
2712 /* save toolbar information */
2713 FIXME("save to \"%s\" \"%s\"\n",
2714 lpSave->pszSubKey, lpSave->pszValueName);
2718 else {
2719 /* restore toolbar information */
2721 FIXME("restore from \"%s\" \"%s\"\n",
2722 lpSave->pszSubKey, lpSave->pszValueName);
2726 #endif
2728 return 0;
2732 static LRESULT
2733 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2735 #if 0
2736 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2737 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2739 if (lpSave == NULL)
2740 return 0;
2742 if ((BOOL)wParam) {
2743 /* save toolbar information */
2744 FIXME("save to \"%s\" \"%s\"\n",
2745 lpSave->pszSubKey, lpSave->pszValueName);
2749 else {
2750 /* restore toolbar information */
2752 FIXME("restore from \"%s\" \"%s\"\n",
2753 lpSave->pszSubKey, lpSave->pszValueName);
2757 #endif
2759 return 0;
2763 static LRESULT
2764 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2766 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2767 BOOL bOldAnchor = infoPtr->bAnchor;
2769 infoPtr->bAnchor = (BOOL)wParam;
2771 return (LRESULT)bOldAnchor;
2775 static LRESULT
2776 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2778 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2780 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2781 return FALSE;
2783 if (infoPtr->nNumButtons > 0)
2784 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
2785 infoPtr->nNumButtons,
2786 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
2787 LOWORD(lParam), HIWORD(lParam));
2789 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2790 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2792 /* uses image list internals directly */
2793 if (infoPtr->himlDef) {
2794 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
2795 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
2798 return TRUE;
2802 static LRESULT
2803 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2805 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2806 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2807 TBUTTON_INFO *btnPtr;
2808 INT nIndex;
2810 if (lptbbi == NULL)
2811 return FALSE;
2812 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2813 return FALSE;
2815 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2816 if (nIndex == -1)
2817 return FALSE;
2819 btnPtr = &infoPtr->buttons[nIndex];
2820 if (lptbbi->dwMask & TBIF_COMMAND)
2821 btnPtr->idCommand = lptbbi->idCommand;
2822 if (lptbbi->dwMask & TBIF_IMAGE)
2823 btnPtr->iBitmap = lptbbi->iImage;
2824 if (lptbbi->dwMask & TBIF_LPARAM)
2825 btnPtr->dwData = lptbbi->lParam;
2826 /* if (lptbbi->dwMask & TBIF_SIZE) */
2827 /* btnPtr->cx = lptbbi->cx; */
2828 if (lptbbi->dwMask & TBIF_STATE)
2829 btnPtr->fsState = lptbbi->fsState;
2830 if (lptbbi->dwMask & TBIF_STYLE)
2831 btnPtr->fsStyle = lptbbi->fsStyle;
2833 if (lptbbi->dwMask & TBIF_TEXT) {
2834 if ((btnPtr->iString >= 0) ||
2835 (btnPtr->iString < infoPtr->nNumStrings)) {
2836 TRACE("Ooooooch\n");
2837 #if 0
2838 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2839 INT len = lstrlenA (lptbbi->pszText);
2840 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2841 #endif
2843 /* this is the ultimate sollution */
2844 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2848 return TRUE;
2852 static LRESULT
2853 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2855 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2856 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2857 TBUTTON_INFO *btnPtr;
2858 INT nIndex;
2860 if (lptbbi == NULL)
2861 return FALSE;
2862 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2863 return FALSE;
2865 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2866 if (nIndex == -1)
2867 return FALSE;
2869 btnPtr = &infoPtr->buttons[nIndex];
2870 if (lptbbi->dwMask & TBIF_COMMAND)
2871 btnPtr->idCommand = lptbbi->idCommand;
2872 if (lptbbi->dwMask & TBIF_IMAGE)
2873 btnPtr->iBitmap = lptbbi->iImage;
2874 if (lptbbi->dwMask & TBIF_LPARAM)
2875 btnPtr->dwData = lptbbi->lParam;
2876 /* if (lptbbi->dwMask & TBIF_SIZE) */
2877 /* btnPtr->cx = lptbbi->cx; */
2878 if (lptbbi->dwMask & TBIF_STATE)
2879 btnPtr->fsState = lptbbi->fsState;
2880 if (lptbbi->dwMask & TBIF_STYLE)
2881 btnPtr->fsStyle = lptbbi->fsStyle;
2883 if (lptbbi->dwMask & TBIF_TEXT) {
2884 if ((btnPtr->iString >= 0) ||
2885 (btnPtr->iString < infoPtr->nNumStrings)) {
2886 #if 0
2887 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2888 INT len = lstrlenW (lptbbi->pszText);
2889 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2890 #endif
2892 /* this is the ultimate solution */
2893 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2897 return TRUE;
2901 static LRESULT
2902 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2904 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2906 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2908 ERR("invalid parameter\n");
2909 return FALSE;
2912 /* Button size can only be set before adding any button to the toolbar
2913 according to the documentation. */
2914 /* this appears to be wrong. WINZIP32.EXE (ver 8) calls this on
2915 one of its buttons after adding it to the toolbar, and it
2916 checks that the return value is nonzero - mjm */
2917 if( infoPtr->nNumButtons != 0 )
2919 WARN("Button size set after button in toolbar\n");
2920 return TRUE;
2923 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2924 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2925 return TRUE;
2929 static LRESULT
2930 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2932 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2934 if (infoPtr == NULL)
2935 return FALSE;
2937 infoPtr->cxMin = (INT)LOWORD(lParam);
2938 infoPtr->cxMax = (INT)HIWORD(lParam);
2940 return TRUE;
2944 static LRESULT
2945 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2947 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2948 INT nIndex = (INT)wParam;
2950 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2951 return FALSE;
2953 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2955 if (infoPtr->hwndToolTip) {
2957 FIXME("change tool tip!\n");
2961 return TRUE;
2965 /* << TOOLBAR_SetColorScheme >> */
2968 static LRESULT
2969 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2971 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2972 HIMAGELIST himlTemp;
2975 himlTemp = infoPtr->himlDis;
2976 infoPtr->himlDis = (HIMAGELIST)lParam;
2978 /* FIXME: redraw ? */
2980 return (LRESULT)himlTemp;
2984 static LRESULT
2985 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2987 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2988 DWORD dwTemp;
2990 dwTemp = infoPtr->dwDTFlags;
2991 infoPtr->dwDTFlags =
2992 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2994 return (LRESULT)dwTemp;
2998 static LRESULT
2999 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3001 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3002 DWORD dwTemp;
3004 dwTemp = infoPtr->dwExStyle;
3005 infoPtr->dwExStyle = (DWORD)lParam;
3007 return (LRESULT)dwTemp;
3011 static LRESULT
3012 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3014 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3015 HIMAGELIST himlTemp;
3017 himlTemp = infoPtr->himlHot;
3018 infoPtr->himlHot = (HIMAGELIST)lParam;
3020 /* FIXME: redraw ? */
3022 return (LRESULT)himlTemp;
3026 static LRESULT
3027 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3029 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3030 INT nOldHotItem = infoPtr->nHotItem;
3032 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3034 infoPtr->nHotItem = (INT)wParam;
3036 /* FIXME: What else must be done ??? */
3040 if (nOldHotItem < 0)
3041 return -1;
3043 return (LRESULT)nOldHotItem;
3047 static LRESULT
3048 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3050 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3051 HIMAGELIST himlTemp;
3053 himlTemp = infoPtr->himlDef;
3054 infoPtr->himlDef = (HIMAGELIST)lParam;
3056 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3057 /* FIXME: redraw ? */
3059 return (LRESULT)himlTemp;
3063 static LRESULT
3064 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3066 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3068 TRACE("\n");
3070 /* process only on indent changing */
3071 if(infoPtr->nIndent != (INT)wParam)
3073 infoPtr->nIndent = (INT)wParam;
3074 InvalidateRect(hwnd, NULL, FALSE);
3077 return TRUE;
3081 /* << TOOLBAR_SetInsertMark >> */
3084 static LRESULT
3085 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3087 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3089 infoPtr->clrInsertMark = (COLORREF)lParam;
3091 /* FIXME : redraw ??*/
3093 return 0;
3097 static LRESULT
3098 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3100 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3102 if (infoPtr == NULL)
3103 return FALSE;
3105 infoPtr->nMaxTextRows = (INT)wParam;
3107 return TRUE;
3111 /* << TOOLBAR_SetPadding >> */
3114 static LRESULT
3115 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3117 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3118 HWND hwndOldNotify;
3120 TRACE("\n");
3122 if (infoPtr == NULL)
3123 return 0;
3124 hwndOldNotify = infoPtr->hwndNotify;
3125 infoPtr->hwndNotify = (HWND)wParam;
3127 return hwndOldNotify;
3131 static LRESULT
3132 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3134 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3135 LPRECT lprc = (LPRECT)lParam;
3137 TRACE("\n");
3139 if (LOWORD(wParam) > 1) {
3140 FIXME("multiple rows not supported!\n");
3143 if(infoPtr->nRows != LOWORD(wParam))
3145 infoPtr->nRows = LOWORD(wParam);
3147 /* repaint toolbar */
3148 InvalidateRect(hwnd, NULL, FALSE);
3151 /* return bounding rectangle */
3152 if (lprc) {
3153 lprc->left = infoPtr->rcBound.left;
3154 lprc->right = infoPtr->rcBound.right;
3155 lprc->top = infoPtr->rcBound.top;
3156 lprc->bottom = infoPtr->rcBound.bottom;
3159 return 0;
3163 static LRESULT
3164 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3166 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3167 TBUTTON_INFO *btnPtr;
3168 INT nIndex;
3170 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3171 if (nIndex == -1)
3172 return FALSE;
3174 btnPtr = &infoPtr->buttons[nIndex];
3176 /* process state changing if current state doesn't match new state */
3177 if(btnPtr->fsState != LOWORD(lParam))
3179 btnPtr->fsState = LOWORD(lParam);
3180 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3181 btnPtr));
3184 return TRUE;
3188 static LRESULT
3189 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3191 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3192 TBUTTON_INFO *btnPtr;
3193 INT nIndex;
3195 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3196 if (nIndex == -1)
3197 return FALSE;
3199 btnPtr = &infoPtr->buttons[nIndex];
3201 /* process style change if current style doesn't match new style */
3202 if(btnPtr->fsStyle != LOWORD(lParam))
3204 btnPtr->fsStyle = LOWORD(lParam);
3205 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3206 btnPtr));
3208 if (infoPtr->hwndToolTip) {
3209 FIXME("change tool tip!\n");
3213 return TRUE;
3217 inline static LRESULT
3218 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3220 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3222 if (infoPtr == NULL)
3223 return 0;
3224 infoPtr->hwndToolTip = (HWND)wParam;
3225 return 0;
3229 static LRESULT
3230 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3232 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3233 BOOL bTemp;
3235 TRACE("%s hwnd=0x%04x stub!\n",
3236 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3238 bTemp = infoPtr->bUnicode;
3239 infoPtr->bUnicode = (BOOL)wParam;
3241 return bTemp;
3245 static LRESULT
3246 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3248 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3249 INT iOldVersion = infoPtr->iVersion;
3251 infoPtr->iVersion = iVersion;
3253 return iOldVersion;
3257 static LRESULT
3258 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3260 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3261 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3262 LOGFONTA logFont;
3264 /* initialize info structure */
3265 infoPtr->nButtonHeight = 22;
3266 infoPtr->nButtonWidth = 24;
3267 infoPtr->nBitmapHeight = 15;
3268 infoPtr->nBitmapWidth = 16;
3270 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3271 infoPtr->nRows = 1;
3272 infoPtr->nMaxTextRows = 1;
3273 infoPtr->cxMin = -1;
3274 infoPtr->cxMax = -1;
3275 infoPtr->nNumBitmaps = 0;
3276 infoPtr->nNumStrings = 0;
3278 infoPtr->bCaptured = FALSE;
3279 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3280 infoPtr->nButtonDown = -1;
3281 infoPtr->nOldHit = -1;
3282 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3283 infoPtr->hwndNotify = GetParent (hwnd);
3284 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3285 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3286 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3287 infoPtr->iVersion = 0;
3289 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3290 infoPtr->hFont = CreateFontIndirectA (&logFont);
3292 if (dwStyle & TBSTYLE_TOOLTIPS) {
3293 /* Create tooltip control */
3294 infoPtr->hwndToolTip =
3295 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3296 CW_USEDEFAULT, CW_USEDEFAULT,
3297 CW_USEDEFAULT, CW_USEDEFAULT,
3298 hwnd, 0, 0, 0);
3300 /* Send NM_TOOLTIPSCREATED notification */
3301 if (infoPtr->hwndToolTip) {
3302 NMTOOLTIPSCREATED nmttc;
3304 nmttc.hdr.hwndFrom = hwnd;
3305 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3306 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3307 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3309 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3310 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3313 return 0;
3317 static LRESULT
3318 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3320 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3322 /* delete tooltip control */
3323 if (infoPtr->hwndToolTip)
3324 DestroyWindow (infoPtr->hwndToolTip);
3326 /* delete button data */
3327 if (infoPtr->buttons)
3328 COMCTL32_Free (infoPtr->buttons);
3330 /* delete strings */
3331 if (infoPtr->strings) {
3332 INT i;
3333 for (i = 0; i < infoPtr->nNumStrings; i++)
3334 if (infoPtr->strings[i])
3335 COMCTL32_Free (infoPtr->strings[i]);
3337 COMCTL32_Free (infoPtr->strings);
3340 /* destroy internal image list */
3341 if (infoPtr->himlInt)
3342 ImageList_Destroy (infoPtr->himlInt);
3344 /* delete default font */
3345 if (infoPtr->hFont)
3346 DeleteObject (infoPtr->hFont);
3348 /* free toolbar info data */
3349 COMCTL32_Free (infoPtr);
3350 SetWindowLongA (hwnd, 0, 0);
3352 return 0;
3356 static LRESULT
3357 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3359 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3361 if (infoPtr->bTransparent)
3362 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3364 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3368 static LRESULT
3369 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3371 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3373 return infoPtr->hFont;
3377 static LRESULT
3378 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3380 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3381 TBUTTON_INFO *btnPtr;
3382 POINT pt;
3383 INT nHit;
3385 pt.x = (INT)LOWORD(lParam);
3386 pt.y = (INT)HIWORD(lParam);
3387 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3389 if (nHit >= 0) {
3390 btnPtr = &infoPtr->buttons[nHit];
3391 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3392 return 0;
3393 SetCapture (hwnd);
3394 infoPtr->bCaptured = TRUE;
3395 infoPtr->nButtonDown = nHit;
3397 btnPtr->fsState |= TBSTATE_PRESSED;
3399 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3400 btnPtr));
3402 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3403 TOOLBAR_Customize (hwnd);
3405 return 0;
3409 static LRESULT
3410 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3412 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3413 TBUTTON_INFO *btnPtr;
3414 POINT pt;
3415 INT nHit;
3417 if (infoPtr->hwndToolTip)
3418 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3419 WM_LBUTTONDOWN, wParam, lParam);
3421 pt.x = (INT)LOWORD(lParam);
3422 pt.y = (INT)HIWORD(lParam);
3423 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3425 if (nHit >= 0) {
3426 RECT arrowRect;
3427 btnPtr = &infoPtr->buttons[nHit];
3428 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3429 return 0;
3431 SetCapture (hwnd);
3432 infoPtr->bCaptured = TRUE;
3433 infoPtr->nButtonDown = nHit;
3434 infoPtr->nOldHit = nHit;
3436 btnPtr->fsState |= TBSTATE_PRESSED;
3437 btnPtr->bHot = FALSE;
3439 CopyRect(&arrowRect, &btnPtr->rect);
3440 arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
3442 /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */
3443 if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
3444 !(TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && !PtInRect(&arrowRect, pt)))
3446 NMTOOLBARA nmtb;
3448 * this time we must force a Redraw, so the btn is
3449 * painted down before CaptureChanged repaints it up
3451 RedrawWindow(hwnd,&btnPtr->rect,0,
3452 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3454 nmtb.hdr.hwndFrom = hwnd;
3455 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3456 nmtb.hdr.code = TBN_DROPDOWN;
3457 nmtb.iItem = btnPtr->idCommand;
3459 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3460 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3462 else
3463 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3464 btnPtr));
3467 return 0;
3470 static LRESULT
3471 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3473 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3474 TBUTTON_INFO *btnPtr;
3475 POINT pt;
3476 INT nHit;
3477 INT nOldIndex = -1;
3478 BOOL bSendMessage = TRUE;
3480 if (infoPtr->hwndToolTip)
3481 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3482 WM_LBUTTONUP, wParam, lParam);
3484 pt.x = (INT)LOWORD(lParam);
3485 pt.y = (INT)HIWORD(lParam);
3486 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3488 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3489 /* if the cursor is still inside of the toolbar */
3490 if((infoPtr->nHotItem >= 0) && (nHit != -1))
3491 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3493 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3494 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3495 btnPtr->fsState &= ~TBSTATE_PRESSED;
3497 if (nHit == infoPtr->nButtonDown) {
3498 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3499 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3500 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3501 infoPtr->nButtonDown);
3502 if (nOldIndex == infoPtr->nButtonDown)
3503 bSendMessage = FALSE;
3504 if ((nOldIndex != infoPtr->nButtonDown) &&
3505 (nOldIndex != -1))
3506 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3507 btnPtr->fsState |= TBSTATE_CHECKED;
3509 else {
3510 if (btnPtr->fsState & TBSTATE_CHECKED)
3511 btnPtr->fsState &= ~TBSTATE_CHECKED;
3512 else
3513 btnPtr->fsState |= TBSTATE_CHECKED;
3517 else
3518 bSendMessage = FALSE;
3520 if (nOldIndex != -1)
3522 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
3523 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
3527 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
3528 * that resets bCaptured and btn TBSTATE_PRESSED flags,
3529 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged)
3531 ReleaseCapture ();
3533 if (bSendMessage)
3534 SendMessageA (GetParent(hwnd), WM_COMMAND,
3535 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3538 return 0;
3541 static LRESULT
3542 TOOLBAR_CaptureChanged(HWND hwnd)
3544 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3545 TBUTTON_INFO *btnPtr;
3547 infoPtr->bCaptured = FALSE;
3549 if (infoPtr->nButtonDown >= 0)
3551 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3552 btnPtr->fsState &= ~TBSTATE_PRESSED;
3554 infoPtr->nButtonDown = -1;
3555 infoPtr->nOldHit = -1;
3557 InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3558 btnPtr));
3560 return 0;
3563 static LRESULT
3564 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3566 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3567 TBUTTON_INFO *hotBtnPtr, *btnPtr;
3569 if (infoPtr->nOldHit < 0)
3570 return TRUE;
3572 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3574 /* Redraw the button if the last button we were over is the hot button and it
3575 is enabled */
3576 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3578 hotBtnPtr->bHot = FALSE;
3580 InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
3581 hotBtnPtr));
3584 /* If the last button we were over is depressed then make it not */
3585 /* depressed and redraw it */
3586 if(infoPtr->nOldHit == infoPtr->nButtonDown)
3588 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3590 btnPtr->fsState &= ~TBSTATE_PRESSED;
3592 InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
3595 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3596 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3598 return TRUE;
3601 static LRESULT
3602 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3604 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3605 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3606 POINT pt;
3607 INT nHit;
3608 TRACKMOUSEEVENT trackinfo;
3610 /* fill in the TRACKMOUSEEVENT struct */
3611 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3612 trackinfo.dwFlags = TME_QUERY;
3613 trackinfo.hwndTrack = hwnd;
3614 trackinfo.dwHoverTime = HOVER_DEFAULT;
3616 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3617 _TrackMouseEvent(&trackinfo);
3619 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3620 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3621 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3623 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3624 /* and can properly deactivate the hot toolbar button */
3625 _TrackMouseEvent(&trackinfo);
3628 if (infoPtr->hwndToolTip)
3629 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3630 WM_MOUSEMOVE, wParam, lParam);
3632 pt.x = (INT)LOWORD(lParam);
3633 pt.y = (INT)HIWORD(lParam);
3635 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3637 if (infoPtr->nOldHit != nHit)
3639 /* Remove the effect of an old hot button if the button was enabled and was
3640 drawn with the hot button effect */
3641 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
3642 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3644 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3645 oldBtnPtr->bHot = FALSE;
3647 InvalidateRect (hwnd, &oldBtnPtr->rect,
3648 TOOLBAR_HasText(infoPtr, oldBtnPtr));
3651 /* It's not a separator or in nowhere. It's a hot button. */
3652 if (nHit >= 0)
3654 btnPtr = &infoPtr->buttons[nHit];
3655 btnPtr->bHot = TRUE;
3657 infoPtr->nHotItem = nHit;
3659 /* only enabled buttons show hot effect */
3660 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3662 InvalidateRect(hwnd, &btnPtr->rect,
3663 TOOLBAR_HasText(infoPtr, btnPtr));
3668 if (infoPtr->bCaptured) {
3669 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3670 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3671 btnPtr->fsState &= ~TBSTATE_PRESSED;
3672 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3674 else if (nHit == infoPtr->nButtonDown) {
3675 btnPtr->fsState |= TBSTATE_PRESSED;
3676 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3679 infoPtr->nOldHit = nHit;
3681 return 0;
3685 inline static LRESULT
3686 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3688 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3689 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3690 /* else */
3691 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3695 inline static LRESULT
3696 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3698 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3699 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3701 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3705 static LRESULT
3706 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3708 TOOLBAR_INFO *infoPtr;
3710 /* allocate memory for info structure */
3711 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3712 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3714 /* paranoid!! */
3715 infoPtr->dwStructSize = sizeof(TBBUTTON);
3717 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3718 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3719 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3720 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3723 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3727 static LRESULT
3728 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3730 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3731 RECT rcWindow;
3732 HDC hdc;
3734 if (dwStyle & WS_MINIMIZE)
3735 return 0; /* Nothing to do */
3737 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3739 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3740 return 0;
3742 if (!(dwStyle & CCS_NODIVIDER))
3744 GetWindowRect (hwnd, &rcWindow);
3745 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3746 if( dwStyle & WS_BORDER )
3747 OffsetRect (&rcWindow, 1, 1);
3748 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3751 ReleaseDC( hwnd, hdc );
3753 return 0;
3757 inline static LRESULT
3758 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3760 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3761 LPNMHDR lpnmh = (LPNMHDR)lParam;
3763 TRACE("passing WM_NOTIFY!\n");
3765 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3766 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3768 #if 0
3769 if (lpnmh->code == TTN_GETDISPINFOA) {
3770 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3772 FIXME("retrieving ASCII string\n");
3775 else if (lpnmh->code == TTN_GETDISPINFOW) {
3776 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3778 FIXME("retrieving UNICODE string\n");
3781 #endif
3784 return 0;
3788 static LRESULT
3789 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3791 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3792 HDC hdc;
3793 PAINTSTRUCT ps;
3795 TRACE("\n");
3797 /* fill ps.rcPaint with a default rect */
3798 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
3800 TOOLBAR_CalcToolbar( hwnd );
3801 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
3802 TOOLBAR_Refresh (hwnd, hdc, &ps);
3803 if (!wParam) EndPaint (hwnd, &ps);
3805 return 0;
3809 static LRESULT
3810 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3812 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3813 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3814 RECT parent_rect;
3815 RECT window_rect;
3816 HWND parent;
3817 INT x, y;
3818 INT cx, cy;
3819 INT flags;
3820 UINT uPosFlags = 0;
3822 /* Resize deadlock check */
3823 if (infoPtr->bAutoSize) {
3824 infoPtr->bAutoSize = FALSE;
3825 return 0;
3828 /* FIXME: optimize to only update size if the new size doesn't */
3829 /* match the current size */
3831 flags = (INT) wParam;
3833 /* FIXME for flags =
3834 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3837 TRACE("sizing toolbar!\n");
3839 if (flags == SIZE_RESTORED) {
3840 /* width and height don't apply */
3841 parent = GetParent (hwnd);
3842 GetClientRect(parent, &parent_rect);
3843 x = parent_rect.left;
3844 y = parent_rect.top;
3846 if (dwStyle & CCS_NORESIZE) {
3847 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3850 * this sets the working width of the toolbar, and
3851 * Calc Toolbar will not adjust it, only the height
3853 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3854 cy = infoPtr->nHeight;
3855 cx = infoPtr->nWidth;
3856 TOOLBAR_CalcToolbar (hwnd);
3857 infoPtr->nWidth = cx;
3858 infoPtr->nHeight = cy;
3860 else {
3861 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3862 TOOLBAR_CalcToolbar (hwnd);
3863 cy = infoPtr->nHeight;
3864 cx = infoPtr->nWidth;
3866 if (dwStyle & CCS_NOMOVEY) {
3867 GetWindowRect(hwnd, &window_rect);
3868 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3869 y = window_rect.top;
3873 if (dwStyle & CCS_NOPARENTALIGN) {
3874 uPosFlags |= SWP_NOMOVE;
3875 cy = infoPtr->nHeight;
3876 cx = infoPtr->nWidth;
3879 if (!(dwStyle & CCS_NODIVIDER))
3880 cy += GetSystemMetrics(SM_CYEDGE);
3882 if (dwStyle & WS_BORDER)
3884 x = y = 1;
3885 cy += GetSystemMetrics(SM_CYEDGE);
3886 cx += GetSystemMetrics(SM_CYEDGE);
3889 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3890 cx, cy, uPosFlags | SWP_NOZORDER);
3892 return 0;
3896 static LRESULT
3897 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3899 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3901 if (nType == GWL_STYLE) {
3902 if (lpStyle->styleNew & TBSTYLE_LIST) {
3903 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3905 else {
3906 infoPtr->dwDTFlags = DT_CENTER;
3910 TOOLBAR_AutoSize (hwnd);
3912 InvalidateRect(hwnd, NULL, FALSE);
3914 return 0;
3919 static LRESULT WINAPI
3920 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3923 switch (uMsg)
3925 case WM_DESTROY:
3926 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3928 case WM_NCCREATE:
3929 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3932 if (!TOOLBAR_GetInfoPtr (hwnd))
3934 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3937 switch (uMsg)
3939 case TB_ADDBITMAP:
3940 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3942 case TB_ADDBUTTONSA:
3943 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3945 case TB_ADDBUTTONSW:
3946 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3948 case TB_ADDSTRINGA:
3949 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3951 case TB_ADDSTRINGW:
3952 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3954 case TB_AUTOSIZE:
3955 return TOOLBAR_AutoSize (hwnd);
3957 case TB_BUTTONCOUNT:
3958 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3960 case TB_BUTTONSTRUCTSIZE:
3961 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3963 case TB_CHANGEBITMAP:
3964 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3966 case TB_CHECKBUTTON:
3967 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3969 case TB_COMMANDTOINDEX:
3970 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3972 case TB_CUSTOMIZE:
3973 return TOOLBAR_Customize (hwnd);
3975 case TB_DELETEBUTTON:
3976 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3978 case TB_ENABLEBUTTON:
3979 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3981 case TB_GETANCHORHIGHLIGHT:
3982 return TOOLBAR_GetAnchorHighlight (hwnd);
3984 case TB_GETBITMAP:
3985 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3987 case TB_GETBITMAPFLAGS:
3988 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3990 case TB_GETBUTTON:
3991 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3993 case TB_GETBUTTONINFOA:
3994 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3996 case TB_GETBUTTONINFOW:
3997 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3999 case TB_GETBUTTONSIZE:
4000 return TOOLBAR_GetButtonSize (hwnd);
4002 case TB_GETBUTTONTEXTA:
4003 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
4005 case TB_GETBUTTONTEXTW:
4006 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
4008 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
4010 case TB_GETDISABLEDIMAGELIST:
4011 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
4013 case TB_GETEXTENDEDSTYLE:
4014 return TOOLBAR_GetExtendedStyle (hwnd);
4016 case TB_GETHOTIMAGELIST:
4017 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
4019 case TB_GETHOTITEM:
4020 return TOOLBAR_GetHotItem (hwnd);
4022 case TB_GETIMAGELIST:
4023 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
4025 /* case TB_GETINSERTMARK: */ /* 4.71 */
4026 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
4028 case TB_GETITEMRECT:
4029 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
4031 case TB_GETMAXSIZE:
4032 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
4034 /* case TB_GETOBJECT: */ /* 4.71 */
4035 /* case TB_GETPADDING: */ /* 4.71 */
4037 case TB_GETRECT:
4038 return TOOLBAR_GetRect (hwnd, wParam, lParam);
4040 case TB_GETROWS:
4041 return TOOLBAR_GetRows (hwnd, wParam, lParam);
4043 case TB_GETSTATE:
4044 return TOOLBAR_GetState (hwnd, wParam, lParam);
4046 case TB_GETSTYLE:
4047 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
4049 case TB_GETTEXTROWS:
4050 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
4052 case TB_GETTOOLTIPS:
4053 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
4055 case TB_GETUNICODEFORMAT:
4056 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
4058 case CCM_GETVERSION:
4059 return TOOLBAR_GetVersion (hwnd);
4061 case TB_HIDEBUTTON:
4062 return TOOLBAR_HideButton (hwnd, wParam, lParam);
4064 case TB_HITTEST:
4065 return TOOLBAR_HitTest (hwnd, wParam, lParam);
4067 case TB_INDETERMINATE:
4068 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
4070 case TB_INSERTBUTTONA:
4071 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
4073 case TB_INSERTBUTTONW:
4074 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
4076 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
4078 case TB_ISBUTTONCHECKED:
4079 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
4081 case TB_ISBUTTONENABLED:
4082 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
4084 case TB_ISBUTTONHIDDEN:
4085 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
4087 case TB_ISBUTTONHIGHLIGHTED:
4088 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
4090 case TB_ISBUTTONINDETERMINATE:
4091 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
4093 case TB_ISBUTTONPRESSED:
4094 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
4096 case TB_LOADIMAGES: /* 4.70 */
4097 FIXME("missing standard imagelists\n");
4098 return 0;
4100 /* case TB_MAPACCELERATORA: */ /* 4.71 */
4101 /* case TB_MAPACCELERATORW: */ /* 4.71 */
4102 /* case TB_MARKBUTTON: */ /* 4.71 */
4103 /* case TB_MOVEBUTTON: */ /* 4.71 */
4105 case TB_PRESSBUTTON:
4106 return TOOLBAR_PressButton (hwnd, wParam, lParam);
4108 /* case TB_REPLACEBITMAP: */
4110 case TB_SAVERESTOREA:
4111 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
4113 case TB_SAVERESTOREW:
4114 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
4116 case TB_SETANCHORHIGHLIGHT:
4117 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
4119 case TB_SETBITMAPSIZE:
4120 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
4122 case TB_SETBUTTONINFOA:
4123 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
4125 case TB_SETBUTTONINFOW:
4126 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
4128 case TB_SETBUTTONSIZE:
4129 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
4131 case TB_SETBUTTONWIDTH:
4132 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
4134 case TB_SETCMDID:
4135 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
4137 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
4139 case TB_SETDISABLEDIMAGELIST:
4140 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
4142 case TB_SETDRAWTEXTFLAGS:
4143 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
4145 case TB_SETEXTENDEDSTYLE:
4146 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
4148 case TB_SETHOTIMAGELIST:
4149 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
4151 case TB_SETHOTITEM:
4152 return TOOLBAR_SetHotItem (hwnd, wParam);
4154 case TB_SETIMAGELIST:
4155 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
4157 case TB_SETINDENT:
4158 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
4160 /* case TB_SETINSERTMARK: */ /* 4.71 */
4162 case TB_SETINSERTMARKCOLOR:
4163 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
4165 case TB_SETMAXTEXTROWS:
4166 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
4168 /* case TB_SETPADDING: */ /* 4.71 */
4170 case TB_SETPARENT:
4171 return TOOLBAR_SetParent (hwnd, wParam, lParam);
4173 case TB_SETROWS:
4174 return TOOLBAR_SetRows (hwnd, wParam, lParam);
4176 case TB_SETSTATE:
4177 return TOOLBAR_SetState (hwnd, wParam, lParam);
4179 case TB_SETSTYLE:
4180 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
4182 case TB_SETTOOLTIPS:
4183 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
4185 case TB_SETUNICODEFORMAT:
4186 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
4188 case CCM_SETVERSION:
4189 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
4192 /* case WM_CHAR: */
4194 case WM_CREATE:
4195 return TOOLBAR_Create (hwnd, wParam, lParam);
4197 case WM_ERASEBKGND:
4198 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
4200 case WM_GETFONT:
4201 return TOOLBAR_GetFont (hwnd, wParam, lParam);
4203 /* case WM_KEYDOWN: */
4204 /* case WM_KILLFOCUS: */
4206 case WM_LBUTTONDBLCLK:
4207 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
4209 case WM_LBUTTONDOWN:
4210 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
4212 case WM_LBUTTONUP:
4213 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4215 case WM_MOUSEMOVE:
4216 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4218 case WM_MOUSELEAVE:
4219 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
4221 case WM_CAPTURECHANGED:
4222 return TOOLBAR_CaptureChanged(hwnd);
4224 case WM_NCACTIVATE:
4225 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4227 case WM_NCCALCSIZE:
4228 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4230 case WM_NCPAINT:
4231 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4233 case WM_NOTIFY:
4234 return TOOLBAR_Notify (hwnd, wParam, lParam);
4236 /* case WM_NOTIFYFORMAT: */
4238 case WM_PAINT:
4239 return TOOLBAR_Paint (hwnd, wParam);
4241 case WM_SIZE:
4242 return TOOLBAR_Size (hwnd, wParam, lParam);
4244 case WM_STYLECHANGED:
4245 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4247 /* case WM_SYSCOLORCHANGE: */
4249 /* case WM_WININICHANGE: */
4251 case WM_CHARTOITEM:
4252 case WM_COMMAND:
4253 case WM_DRAWITEM:
4254 case WM_MEASUREITEM:
4255 case WM_VKEYTOITEM:
4256 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4258 default:
4259 if (uMsg >= WM_USER)
4260 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4261 uMsg, wParam, lParam);
4262 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4264 return 0;
4268 VOID
4269 TOOLBAR_Register (void)
4271 WNDCLASSA wndClass;
4273 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4274 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4275 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4276 wndClass.cbClsExtra = 0;
4277 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4278 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4279 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4280 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4282 RegisterClassA (&wndClass);
4286 VOID
4287 TOOLBAR_Unregister (void)
4289 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);