Use MZ_Current() instead of pModule->lpDosTask. Cleaned up the RMCB32
[wine/dcerpc.git] / dlls / comctl32 / toolbar.c
blob45fe151837c70c243839e7415ae23e3bf7e3eeb2
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.
19 * Testing:
20 * - Run tests using Waite Group Windows95 API Bible Volume 2.
21 * The second cdrom contains executables addstr.exe, btncount.exe,
22 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
23 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
24 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
25 * setparnt.exe, setrows.exe, toolwnd.exe.
26 * - Microsofts controlspy examples.
29 #include <string.h>
31 #include "winbase.h"
32 #include "windef.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "commctrl.h"
36 #include "cache.h"
37 #include "comctl32.h"
38 #include "toolbar.h"
39 #include "debugtools.h"
41 DEFAULT_DEBUG_CHANNEL(toolbar)
43 #define SEPARATOR_WIDTH 8
44 #define TOP_BORDER 2
45 #define BOTTOM_BORDER 2
47 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
49 static BOOL
50 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
52 if ((index>=0) && (index < infoPtr->nNumBitmaps))
53 return TRUE;
54 else
55 return FALSE;
59 static void
60 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
62 INT x = (lpRect->left + lpRect->right) / 2 - 1;
63 INT yBottom = lpRect->bottom - 3;
64 INT yTop = lpRect->top + 1;
66 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
67 MoveToEx (hdc, x, yBottom, NULL);
68 LineTo (hdc, x, yTop);
69 x++;
70 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
71 MoveToEx (hdc, x, yBottom, NULL);
72 LineTo (hdc, x, yTop);
76 * Draw the text string for this button.
77 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
78 * is non-zero, so we can simply check himlDef to see if we have
79 * an image list
81 static void
82 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
83 HDC hdc, INT nState, DWORD dwStyle)
85 RECT rcText = btnPtr->rect;
86 HFONT hOldFont;
87 INT nOldBkMode;
88 COLORREF clrOld;
89 LPWSTR lpText = NULL;
90 HIMAGELIST himl = infoPtr->himlDef;
92 TRACE ("iString: %x\n", btnPtr->iString);
94 /* get a pointer to the text */
95 if (btnPtr->iString == -1)
96 FIXME("Undocumented Index -1\n");
97 else if (HIWORD(btnPtr->iString) != 0)
98 lpText = (LPWSTR)btnPtr->iString;
99 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
100 lpText = infoPtr->strings[btnPtr->iString];
102 TRACE ("lpText: \"%s\"\n", debugstr_w(lpText));
104 /* draw text */
105 if (lpText) {
107 InflateRect (&rcText, -3, -3);
109 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
110 if ((dwStyle & TBSTYLE_LIST) &&
111 ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
112 (btnPtr->iBitmap != I_IMAGENONE)) {
113 rcText.left += infoPtr->nBitmapWidth;
115 else {
116 rcText.top += infoPtr->nBitmapHeight;
120 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
121 OffsetRect (&rcText, 1, 1);
123 hOldFont = SelectObject (hdc, infoPtr->hFont);
124 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
125 if (!(nState & TBSTATE_ENABLED)) {
126 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
127 OffsetRect (&rcText, 1, 1);
128 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
129 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
130 OffsetRect (&rcText, -1, -1);
131 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
133 else if (nState & TBSTATE_INDETERMINATE) {
134 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
135 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
137 else {
138 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
139 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
142 SetTextColor (hdc, clrOld);
143 SelectObject (hdc, hOldFont);
144 if (nOldBkMode != TRANSPARENT)
145 SetBkMode (hdc, nOldBkMode);
150 static void
151 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
153 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
154 INT cx = lpRect->right - lpRect->left;
155 INT cy = lpRect->bottom - lpRect->top;
156 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
157 SelectObject (hdc, hbr);
161 static void
162 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
163 HDC hdc, INT x, INT y)
165 /* FIXME: this function is a hack since it uses image list
166 internals directly */
168 HIMAGELIST himl = infoPtr->himlDef;
169 HBITMAP hbmMask;
170 HDC hdcImageList;
171 HDC hdcMask;
173 if (!himl)
174 return;
176 /* create new dc's */
177 hdcImageList = CreateCompatibleDC (0);
178 hdcMask = CreateCompatibleDC (0);
180 /* create new bitmap */
181 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
182 SelectObject (hdcMask, hbmMask);
184 /* copy the mask bitmap */
185 SelectObject (hdcImageList, himl->hbmMask);
186 SetBkColor (hdcImageList, RGB(255, 255, 255));
187 SetTextColor (hdcImageList, RGB(0, 0, 0));
188 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
189 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
191 #if 0
192 /* add white mask from image */
193 SelectObject (hdcImageList, himl->hbmImage);
194 SetBkColor (hdcImageList, RGB(0, 0, 0));
195 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
196 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
197 #endif
199 /* draw the new mask */
200 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
201 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
202 hdcMask, 0, 0, 0xB8074A);
204 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
205 BitBlt (hdc, x, y, himl->cx, himl->cy,
206 hdcMask, 0, 0, 0xB8074A);
208 DeleteObject (hbmMask);
209 DeleteDC (hdcMask);
210 DeleteDC (hdcImageList);
214 static void
215 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
217 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
218 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
219 RECT rc;
221 if (btnPtr->fsState & TBSTATE_HIDDEN)
222 return;
224 rc = btnPtr->rect;
226 TRACE("iBitmap: %d\n", btnPtr->iBitmap);
228 /* separator */
229 if (btnPtr->fsStyle & TBSTYLE_SEP) {
230 /* with the FLAT style, iBitmap is the width and has already */
231 /* been taken into consideration in calculating the width */
232 /* so now we need to draw the vertical separator */
233 /* empirical tests show that iBitmap can/will be non-zero */
234 /* when drawing the vertical bar... */
235 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
236 TOOLBAR_DrawFlatSeparator (&rc, hdc);
237 return;
240 /* disabled */
241 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
242 if (!(dwStyle & TBSTYLE_FLAT))
243 DrawEdge (hdc, &rc, EDGE_RAISED,
244 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
246 if (infoPtr->himlDis &&
247 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
248 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
249 rc.left+1, rc.top+1, ILD_NORMAL);
250 else
251 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
253 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
254 return;
257 /* pressed TBSTYLE_BUTTON */
258 if (btnPtr->fsState & TBSTATE_PRESSED) {
259 if (dwStyle & TBSTYLE_FLAT)
260 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
261 else
262 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
263 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
264 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
265 rc.left+2, rc.top+2, ILD_NORMAL);
266 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
267 return;
270 /* checked TBSTYLE_CHECK */
271 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
272 (btnPtr->fsState & TBSTATE_CHECKED)) {
273 if (dwStyle & TBSTYLE_FLAT)
274 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
275 BF_RECT | BF_MIDDLE | BF_ADJUST);
276 else
277 DrawEdge (hdc, &rc, EDGE_SUNKEN,
278 BF_RECT | BF_MIDDLE | BF_ADJUST);
280 TOOLBAR_DrawPattern (hdc, &rc);
282 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
283 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
284 rc.left+2, rc.top+2, ILD_NORMAL);
286 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
287 return;
290 /* indeterminate */
291 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
292 DrawEdge (hdc, &rc, EDGE_RAISED,
293 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
295 TOOLBAR_DrawPattern (hdc, &rc);
296 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
297 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
298 return;
301 /* normal state */
302 if (dwStyle & TBSTYLE_FLAT)
304 if (btnPtr->bHot)
305 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
306 if (btnPtr->bHot && infoPtr->himlHot &&
307 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
308 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
309 rc.left +2, rc.top +2, ILD_NORMAL);
310 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
311 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
312 rc.left +2, rc.top +2, ILD_NORMAL);
314 else
316 DrawEdge (hdc, &rc, EDGE_RAISED,
317 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
319 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
320 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
321 rc.left+1, rc.top+1, ILD_NORMAL);
324 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
328 static void
329 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
331 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
332 TBUTTON_INFO *btnPtr;
333 INT i;
334 RECT rcTemp;
336 /* redraw necessary buttons */
337 btnPtr = infoPtr->buttons;
338 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
340 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
341 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
345 static void
346 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
348 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
349 TBUTTON_INFO *btnPtr;
350 HDC hdc;
351 HFONT hOldFont;
353 lpSize->cx = 0;
354 lpSize->cy = 0;
355 hdc = GetDC (0);
356 hOldFont = SelectObject (hdc, infoPtr->hFont);
358 btnPtr = &infoPtr->buttons[index];
360 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
361 (btnPtr->iString > -1) &&
362 (btnPtr->iString < infoPtr->nNumStrings))
364 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
365 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
368 SelectObject (hdc, hOldFont);
369 ReleaseDC (0, hdc);
371 TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
374 static void
375 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
377 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
378 TBUTTON_INFO *btnPtr;
379 INT i;
380 SIZE sz;
383 lpSize->cx = 0;
384 lpSize->cy = 0;
386 btnPtr = infoPtr->buttons;
387 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
388 TOOLBAR_MeasureString(hwnd,i,&sz);
389 if (sz.cx > lpSize->cx)
390 lpSize->cx = sz.cx;
391 if (sz.cy > lpSize->cy)
392 lpSize->cy = sz.cy;
395 TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
398 /***********************************************************************
399 * TOOLBAR_WrapToolbar
401 * This function walks through the buttons and seperators in the
402 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
403 * wrapping should occur based on the width of the toolbar window.
404 * It does *not* calculate button placement itself. That task
405 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
406 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
407 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
410 static void
411 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
413 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
414 TBUTTON_INFO *btnPtr;
415 INT x, cx, i, j;
416 RECT rc;
417 BOOL bWrap, bButtonWrap;
419 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
420 /* no layout is necessary. Applications may use this style */
421 /* to perform their own layout on the toolbar. */
422 if( !(dwStyle & TBSTYLE_WRAPABLE) )
423 return;
425 btnPtr = infoPtr->buttons;
426 x = infoPtr->nIndent;
428 /* this can get the parents width, to know how far we can extend
429 * this toolbar. We cannot use its height, as there may be multiple
430 * toolbars in a rebar control
432 GetClientRect( GetParent(hwnd), &rc );
433 infoPtr->nWidth = rc.right - rc.left;
434 bButtonWrap = FALSE;
436 for (i = 0; i < infoPtr->nNumButtons; i++ )
438 bWrap = FALSE;
439 btnPtr[i].fsState &= ~TBSTATE_WRAP;
441 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
442 continue;
444 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
445 /* it is the actual width of the separator. This is used for */
446 /* custom controls in toolbars. */
447 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
448 cx = (btnPtr[i].iBitmap > 0) ?
449 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
450 else
451 cx = infoPtr->nButtonWidth;
453 /* Two or more adjacent separators form a separator group. */
454 /* The first separator in a group should be wrapped to the */
455 /* next row if the previous wrapping is on a button. */
456 if( bButtonWrap &&
457 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
458 (i + 1 < infoPtr->nNumButtons ) &&
459 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
461 btnPtr[i].fsState |= TBSTATE_WRAP;
462 x = infoPtr->nIndent;
463 i++;
464 bButtonWrap = FALSE;
465 continue;
468 /* The layout makes sure the bitmap is visible, but not the button. */
469 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
470 > infoPtr->nWidth )
472 BOOL bFound = FALSE;
474 /* If the current button is a separator and not hidden, */
475 /* go to the next until it reaches a non separator. */
476 /* Wrap the last separator if it is before a button. */
477 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
478 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
479 i < infoPtr->nNumButtons )
481 i++;
482 bFound = TRUE;
485 if( bFound && i < infoPtr->nNumButtons )
487 i--;
488 btnPtr[i].fsState |= TBSTATE_WRAP;
489 x = infoPtr->nIndent;
490 bButtonWrap = FALSE;
491 continue;
493 else if ( i >= infoPtr->nNumButtons)
494 break;
496 /* If the current button is not a separator, find the last */
497 /* separator and wrap it. */
498 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
500 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
501 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
503 bFound = TRUE;
504 i = j;
505 x = infoPtr->nIndent;
506 btnPtr[j].fsState |= TBSTATE_WRAP;
507 bButtonWrap = FALSE;
508 break;
512 /* If no separator available for wrapping, wrap one of */
513 /* non-hidden previous button. */
514 if (!bFound)
516 for ( j = i - 1;
517 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
519 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
520 continue;
522 bFound = TRUE;
523 i = j;
524 x = infoPtr->nIndent;
525 btnPtr[j].fsState |= TBSTATE_WRAP;
526 bButtonWrap = TRUE;
527 break;
531 /* If all above failed, wrap the current button. */
532 if (!bFound)
534 btnPtr[i].fsState |= TBSTATE_WRAP;
535 bFound = TRUE;
536 x = infoPtr->nIndent;
537 if (btnPtr[i].fsState & TBSTYLE_SEP )
538 bButtonWrap = FALSE;
539 else
540 bButtonWrap = TRUE;
543 else
544 x += cx;
548 /***********************************************************************
549 * TOOLBAR_CalcToolbar
551 * This function calculates button and separator placement. It first
552 * calculates the button sizes, gets the toolbar window width and then
553 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
554 * on. It assigns a new location to each item and sends this location to
555 * the tooltip window if appropriate. Finally, it updates the rcBound
556 * rect and calculates the new required toolbar window height.
559 static void
560 TOOLBAR_CalcToolbar (HWND hwnd)
562 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
563 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
564 TBUTTON_INFO *btnPtr;
565 INT i, nRows, nSepRows;
566 INT x, y, cx, cy;
567 SIZE sizeString;
568 BOOL bWrap;
570 TOOLBAR_CalcStrings (hwnd, &sizeString);
572 if (dwStyle & TBSTYLE_LIST) {
573 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
574 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
576 else {
577 BOOL usesBitmaps = FALSE;
578 INT i;
580 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
581 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
582 usesBitmaps = TRUE;
584 if (sizeString.cy > 0) {
585 if (usesBitmaps)
586 infoPtr->nButtonHeight = sizeString.cy + infoPtr->nBitmapHeight + 6;
587 else
588 infoPtr->nButtonHeight = sizeString.cy + 6;
590 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
591 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
593 if (sizeString.cx > infoPtr->nBitmapWidth)
594 infoPtr->nButtonWidth = sizeString.cx + 6;
595 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
596 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
599 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
600 infoPtr->nButtonWidth = infoPtr->cxMin;
601 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
602 infoPtr->nButtonWidth = infoPtr->cxMax;
604 TOOLBAR_WrapToolbar( hwnd, dwStyle );
606 x = infoPtr->nIndent;
607 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
610 * We wills et the height below, and we set the width on entry
611 * so we do not reset them here..
613 #if 0
614 GetClientRect( hwnd, &rc );
615 /* get initial values for toolbar */
616 infoPtr->nWidth = rc.right - rc.left;
617 infoPtr->nHeight = rc.bottom - rc.top;
618 #endif
620 /* from above, minimum is a button, and possible text */
621 cx = infoPtr->nButtonWidth;
622 /* cannot use just ButtonHeight, we may have no buttons! */
623 if (infoPtr->nNumButtons > 0)
624 infoPtr->nHeight = infoPtr->nButtonHeight;
625 cy = infoPtr->nHeight;
627 nRows = nSepRows = 0;
629 infoPtr->rcBound.top = y;
630 infoPtr->rcBound.left = x;
631 infoPtr->rcBound.bottom = y + cy;
632 infoPtr->rcBound.right = x;
634 btnPtr = infoPtr->buttons;
636 /* do not base height/width on parent, if the parent is a */
637 /* rebar control it could have multiple rows of toolbars */
638 /* GetClientRect( GetParent(hwnd), &rc ); */
639 /* cx = rc.right - rc.left; */
640 /* cy = rc.bottom - rc.top; */
642 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
644 bWrap = FALSE;
645 if (btnPtr->fsState & TBSTATE_HIDDEN)
647 SetRectEmpty (&btnPtr->rect);
648 continue;
651 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
652 /* it is the actual width of the separator. This is used for */
653 /* custom controls in toolbars. */
654 if (btnPtr->fsStyle & TBSTYLE_SEP)
655 cx = (btnPtr->iBitmap > 0) ?
656 btnPtr->iBitmap : SEPARATOR_WIDTH;
657 else {
658 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
660 SIZE sz;
661 TOOLBAR_MeasureString(hwnd,i,&sz);
662 cx = sz.cx + 6;
664 else
665 cx = infoPtr->nButtonWidth;
667 cy = infoPtr->nHeight;
669 if (btnPtr->fsState & TBSTATE_WRAP )
670 bWrap = TRUE;
672 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
674 if (infoPtr->rcBound.left > x)
675 infoPtr->rcBound.left = x;
676 if (infoPtr->rcBound.right < x + cx)
677 infoPtr->rcBound.right = x + cx;
678 if (infoPtr->rcBound.bottom < y + cy)
679 infoPtr->rcBound.bottom = y + cy;
681 /* Set the toolTip only for non-hidden, non-separator button */
682 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
684 TTTOOLINFOA ti;
686 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
687 ti.cbSize = sizeof(TTTOOLINFOA);
688 ti.hwnd = hwnd;
689 ti.uId = btnPtr->idCommand;
690 ti.rect = btnPtr->rect;
691 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
692 0, (LPARAM)&ti);
695 /* btnPtr->nRow is zero based. The space between the rows is */
696 /* also considered as a row. */
697 btnPtr->nRow = nRows + nSepRows;
698 if( bWrap )
700 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
701 y += cy;
702 else
704 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
705 /* it is the actual width of the separator. This is used for */
706 /* custom controls in toolbars. */
707 y += cy + ( (btnPtr->iBitmap > 0 ) ?
708 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
710 /* nSepRows is used to calculate the extra height follwoing */
711 /* the last row. */
712 nSepRows++;
714 x = infoPtr->nIndent;
715 nRows++;
717 else
718 x += cx;
721 /* infoPtr->nRows is the number of rows on the toolbar */
722 infoPtr->nRows = nRows + nSepRows + 1;
724 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
725 /* the last row. */
726 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
727 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
728 nSepRows * (infoPtr->nBitmapHeight + 1) +
729 BOTTOM_BORDER;
730 TRACE("toolbar height %d\n", infoPtr->nHeight);
734 static INT
735 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
737 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
738 TBUTTON_INFO *btnPtr;
739 INT i;
741 btnPtr = infoPtr->buttons;
742 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
743 if (btnPtr->fsState & TBSTATE_HIDDEN)
744 continue;
746 if (btnPtr->fsStyle & TBSTYLE_SEP) {
747 if (PtInRect (&btnPtr->rect, *lpPt)) {
748 TRACE(" ON SEPARATOR %d!\n", i);
749 return -i;
752 else {
753 if (PtInRect (&btnPtr->rect, *lpPt)) {
754 TRACE(" ON BUTTON %d!\n", i);
755 return i;
760 TRACE(" NOWHERE!\n");
761 return -1;
765 static INT
766 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
768 TBUTTON_INFO *btnPtr;
769 INT i;
771 btnPtr = infoPtr->buttons;
772 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
773 if (btnPtr->idCommand == idCommand) {
774 TRACE("command=%d index=%d\n", idCommand, i);
775 return i;
778 TRACE("no index found for command=%d\n", idCommand);
779 return -1;
783 static INT
784 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
786 TBUTTON_INFO *btnPtr;
787 INT nRunIndex;
789 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
790 return -1;
792 /* check index button */
793 btnPtr = &infoPtr->buttons[nIndex];
794 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
795 if (btnPtr->fsState & TBSTATE_CHECKED)
796 return nIndex;
799 /* check previous buttons */
800 nRunIndex = nIndex - 1;
801 while (nRunIndex >= 0) {
802 btnPtr = &infoPtr->buttons[nRunIndex];
803 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
804 if (btnPtr->fsState & TBSTATE_CHECKED)
805 return nRunIndex;
807 else
808 break;
809 nRunIndex--;
812 /* check next buttons */
813 nRunIndex = nIndex + 1;
814 while (nRunIndex < infoPtr->nNumButtons) {
815 btnPtr = &infoPtr->buttons[nRunIndex];
816 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
817 if (btnPtr->fsState & TBSTATE_CHECKED)
818 return nRunIndex;
820 else
821 break;
822 nRunIndex++;
825 return -1;
829 static VOID
830 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
831 WPARAM wParam, LPARAM lParam)
833 MSG msg;
835 msg.hwnd = hwndMsg;
836 msg.message = uMsg;
837 msg.wParam = wParam;
838 msg.lParam = lParam;
839 msg.time = GetMessageTime ();
840 msg.pt.x = LOWORD(GetMessagePos ());
841 msg.pt.y = HIWORD(GetMessagePos ());
843 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
847 /***********************************************************************
848 * TOOLBAR_CustomizeDialogProc
849 * This function implements the toolbar customization dialog.
851 static BOOL WINAPI
852 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
854 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
855 static HDSA hDsa = NULL;
857 switch (uMsg)
859 case WM_INITDIALOG:
860 infoPtr = (TOOLBAR_INFO *)lParam;
861 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
863 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
865 if (infoPtr)
867 TBUTTON_INFO *btnPtr;
868 INT i;
870 /* insert 'virtual' separator button into 'available buttons' list */
871 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
873 /* copy all buttons and append them to the right listbox */
874 btnPtr = infoPtr->buttons;
875 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
877 DSA_InsertItem (hDsa, i, btnPtr);
879 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
880 if (btnPtr->fsState & TBSTATE_HIDDEN)
882 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
884 else
886 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
890 /* append 'virtual' separator button to the 'toolbar buttons' list */
891 /* TODO */
893 return TRUE;
895 case WM_CLOSE:
896 EndDialog(hwnd, FALSE);
897 return TRUE;
899 case WM_COMMAND:
900 switch (LOWORD(wParam))
902 case IDCANCEL:
903 EndDialog(hwnd, FALSE);
904 break;
906 return TRUE;
908 case WM_DESTROY:
909 if (hDsa)
910 DSA_Destroy (hDsa);
911 return TRUE;
913 case WM_DRAWITEM:
914 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
916 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
917 TBUTTON_INFO btnPtr;
918 RECT rcButton;
919 RECT rcText;
920 HPEN hOldPen;
921 HBRUSH hOldBrush;
922 COLORREF oldText = 0;
923 COLORREF oldBk = 0;
925 FIXME("action: %x itemState: %x\n",
926 lpdis->itemAction, lpdis->itemState);
928 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
930 if (lpdis->itemState & ODS_FOCUS)
932 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
933 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
936 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
937 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
939 /* fill background rectangle */
940 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
941 lpdis->rcItem.right, lpdis->rcItem.bottom);
943 /* calculate button and text rectangles */
944 CopyRect (&rcButton, &lpdis->rcItem);
945 InflateRect (&rcButton, -1, -1);
946 CopyRect (&rcText, &rcButton);
947 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
948 rcText.left = rcButton.right + 2;
950 /* draw focus rectangle */
951 if (lpdis->itemState & ODS_FOCUS)
952 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
954 /* draw button */
955 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
957 /* draw image and text */
958 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
960 /* virtual separator in the 'available' list */
961 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
962 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
964 else
966 /* real button */
968 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
969 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
971 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
972 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
976 if (lpdis->itemState & ODS_FOCUS)
978 SetBkColor (lpdis->hDC, oldBk);
979 SetTextColor (lpdis->hDC, oldText);
982 SelectObject (lpdis->hDC, hOldBrush);
983 SelectObject (lpdis->hDC, hOldPen);
985 return TRUE;
987 return FALSE;
989 case WM_MEASUREITEM:
990 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
992 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
994 if (infoPtr)
995 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
996 else
997 lpmis->itemHeight = 15 + 8; /* default height */
999 return TRUE;
1001 return FALSE;
1003 default:
1004 return FALSE;
1009 /***********************************************************************
1010 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1013 static LRESULT
1014 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1016 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1017 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1018 INT nIndex = 0, nButtons, nCount;
1019 HBITMAP hbmLoad;
1021 TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1022 if (!lpAddBmp)
1023 return -1;
1025 if (lpAddBmp->hInst == HINST_COMMCTRL)
1027 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1028 nButtons = 15;
1029 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1030 nButtons = 13;
1031 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1032 nButtons = 5;
1033 else
1034 return -1;
1036 TRACE ("adding %d internal bitmaps!\n", nButtons);
1038 /* Windows resize all the buttons to the size of a newly added standard image */
1039 if (lpAddBmp->nID & 1)
1041 /* large icons */
1042 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1043 MAKELPARAM((WORD)26, (WORD)26));
1044 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1045 MAKELPARAM((WORD)33, (WORD)33));
1047 else
1049 /* small icons */
1050 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1051 MAKELPARAM((WORD)16, (WORD)16));
1052 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1053 MAKELPARAM((WORD)22, (WORD)22));
1056 TOOLBAR_CalcToolbar (hwnd);
1058 else
1060 nButtons = (INT)wParam;
1061 if (nButtons <= 0)
1062 return -1;
1064 TRACE ("adding %d bitmaps!\n", nButtons);
1067 if (!(infoPtr->himlDef)) {
1068 /* create new default image list */
1069 TRACE ("creating default image list!\n");
1071 infoPtr->himlDef =
1072 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1073 ILC_COLOR | ILC_MASK, nButtons, 2);
1074 infoPtr->himlInt = infoPtr->himlDef;
1077 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1079 /* Add bitmaps to the default image list */
1080 if (lpAddBmp->hInst == (HINSTANCE)0)
1082 nIndex =
1083 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1084 CLR_DEFAULT);
1086 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1088 /* Add system bitmaps */
1089 switch (lpAddBmp->nID)
1091 case IDB_STD_SMALL_COLOR:
1092 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1093 MAKEINTRESOURCEA(IDB_STD_SMALL));
1094 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1095 hbmLoad, CLR_DEFAULT);
1096 DeleteObject (hbmLoad);
1097 break;
1099 case IDB_STD_LARGE_COLOR:
1100 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1101 MAKEINTRESOURCEA(IDB_STD_LARGE));
1102 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1103 hbmLoad, CLR_DEFAULT);
1104 DeleteObject (hbmLoad);
1105 break;
1107 case IDB_VIEW_SMALL_COLOR:
1108 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1109 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1110 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1111 hbmLoad, CLR_DEFAULT);
1112 DeleteObject (hbmLoad);
1113 break;
1115 case IDB_VIEW_LARGE_COLOR:
1116 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1117 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1118 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1119 hbmLoad, CLR_DEFAULT);
1120 DeleteObject (hbmLoad);
1121 break;
1123 case IDB_HIST_SMALL_COLOR:
1124 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1125 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1126 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1127 hbmLoad, CLR_DEFAULT);
1128 DeleteObject (hbmLoad);
1129 break;
1131 case IDB_HIST_LARGE_COLOR:
1132 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1133 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1134 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1135 hbmLoad, CLR_DEFAULT);
1136 DeleteObject (hbmLoad);
1137 break;
1139 default:
1140 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1141 ERR ("invalid imagelist!\n");
1142 break;
1145 else
1147 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1148 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1149 DeleteObject (hbmLoad);
1152 if (nIndex != -1)
1154 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1156 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1158 WARN("Desired images do not match recieved images : Previous image number %i Previous images in list %i added %i expecting total %i, Images in list %i\n",
1159 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1160 infoPtr->nNumBitmaps+nButtons,imagecount);
1162 infoPtr->nNumBitmaps = imagecount;
1164 else
1165 infoPtr->nNumBitmaps += nButtons;
1168 return nIndex;
1172 static LRESULT
1173 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1175 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1176 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1177 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1179 TRACE("adding %d buttons!\n", wParam);
1181 nAddButtons = (UINT)wParam;
1182 nOldButtons = infoPtr->nNumButtons;
1183 nNewButtons = nOldButtons + nAddButtons;
1185 if (infoPtr->nNumButtons == 0) {
1186 infoPtr->buttons =
1187 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1189 else {
1190 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1191 infoPtr->buttons =
1192 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1193 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1194 nOldButtons * sizeof(TBUTTON_INFO));
1195 COMCTL32_Free (oldButtons);
1198 infoPtr->nNumButtons = nNewButtons;
1200 /* insert new button data */
1201 for (nCount = 0; nCount < nAddButtons; nCount++) {
1202 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1203 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1204 btnPtr->idCommand = lpTbb[nCount].idCommand;
1205 btnPtr->fsState = lpTbb[nCount].fsState;
1206 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1207 btnPtr->dwData = lpTbb[nCount].dwData;
1208 btnPtr->iString = lpTbb[nCount].iString;
1209 btnPtr->bHot = FALSE;
1211 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1212 TTTOOLINFOA ti;
1214 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1215 ti.cbSize = sizeof (TTTOOLINFOA);
1216 ti.hwnd = hwnd;
1217 ti.uId = btnPtr->idCommand;
1218 ti.hinst = 0;
1219 ti.lpszText = LPSTR_TEXTCALLBACKA;
1221 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1222 0, (LPARAM)&ti);
1226 TOOLBAR_CalcToolbar (hwnd);
1228 InvalidateRect(hwnd, NULL, FALSE);
1230 return TRUE;
1234 static LRESULT
1235 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1237 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1238 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1239 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1241 TRACE("adding %d buttons!\n", wParam);
1243 nAddButtons = (UINT)wParam;
1244 nOldButtons = infoPtr->nNumButtons;
1245 nNewButtons = nOldButtons + nAddButtons;
1247 if (infoPtr->nNumButtons == 0) {
1248 infoPtr->buttons =
1249 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1251 else {
1252 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1253 infoPtr->buttons =
1254 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1255 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1256 nOldButtons * sizeof(TBUTTON_INFO));
1257 COMCTL32_Free (oldButtons);
1260 infoPtr->nNumButtons = nNewButtons;
1262 /* insert new button data */
1263 for (nCount = 0; nCount < nAddButtons; nCount++) {
1264 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1265 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1266 btnPtr->idCommand = lpTbb[nCount].idCommand;
1267 btnPtr->fsState = lpTbb[nCount].fsState;
1268 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1269 btnPtr->dwData = lpTbb[nCount].dwData;
1270 btnPtr->iString = lpTbb[nCount].iString;
1271 btnPtr->bHot = FALSE;
1273 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1274 TTTOOLINFOW ti;
1276 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1277 ti.cbSize = sizeof (TTTOOLINFOW);
1278 ti.hwnd = hwnd;
1279 ti.uId = btnPtr->idCommand;
1280 ti.hinst = 0;
1281 ti.lpszText = LPSTR_TEXTCALLBACKW;
1283 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1284 0, (LPARAM)&ti);
1288 TOOLBAR_CalcToolbar (hwnd);
1290 InvalidateRect(hwnd, NULL, FALSE);
1292 return TRUE;
1296 static LRESULT
1297 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1299 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1300 INT nIndex;
1302 if ((wParam) && (HIWORD(lParam) == 0)) {
1303 char szString[256];
1304 INT len;
1305 TRACE("adding string from resource!\n");
1307 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1308 szString, 256);
1310 TRACE("len=%d \"%s\"\n", len, szString);
1311 nIndex = infoPtr->nNumStrings;
1312 if (infoPtr->nNumStrings == 0) {
1313 infoPtr->strings =
1314 COMCTL32_Alloc (sizeof(LPWSTR));
1316 else {
1317 LPWSTR *oldStrings = infoPtr->strings;
1318 infoPtr->strings =
1319 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1320 memcpy (&infoPtr->strings[0], &oldStrings[0],
1321 sizeof(LPWSTR) * infoPtr->nNumStrings);
1322 COMCTL32_Free (oldStrings);
1325 infoPtr->strings[infoPtr->nNumStrings] =
1326 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1327 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1328 infoPtr->nNumStrings++;
1330 else {
1331 LPSTR p = (LPSTR)lParam;
1332 INT len;
1334 if (p == NULL)
1335 return -1;
1336 TRACE("adding string(s) from array!\n");
1338 nIndex = infoPtr->nNumStrings;
1339 while (*p) {
1340 len = lstrlenA (p);
1341 TRACE("len=%d \"%s\"\n", len, p);
1343 if (infoPtr->nNumStrings == 0) {
1344 infoPtr->strings =
1345 COMCTL32_Alloc (sizeof(LPWSTR));
1347 else {
1348 LPWSTR *oldStrings = infoPtr->strings;
1349 infoPtr->strings =
1350 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1351 memcpy (&infoPtr->strings[0], &oldStrings[0],
1352 sizeof(LPWSTR) * infoPtr->nNumStrings);
1353 COMCTL32_Free (oldStrings);
1356 infoPtr->strings[infoPtr->nNumStrings] =
1357 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1358 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1359 infoPtr->nNumStrings++;
1361 p += (len+1);
1365 return nIndex;
1369 static LRESULT
1370 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1372 #define MAX_RESOURCE_STRING_LENGTH 512
1373 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1374 INT nIndex;
1376 if ((wParam) && (HIWORD(lParam) == 0)) {
1377 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1378 INT len;
1379 TRACE("adding string from resource!\n");
1381 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1382 szString, MAX_RESOURCE_STRING_LENGTH);
1384 TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1385 TRACE("First char: 0x%x\n", *szString);
1386 if (szString[0] == L'|')
1388 PWSTR p = szString + 1;
1390 nIndex = infoPtr->nNumStrings;
1391 while (*p != L'|') {
1393 if (infoPtr->nNumStrings == 0) {
1394 infoPtr->strings =
1395 COMCTL32_Alloc (sizeof(LPWSTR));
1397 else {
1398 LPWSTR *oldStrings = infoPtr->strings;
1399 infoPtr->strings =
1400 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1401 memcpy (&infoPtr->strings[0], &oldStrings[0],
1402 sizeof(LPWSTR) * infoPtr->nNumStrings);
1403 COMCTL32_Free (oldStrings);
1406 len = COMCTL32_StrChrW (p, L'|') - p;
1407 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1408 infoPtr->strings[infoPtr->nNumStrings] =
1409 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1410 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1411 infoPtr->nNumStrings++;
1413 p += (len+1);
1416 else
1418 nIndex = infoPtr->nNumStrings;
1419 if (infoPtr->nNumStrings == 0) {
1420 infoPtr->strings =
1421 COMCTL32_Alloc (sizeof(LPWSTR));
1423 else {
1424 LPWSTR *oldStrings = infoPtr->strings;
1425 infoPtr->strings =
1426 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1427 memcpy (&infoPtr->strings[0], &oldStrings[0],
1428 sizeof(LPWSTR) * infoPtr->nNumStrings);
1429 COMCTL32_Free (oldStrings);
1432 infoPtr->strings[infoPtr->nNumStrings] =
1433 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1434 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1435 infoPtr->nNumStrings++;
1438 else {
1439 LPWSTR p = (LPWSTR)lParam;
1440 INT len;
1442 if (p == NULL)
1443 return -1;
1444 TRACE("adding string(s) from array!\n");
1445 nIndex = infoPtr->nNumStrings;
1446 while (*p) {
1447 len = lstrlenW (p);
1449 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1450 if (infoPtr->nNumStrings == 0) {
1451 infoPtr->strings =
1452 COMCTL32_Alloc (sizeof(LPWSTR));
1454 else {
1455 LPWSTR *oldStrings = infoPtr->strings;
1456 infoPtr->strings =
1457 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1458 memcpy (&infoPtr->strings[0], &oldStrings[0],
1459 sizeof(LPWSTR) * infoPtr->nNumStrings);
1460 COMCTL32_Free (oldStrings);
1463 infoPtr->strings[infoPtr->nNumStrings] =
1464 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1465 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1466 infoPtr->nNumStrings++;
1468 p += (len+1);
1472 return nIndex;
1476 static LRESULT
1477 TOOLBAR_AutoSize (HWND hwnd)
1479 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1480 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1481 RECT parent_rect;
1482 RECT window_rect;
1483 HWND parent;
1484 INT x, y;
1485 INT cx, cy;
1486 UINT uPosFlags = SWP_NOZORDER;
1488 TRACE("resize forced, style=%lx!\n", dwStyle);
1490 parent = GetParent (hwnd);
1491 GetClientRect(parent, &parent_rect);
1493 x = parent_rect.left;
1494 y = parent_rect.top;
1496 if (dwStyle & CCS_NORESIZE) {
1497 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1498 cx = 0;
1499 cy = 0;
1501 else {
1502 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1503 TOOLBAR_CalcToolbar (hwnd);
1504 InvalidateRect( hwnd, NULL, TRUE );
1505 cy = infoPtr->nHeight;
1506 cx = infoPtr->nWidth;
1508 if (dwStyle & CCS_NOMOVEY) {
1509 GetWindowRect(hwnd, &window_rect);
1510 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1511 y = window_rect.top;
1515 if (dwStyle & CCS_NOPARENTALIGN)
1516 uPosFlags |= SWP_NOMOVE;
1518 if (!(dwStyle & CCS_NODIVIDER))
1519 cy += GetSystemMetrics(SM_CYEDGE);
1521 if (dwStyle & WS_BORDER)
1523 x = y = 1;
1524 cy += GetSystemMetrics(SM_CYEDGE);
1525 cx += GetSystemMetrics(SM_CYEDGE);
1528 infoPtr->bAutoSize = TRUE;
1529 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1530 cx, cy, uPosFlags);
1531 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1532 * the setwindowpos calls */
1533 infoPtr->bAutoSize = FALSE;
1535 return 0;
1539 static LRESULT
1540 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1542 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1544 return infoPtr->nNumButtons;
1548 static LRESULT
1549 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1551 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1553 if (infoPtr == NULL) {
1554 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1555 ERR("infoPtr == NULL!\n");
1556 return 0;
1559 infoPtr->dwStructSize = (DWORD)wParam;
1561 return 0;
1565 static LRESULT
1566 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1568 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1569 TBUTTON_INFO *btnPtr;
1570 INT nIndex;
1572 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1573 if (nIndex == -1)
1574 return FALSE;
1576 btnPtr = &infoPtr->buttons[nIndex];
1577 btnPtr->iBitmap = LOWORD(lParam);
1579 RedrawWindow(hwnd,&btnPtr->rect,0,RDW_ERASE|RDW_INVALIDATE);
1581 return TRUE;
1585 static LRESULT
1586 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1588 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1589 TBUTTON_INFO *btnPtr;
1590 INT nIndex;
1591 INT nOldIndex = -1;
1592 BOOL bChecked = FALSE;
1594 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1595 if (nIndex == -1)
1596 return FALSE;
1598 btnPtr = &infoPtr->buttons[nIndex];
1600 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1601 return FALSE;
1603 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1605 if (LOWORD(lParam) == FALSE)
1606 btnPtr->fsState &= ~TBSTATE_CHECKED;
1607 else {
1608 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1609 nOldIndex =
1610 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1611 if (nOldIndex == nIndex)
1612 return 0;
1613 if (nOldIndex != -1)
1614 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1616 btnPtr->fsState |= TBSTATE_CHECKED;
1619 if( bChecked != LOWORD(lParam) )
1621 if (nOldIndex != -1)
1622 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,(HRGN)NULL,
1623 RDW_ERASE|RDW_INVALIDATE);
1624 RedrawWindow(hwnd,&btnPtr->rect,0,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1627 /* FIXME: Send a WM_NOTIFY?? */
1629 return TRUE;
1633 static LRESULT
1634 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1636 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1638 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1642 static LRESULT
1643 TOOLBAR_Customize (HWND hwnd)
1645 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1646 LRESULT ret;
1647 LPCVOID template;
1648 HRSRC hRes;
1649 NMHDR nmhdr;
1651 /* send TBN_BEGINADJUST notification */
1652 nmhdr.hwndFrom = hwnd;
1653 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1654 nmhdr.code = TBN_BEGINADJUST;
1656 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1657 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1659 if (!(hRes = FindResourceA (COMCTL32_hModule,
1660 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1661 RT_DIALOGA)))
1662 return FALSE;
1664 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1665 return FALSE;
1667 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1668 (LPDLGTEMPLATEA)template,
1669 hwnd,
1670 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1671 (LPARAM)infoPtr);
1673 /* send TBN_ENDADJUST notification */
1674 nmhdr.code = TBN_ENDADJUST;
1676 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1677 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1679 return ret;
1683 static LRESULT
1684 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1686 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1687 INT nIndex = (INT)wParam;
1689 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1690 return FALSE;
1692 if ((infoPtr->hwndToolTip) &&
1693 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1694 TTTOOLINFOA ti;
1696 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1697 ti.cbSize = sizeof (TTTOOLINFOA);
1698 ti.hwnd = hwnd;
1699 ti.uId = infoPtr->buttons[nIndex].idCommand;
1701 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1704 if (infoPtr->nNumButtons == 1) {
1705 TRACE(" simple delete!\n");
1706 COMCTL32_Free (infoPtr->buttons);
1707 infoPtr->buttons = NULL;
1708 infoPtr->nNumButtons = 0;
1710 else {
1711 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1712 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1714 infoPtr->nNumButtons--;
1715 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1716 if (nIndex > 0) {
1717 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1718 nIndex * sizeof(TBUTTON_INFO));
1721 if (nIndex < infoPtr->nNumButtons) {
1722 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1723 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1726 COMCTL32_Free (oldButtons);
1729 TOOLBAR_CalcToolbar (hwnd);
1731 InvalidateRect (hwnd, NULL, TRUE);
1733 return TRUE;
1737 static LRESULT
1738 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1740 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1741 TBUTTON_INFO *btnPtr;
1742 INT nIndex;
1743 DWORD bState;
1745 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1746 if (nIndex == -1)
1747 return FALSE;
1749 btnPtr = &infoPtr->buttons[nIndex];
1751 bState = btnPtr->fsState & TBSTATE_ENABLED;
1753 /* update the toolbar button state */
1754 if(LOWORD(lParam) == FALSE) {
1755 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1756 } else {
1757 btnPtr->fsState |= TBSTATE_ENABLED;
1760 /* redraw the button only if the state of the button changed */
1761 if(bState != (btnPtr->fsState & TBSTATE_ENABLED)) {
1762 RedrawWindow(hwnd,&btnPtr->rect,0,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1765 return TRUE;
1769 static inline LRESULT
1770 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1772 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1774 return infoPtr->bAnchor;
1778 static LRESULT
1779 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1781 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1782 INT nIndex;
1784 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1785 if (nIndex == -1)
1786 return -1;
1788 return infoPtr->buttons[nIndex].iBitmap;
1792 static inline LRESULT
1793 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1795 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1799 static LRESULT
1800 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1802 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1803 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1804 INT nIndex = (INT)wParam;
1805 TBUTTON_INFO *btnPtr;
1807 if (infoPtr == NULL)
1808 return FALSE;
1810 if (lpTbb == NULL)
1811 return FALSE;
1813 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1814 return FALSE;
1816 btnPtr = &infoPtr->buttons[nIndex];
1817 lpTbb->iBitmap = btnPtr->iBitmap;
1818 lpTbb->idCommand = btnPtr->idCommand;
1819 lpTbb->fsState = btnPtr->fsState;
1820 lpTbb->fsStyle = btnPtr->fsStyle;
1821 lpTbb->dwData = btnPtr->dwData;
1822 lpTbb->iString = btnPtr->iString;
1824 return TRUE;
1828 static LRESULT
1829 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1831 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1832 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1833 TBUTTON_INFO *btnPtr;
1834 INT nIndex;
1836 if (infoPtr == NULL)
1837 return -1;
1838 if (lpTbInfo == NULL)
1839 return -1;
1840 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1841 return -1;
1843 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1844 if (nIndex == -1)
1845 return -1;
1847 btnPtr = &infoPtr->buttons[nIndex];
1849 if (lpTbInfo->dwMask & TBIF_COMMAND)
1850 lpTbInfo->idCommand = btnPtr->idCommand;
1851 if (lpTbInfo->dwMask & TBIF_IMAGE)
1852 lpTbInfo->iImage = btnPtr->iBitmap;
1853 if (lpTbInfo->dwMask & TBIF_LPARAM)
1854 lpTbInfo->lParam = btnPtr->dwData;
1855 if (lpTbInfo->dwMask & TBIF_SIZE)
1856 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1857 if (lpTbInfo->dwMask & TBIF_STATE)
1858 lpTbInfo->fsState = btnPtr->fsState;
1859 if (lpTbInfo->dwMask & TBIF_STYLE)
1860 lpTbInfo->fsStyle = btnPtr->fsStyle;
1861 if (lpTbInfo->dwMask & TBIF_TEXT) {
1862 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
1864 lstrcpynWtoA (lpTbInfo->pszText,
1865 (LPWSTR)infoPtr->strings[btnPtr->iString],
1866 lpTbInfo->cchText);
1868 else lpTbInfo->pszText[0]=0;
1870 return nIndex;
1874 static LRESULT
1875 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1877 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1878 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
1879 TBUTTON_INFO *btnPtr;
1880 INT nIndex;
1882 if (infoPtr == NULL)
1883 return -1;
1884 if (lpTbInfo == NULL)
1885 return -1;
1886 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
1887 return -1;
1889 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1890 if (nIndex == -1)
1891 return -1;
1893 btnPtr = &infoPtr->buttons[nIndex];
1895 if (lpTbInfo->dwMask & TBIF_COMMAND)
1896 lpTbInfo->idCommand = btnPtr->idCommand;
1897 if (lpTbInfo->dwMask & TBIF_IMAGE)
1898 lpTbInfo->iImage = btnPtr->iBitmap;
1899 if (lpTbInfo->dwMask & TBIF_LPARAM)
1900 lpTbInfo->lParam = btnPtr->dwData;
1901 if (lpTbInfo->dwMask & TBIF_SIZE)
1902 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1903 if (lpTbInfo->dwMask & TBIF_STATE)
1904 lpTbInfo->fsState = btnPtr->fsState;
1905 if (lpTbInfo->dwMask & TBIF_STYLE)
1906 lpTbInfo->fsStyle = btnPtr->fsStyle;
1907 if (lpTbInfo->dwMask & TBIF_TEXT) {
1908 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1909 lstrcpynW (lpTbInfo->pszText,
1910 (LPWSTR)infoPtr->strings[btnPtr->iString],
1911 lpTbInfo->cchText);
1914 return nIndex;
1918 static LRESULT
1919 TOOLBAR_GetButtonSize (HWND hwnd)
1921 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1923 return MAKELONG((WORD)infoPtr->nButtonWidth,
1924 (WORD)infoPtr->nButtonHeight);
1928 static LRESULT
1929 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1931 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1932 INT nIndex, nStringIndex;
1934 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1935 if (nIndex == -1)
1936 return -1;
1938 nStringIndex = infoPtr->buttons[nIndex].iString;
1940 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1942 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1943 return -1;
1945 if (lParam == 0)
1946 return -1;
1948 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1950 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1954 static LRESULT
1955 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1957 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1958 INT nIndex, nStringIndex;
1960 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1961 if (nIndex == -1)
1962 return -1;
1964 nStringIndex = infoPtr->buttons[nIndex].iString;
1966 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1968 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1969 return -1;
1971 if (lParam == 0)
1972 return -1;
1974 lstrcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1976 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1980 /* << TOOLBAR_GetColorScheme >> */
1983 static LRESULT
1984 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1986 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1988 return (LRESULT)infoPtr->himlDis;
1992 inline static LRESULT
1993 TOOLBAR_GetExtendedStyle (HWND hwnd)
1995 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1997 return infoPtr->dwExStyle;
2001 static LRESULT
2002 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2004 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2006 return (LRESULT)infoPtr->himlHot;
2010 static LRESULT
2011 TOOLBAR_GetHotItem (HWND hwnd)
2013 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2015 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2016 return -1;
2018 if (infoPtr->nHotItem < 0)
2019 return -1;
2021 return (LRESULT)infoPtr->nHotItem;
2025 static LRESULT
2026 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2028 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2030 return (LRESULT)infoPtr->himlDef;
2034 /* << TOOLBAR_GetInsertMark >> */
2035 /* << TOOLBAR_GetInsertMarkColor >> */
2038 static LRESULT
2039 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2041 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2042 TBUTTON_INFO *btnPtr;
2043 LPRECT lpRect;
2044 INT nIndex;
2046 if (infoPtr == NULL)
2047 return FALSE;
2048 nIndex = (INT)wParam;
2049 btnPtr = &infoPtr->buttons[nIndex];
2050 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2051 return FALSE;
2052 lpRect = (LPRECT)lParam;
2053 if (lpRect == NULL)
2054 return FALSE;
2055 if (btnPtr->fsState & TBSTATE_HIDDEN)
2056 return FALSE;
2058 TOOLBAR_CalcToolbar( hwnd );
2060 lpRect->left = btnPtr->rect.left;
2061 lpRect->right = btnPtr->rect.right;
2062 lpRect->bottom = btnPtr->rect.bottom;
2063 lpRect->top = btnPtr->rect.top;
2065 return TRUE;
2069 static LRESULT
2070 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2072 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2073 LPSIZE lpSize = (LPSIZE)lParam;
2075 if (lpSize == NULL)
2076 return FALSE;
2078 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2079 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2081 TRACE("maximum size %d x %d\n",
2082 infoPtr->rcBound.right - infoPtr->rcBound.left,
2083 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2085 return TRUE;
2089 /* << TOOLBAR_GetObject >> */
2090 /* << TOOLBAR_GetPadding >> */
2093 static LRESULT
2094 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2096 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2097 TBUTTON_INFO *btnPtr;
2098 LPRECT lpRect;
2099 INT nIndex;
2101 if (infoPtr == NULL)
2102 return FALSE;
2103 nIndex = (INT)wParam;
2104 btnPtr = &infoPtr->buttons[nIndex];
2105 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2106 return FALSE;
2107 lpRect = (LPRECT)lParam;
2108 if (lpRect == NULL)
2109 return FALSE;
2111 lpRect->left = btnPtr->rect.left;
2112 lpRect->right = btnPtr->rect.right;
2113 lpRect->bottom = btnPtr->rect.bottom;
2114 lpRect->top = btnPtr->rect.top;
2116 return TRUE;
2120 static LRESULT
2121 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2123 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2125 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2126 return infoPtr->nRows;
2127 else
2128 return 1;
2132 static LRESULT
2133 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2135 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2136 INT nIndex;
2138 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2139 if (nIndex == -1)
2140 return -1;
2142 return infoPtr->buttons[nIndex].fsState;
2146 static LRESULT
2147 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2149 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2150 INT nIndex;
2152 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2153 if (nIndex == -1)
2154 return -1;
2156 return infoPtr->buttons[nIndex].fsStyle;
2160 static LRESULT
2161 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2163 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2165 if (infoPtr == NULL)
2166 return 0;
2168 return infoPtr->nMaxTextRows;
2172 static LRESULT
2173 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2175 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2177 if (infoPtr == NULL)
2178 return 0;
2179 return infoPtr->hwndToolTip;
2183 static LRESULT
2184 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2186 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2188 TRACE("%s hwnd=0x%x stub!\n",
2189 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2191 return infoPtr->bUnicode;
2195 inline static LRESULT
2196 TOOLBAR_GetVersion (HWND hwnd)
2198 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2199 return infoPtr->iVersion;
2203 static LRESULT
2204 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2206 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2207 TBUTTON_INFO *btnPtr;
2208 INT nIndex;
2210 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2211 if (nIndex == -1)
2212 return FALSE;
2214 btnPtr = &infoPtr->buttons[nIndex];
2215 if (LOWORD(lParam) == FALSE)
2216 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2217 else
2218 btnPtr->fsState |= TBSTATE_HIDDEN;
2220 TOOLBAR_CalcToolbar (hwnd);
2222 InvalidateRect (hwnd, NULL, TRUE);
2224 return TRUE;
2228 inline static LRESULT
2229 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2231 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2235 static LRESULT
2236 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2238 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2239 TBUTTON_INFO *btnPtr;
2240 INT nIndex;
2242 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2243 if (nIndex == -1)
2244 return FALSE;
2246 btnPtr = &infoPtr->buttons[nIndex];
2247 if (LOWORD(lParam) == FALSE)
2248 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2249 else
2250 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2252 RedrawWindow(hwnd,&btnPtr->rect,0,
2253 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2255 return TRUE;
2259 static LRESULT
2260 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2262 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2263 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2264 INT nIndex = (INT)wParam;
2265 TBUTTON_INFO *oldButtons;
2267 if (lpTbb == NULL)
2268 return FALSE;
2270 if (nIndex == -1) {
2271 /* EPP: this seems to be an undocumented call (from my IE4)
2272 * I assume in that case that:
2273 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2274 * - index of insertion is at the end of existing buttons
2275 * I only see this happen with nIndex == -1, but it could have a special
2276 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2278 int len;
2279 LPSTR ptr;
2281 if(lpTbb->iString) {
2282 len = lstrlenA((char*)lpTbb->iString) + 2;
2283 ptr = COMCTL32_Alloc(len);
2284 nIndex = infoPtr->nNumButtons;
2285 strcpy(ptr, (char*)lpTbb->iString);
2286 ptr[len - 1] = 0; /* ended by two '\0' */
2287 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2288 COMCTL32_Free(ptr);
2290 else {
2291 ERR("lpTbb->iString is NULL\n");
2292 return FALSE;
2295 } else if (nIndex < 0)
2296 return FALSE;
2298 TRACE("inserting button index=%d\n", nIndex);
2299 if (nIndex > infoPtr->nNumButtons) {
2300 nIndex = infoPtr->nNumButtons;
2301 TRACE("adjust index=%d\n", nIndex);
2304 oldButtons = infoPtr->buttons;
2305 infoPtr->nNumButtons++;
2306 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2307 /* pre insert copy */
2308 if (nIndex > 0) {
2309 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2310 nIndex * sizeof(TBUTTON_INFO));
2313 /* insert new button */
2314 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2315 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2316 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2317 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2318 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2319 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2321 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2322 TTTOOLINFOA ti;
2324 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2325 ti.cbSize = sizeof (TTTOOLINFOA);
2326 ti.hwnd = hwnd;
2327 ti.uId = lpTbb->idCommand;
2328 ti.hinst = 0;
2329 ti.lpszText = LPSTR_TEXTCALLBACKA;
2331 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2332 0, (LPARAM)&ti);
2335 /* post insert copy */
2336 if (nIndex < infoPtr->nNumButtons - 1) {
2337 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2338 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2341 COMCTL32_Free (oldButtons);
2343 TOOLBAR_CalcToolbar (hwnd);
2345 InvalidateRect (hwnd, NULL, FALSE);
2347 return TRUE;
2351 static LRESULT
2352 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2354 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2355 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2356 INT nIndex = (INT)wParam;
2357 TBUTTON_INFO *oldButtons;
2359 if (lpTbb == NULL)
2360 return FALSE;
2361 if (nIndex < 0)
2362 return FALSE;
2364 TRACE("inserting button index=%d\n", nIndex);
2365 if (nIndex > infoPtr->nNumButtons) {
2366 nIndex = infoPtr->nNumButtons;
2367 TRACE("adjust index=%d\n", nIndex);
2370 oldButtons = infoPtr->buttons;
2371 infoPtr->nNumButtons++;
2372 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2373 /* pre insert copy */
2374 if (nIndex > 0) {
2375 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2376 nIndex * sizeof(TBUTTON_INFO));
2379 /* insert new button */
2380 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2381 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2382 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2383 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2384 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2385 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2387 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2388 TTTOOLINFOW ti;
2390 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2391 ti.cbSize = sizeof (TTTOOLINFOW);
2392 ti.hwnd = hwnd;
2393 ti.uId = lpTbb->idCommand;
2394 ti.hinst = 0;
2395 ti.lpszText = LPSTR_TEXTCALLBACKW;
2397 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2398 0, (LPARAM)&ti);
2401 /* post insert copy */
2402 if (nIndex < infoPtr->nNumButtons - 1) {
2403 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2404 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2407 COMCTL32_Free (oldButtons);
2409 TOOLBAR_CalcToolbar (hwnd);
2411 InvalidateRect (hwnd, NULL, FALSE);
2413 return TRUE;
2417 /* << TOOLBAR_InsertMarkHitTest >> */
2420 static LRESULT
2421 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2423 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2424 INT nIndex;
2426 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2427 if (nIndex == -1)
2428 return FALSE;
2430 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2434 static LRESULT
2435 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2437 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2438 INT nIndex;
2440 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2441 if (nIndex == -1)
2442 return FALSE;
2444 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2448 static LRESULT
2449 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2451 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2452 INT nIndex;
2454 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2455 if (nIndex == -1)
2456 return FALSE;
2458 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2462 static LRESULT
2463 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2465 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2466 INT nIndex;
2468 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2469 if (nIndex == -1)
2470 return FALSE;
2472 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2476 static LRESULT
2477 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2479 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2480 INT nIndex;
2482 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2483 if (nIndex == -1)
2484 return FALSE;
2486 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2490 static LRESULT
2491 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2493 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2494 INT nIndex;
2496 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2497 if (nIndex == -1)
2498 return FALSE;
2500 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2504 /* << TOOLBAR_LoadImages >> */
2505 /* << TOOLBAR_MapAccelerator >> */
2506 /* << TOOLBAR_MarkButton >> */
2507 /* << TOOLBAR_MoveButton >> */
2510 static LRESULT
2511 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2513 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2514 TBUTTON_INFO *btnPtr;
2515 INT nIndex;
2517 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2518 if (nIndex == -1)
2519 return FALSE;
2521 btnPtr = &infoPtr->buttons[nIndex];
2522 if (LOWORD(lParam) == FALSE)
2523 btnPtr->fsState &= ~TBSTATE_PRESSED;
2524 else
2525 btnPtr->fsState |= TBSTATE_PRESSED;
2527 RedrawWindow(hwnd,&btnPtr->rect,0,
2528 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2530 return TRUE;
2534 /* << TOOLBAR_ReplaceBitmap >> */
2537 static LRESULT
2538 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2540 #if 0
2541 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2542 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2544 if (lpSave == NULL) return 0;
2546 if ((BOOL)wParam) {
2547 /* save toolbar information */
2548 FIXME("save to \"%s\" \"%s\"\n",
2549 lpSave->pszSubKey, lpSave->pszValueName);
2553 else {
2554 /* restore toolbar information */
2556 FIXME("restore from \"%s\" \"%s\"\n",
2557 lpSave->pszSubKey, lpSave->pszValueName);
2561 #endif
2563 return 0;
2567 static LRESULT
2568 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2570 #if 0
2571 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2572 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2574 if (lpSave == NULL)
2575 return 0;
2577 if ((BOOL)wParam) {
2578 /* save toolbar information */
2579 FIXME("save to \"%s\" \"%s\"\n",
2580 lpSave->pszSubKey, lpSave->pszValueName);
2584 else {
2585 /* restore toolbar information */
2587 FIXME("restore from \"%s\" \"%s\"\n",
2588 lpSave->pszSubKey, lpSave->pszValueName);
2592 #endif
2594 return 0;
2598 static LRESULT
2599 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2601 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2602 BOOL bOldAnchor = infoPtr->bAnchor;
2604 infoPtr->bAnchor = (BOOL)wParam;
2606 return (LRESULT)bOldAnchor;
2610 static LRESULT
2611 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2613 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2615 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2616 return FALSE;
2618 if (infoPtr->nNumButtons > 0)
2619 WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
2620 infoPtr->nNumButtons,
2621 infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
2622 LOWORD(lParam), HIWORD(lParam));
2624 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2625 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2627 /* uses image list internals directly */
2628 if (infoPtr->himlDef) {
2629 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
2630 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
2633 return TRUE;
2637 static LRESULT
2638 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2640 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2641 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2642 TBUTTON_INFO *btnPtr;
2643 INT nIndex;
2645 if (lptbbi == NULL)
2646 return FALSE;
2647 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2648 return FALSE;
2650 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2651 if (nIndex == -1)
2652 return FALSE;
2654 btnPtr = &infoPtr->buttons[nIndex];
2655 if (lptbbi->dwMask & TBIF_COMMAND)
2656 btnPtr->idCommand = lptbbi->idCommand;
2657 if (lptbbi->dwMask & TBIF_IMAGE)
2658 btnPtr->iBitmap = lptbbi->iImage;
2659 if (lptbbi->dwMask & TBIF_LPARAM)
2660 btnPtr->dwData = lptbbi->lParam;
2661 /* if (lptbbi->dwMask & TBIF_SIZE) */
2662 /* btnPtr->cx = lptbbi->cx; */
2663 if (lptbbi->dwMask & TBIF_STATE)
2664 btnPtr->fsState = lptbbi->fsState;
2665 if (lptbbi->dwMask & TBIF_STYLE)
2666 btnPtr->fsStyle = lptbbi->fsStyle;
2668 if (lptbbi->dwMask & TBIF_TEXT) {
2669 if ((btnPtr->iString >= 0) ||
2670 (btnPtr->iString < infoPtr->nNumStrings)) {
2671 TRACE("Ooooooch\n");
2672 #if 0
2673 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2674 INT len = lstrlenA (lptbbi->pszText);
2675 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2676 #endif
2678 /* this is the ultimate sollution */
2679 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2683 return TRUE;
2687 static LRESULT
2688 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2690 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2691 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2692 TBUTTON_INFO *btnPtr;
2693 INT nIndex;
2695 if (lptbbi == NULL)
2696 return FALSE;
2697 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2698 return FALSE;
2700 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2701 if (nIndex == -1)
2702 return FALSE;
2704 btnPtr = &infoPtr->buttons[nIndex];
2705 if (lptbbi->dwMask & TBIF_COMMAND)
2706 btnPtr->idCommand = lptbbi->idCommand;
2707 if (lptbbi->dwMask & TBIF_IMAGE)
2708 btnPtr->iBitmap = lptbbi->iImage;
2709 if (lptbbi->dwMask & TBIF_LPARAM)
2710 btnPtr->dwData = lptbbi->lParam;
2711 /* if (lptbbi->dwMask & TBIF_SIZE) */
2712 /* btnPtr->cx = lptbbi->cx; */
2713 if (lptbbi->dwMask & TBIF_STATE)
2714 btnPtr->fsState = lptbbi->fsState;
2715 if (lptbbi->dwMask & TBIF_STYLE)
2716 btnPtr->fsStyle = lptbbi->fsStyle;
2718 if (lptbbi->dwMask & TBIF_TEXT) {
2719 if ((btnPtr->iString >= 0) ||
2720 (btnPtr->iString < infoPtr->nNumStrings)) {
2721 #if 0
2722 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2723 INT len = lstrlenW (lptbbi->pszText);
2724 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2725 #endif
2727 /* this is the ultimate sollution */
2728 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2732 return TRUE;
2736 static LRESULT
2737 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2739 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2741 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2743 ERR("invalid parameter\n");
2744 return FALSE;
2747 /* Button size can only be set before adding any button to the toolbar
2748 according to the documentation. */
2749 /* this appears to be wrong. WINZIP32.EXE (ver 8) calls this on
2750 one of its buttons after adding it to the toolbar, and it
2751 checks that the return value is nonzero - mjm */
2752 if( infoPtr->nNumButtons != 0 )
2754 FIXME("Button size set after button in toolbar\n");
2755 return TRUE;
2758 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2759 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2760 return TRUE;
2764 static LRESULT
2765 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2767 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2769 if (infoPtr == NULL)
2770 return FALSE;
2772 infoPtr->cxMin = (INT)LOWORD(lParam);
2773 infoPtr->cxMax = (INT)HIWORD(lParam);
2775 return TRUE;
2779 static LRESULT
2780 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2782 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2783 INT nIndex = (INT)wParam;
2785 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2786 return FALSE;
2788 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2790 if (infoPtr->hwndToolTip) {
2792 FIXME("change tool tip!\n");
2796 return TRUE;
2800 /* << TOOLBAR_SetColorScheme >> */
2803 static LRESULT
2804 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2806 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2807 HIMAGELIST himlTemp;
2810 himlTemp = infoPtr->himlDis;
2811 infoPtr->himlDis = (HIMAGELIST)lParam;
2813 /* FIXME: redraw ? */
2815 return (LRESULT)himlTemp;
2819 static LRESULT
2820 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2822 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2823 DWORD dwTemp;
2825 dwTemp = infoPtr->dwDTFlags;
2826 infoPtr->dwDTFlags =
2827 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2829 return (LRESULT)dwTemp;
2833 static LRESULT
2834 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2836 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2837 DWORD dwTemp;
2839 dwTemp = infoPtr->dwExStyle;
2840 infoPtr->dwExStyle = (DWORD)lParam;
2842 return (LRESULT)dwTemp;
2846 static LRESULT
2847 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2849 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2850 HIMAGELIST himlTemp;
2852 himlTemp = infoPtr->himlHot;
2853 infoPtr->himlHot = (HIMAGELIST)lParam;
2855 /* FIXME: redraw ? */
2857 return (LRESULT)himlTemp;
2861 static LRESULT
2862 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
2864 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2865 INT nOldHotItem = infoPtr->nHotItem;
2867 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
2869 infoPtr->nHotItem = (INT)wParam;
2871 /* FIXME: What else must be done ??? */
2875 if (nOldHotItem < 0)
2876 return -1;
2878 return (LRESULT)nOldHotItem;
2882 static LRESULT
2883 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2885 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2886 HIMAGELIST himlTemp;
2888 himlTemp = infoPtr->himlDef;
2889 infoPtr->himlDef = (HIMAGELIST)lParam;
2891 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
2892 /* FIXME: redraw ? */
2894 return (LRESULT)himlTemp;
2898 static LRESULT
2899 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2901 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2903 infoPtr->nIndent = (INT)wParam;
2905 TOOLBAR_CalcToolbar (hwnd);
2907 InvalidateRect(hwnd, NULL, FALSE);
2909 return TRUE;
2913 /* << TOOLBAR_SetInsertMark >> */
2916 static LRESULT
2917 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2919 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2921 infoPtr->clrInsertMark = (COLORREF)lParam;
2923 /* FIXME : redraw ??*/
2925 return 0;
2929 static LRESULT
2930 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2932 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2934 if (infoPtr == NULL)
2935 return FALSE;
2937 infoPtr->nMaxTextRows = (INT)wParam;
2939 return TRUE;
2943 /* << TOOLBAR_SetPadding >> */
2946 static LRESULT
2947 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2949 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2950 HWND hwndOldNotify;
2952 if (infoPtr == NULL)
2953 return 0;
2954 hwndOldNotify = infoPtr->hwndNotify;
2955 infoPtr->hwndNotify = (HWND)wParam;
2957 return hwndOldNotify;
2961 static LRESULT
2962 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2964 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2965 LPRECT lprc = (LPRECT)lParam;
2967 if (LOWORD(wParam) > 1) {
2969 FIXME("multiple rows not supported!\n");
2973 /* recalculate toolbar */
2974 TOOLBAR_CalcToolbar (hwnd);
2976 /* return bounding rectangle */
2977 if (lprc) {
2978 lprc->left = infoPtr->rcBound.left;
2979 lprc->right = infoPtr->rcBound.right;
2980 lprc->top = infoPtr->rcBound.top;
2981 lprc->bottom = infoPtr->rcBound.bottom;
2984 /* repaint toolbar */
2985 InvalidateRect(hwnd, NULL, FALSE);
2987 return 0;
2991 static LRESULT
2992 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2994 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2995 TBUTTON_INFO *btnPtr;
2996 INT nIndex;
2998 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2999 if (nIndex == -1)
3000 return FALSE;
3002 btnPtr = &infoPtr->buttons[nIndex];
3003 btnPtr->fsState = LOWORD(lParam);
3005 RedrawWindow(hwnd,&btnPtr->rect,0,
3006 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3008 return TRUE;
3012 static LRESULT
3013 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3015 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3016 TBUTTON_INFO *btnPtr;
3017 INT nIndex;
3019 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3020 if (nIndex == -1)
3021 return FALSE;
3023 btnPtr = &infoPtr->buttons[nIndex];
3024 btnPtr->fsStyle = LOWORD(lParam);
3026 RedrawWindow(hwnd,&btnPtr->rect,0,
3027 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3029 if (infoPtr->hwndToolTip) {
3031 FIXME("change tool tip!\n");
3035 return TRUE;
3039 inline static LRESULT
3040 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3042 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3044 if (infoPtr == NULL)
3045 return 0;
3046 infoPtr->hwndToolTip = (HWND)wParam;
3047 return 0;
3051 static LRESULT
3052 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3054 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3055 BOOL bTemp;
3057 TRACE("%s hwnd=0x%04x stub!\n",
3058 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3060 bTemp = infoPtr->bUnicode;
3061 infoPtr->bUnicode = (BOOL)wParam;
3063 return bTemp;
3067 static LRESULT
3068 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3070 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3071 INT iOldVersion = infoPtr->iVersion;
3073 infoPtr->iVersion = iVersion;
3075 return iOldVersion;
3079 static LRESULT
3080 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3082 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3083 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3084 LOGFONTA logFont;
3086 /* initialize info structure */
3087 infoPtr->nButtonHeight = 22;
3088 infoPtr->nButtonWidth = 24;
3089 infoPtr->nBitmapHeight = 15;
3090 infoPtr->nBitmapWidth = 16;
3092 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3093 infoPtr->nRows = 1;
3094 infoPtr->nMaxTextRows = 1;
3095 infoPtr->cxMin = -1;
3096 infoPtr->cxMax = -1;
3097 infoPtr->nNumBitmaps = 0;
3098 infoPtr->nNumStrings = 0;
3100 infoPtr->bCaptured = FALSE;
3101 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3102 infoPtr->nButtonDown = -1;
3103 infoPtr->nOldHit = -1;
3104 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3105 infoPtr->hwndNotify = GetParent (hwnd);
3106 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3107 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3108 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3109 infoPtr->iVersion = 0;
3111 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3112 infoPtr->hFont = CreateFontIndirectA (&logFont);
3114 if (dwStyle & TBSTYLE_TOOLTIPS) {
3115 /* Create tooltip control */
3116 infoPtr->hwndToolTip =
3117 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3118 CW_USEDEFAULT, CW_USEDEFAULT,
3119 CW_USEDEFAULT, CW_USEDEFAULT,
3120 hwnd, 0, 0, 0);
3122 /* Send NM_TOOLTIPSCREATED notification */
3123 if (infoPtr->hwndToolTip) {
3124 NMTOOLTIPSCREATED nmttc;
3126 nmttc.hdr.hwndFrom = hwnd;
3127 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3128 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3129 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3131 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3132 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3136 return 0;
3140 static LRESULT
3141 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3143 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3145 /* delete tooltip control */
3146 if (infoPtr->hwndToolTip)
3147 DestroyWindow (infoPtr->hwndToolTip);
3149 /* delete button data */
3150 if (infoPtr->buttons)
3151 COMCTL32_Free (infoPtr->buttons);
3153 /* delete strings */
3154 if (infoPtr->strings) {
3155 INT i;
3156 for (i = 0; i < infoPtr->nNumStrings; i++)
3157 if (infoPtr->strings[i])
3158 COMCTL32_Free (infoPtr->strings[i]);
3160 COMCTL32_Free (infoPtr->strings);
3163 /* destroy internal image list */
3164 if (infoPtr->himlInt)
3165 ImageList_Destroy (infoPtr->himlInt);
3167 /* delete default font */
3168 if (infoPtr->hFont)
3169 DeleteObject (infoPtr->hFont);
3171 /* free toolbar info data */
3172 COMCTL32_Free (infoPtr);
3173 SetWindowLongA (hwnd, 0, 0);
3175 return 0;
3179 static LRESULT
3180 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3182 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3184 if (infoPtr->bTransparent)
3185 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3187 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3191 static LRESULT
3192 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3194 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3196 return infoPtr->hFont;
3200 static LRESULT
3201 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3203 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3204 TBUTTON_INFO *btnPtr;
3205 POINT pt;
3206 INT nHit;
3208 pt.x = (INT)LOWORD(lParam);
3209 pt.y = (INT)HIWORD(lParam);
3210 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3212 if (nHit >= 0) {
3213 btnPtr = &infoPtr->buttons[nHit];
3214 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3215 return 0;
3216 SetCapture (hwnd);
3217 infoPtr->bCaptured = TRUE;
3218 infoPtr->nButtonDown = nHit;
3220 btnPtr->fsState |= TBSTATE_PRESSED;
3222 RedrawWindow(hwnd,&btnPtr->rect,0,
3223 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3225 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3226 TOOLBAR_Customize (hwnd);
3228 return 0;
3232 static LRESULT
3233 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3235 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3236 TBUTTON_INFO *btnPtr;
3237 POINT pt;
3238 INT nHit;
3240 if (infoPtr->hwndToolTip)
3241 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3242 WM_LBUTTONDOWN, wParam, lParam);
3244 pt.x = (INT)LOWORD(lParam);
3245 pt.y = (INT)HIWORD(lParam);
3246 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3248 if (nHit >= 0) {
3249 btnPtr = &infoPtr->buttons[nHit];
3250 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3251 return 0;
3253 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
3255 NMTOOLBARA nmtb;
3257 nmtb.hdr.hwndFrom = hwnd;
3258 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3259 nmtb.hdr.code = TBN_DROPDOWN;
3260 nmtb.iItem = btnPtr->idCommand;
3262 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3263 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3266 SetCapture (hwnd);
3267 infoPtr->bCaptured = TRUE;
3268 infoPtr->nButtonDown = nHit;
3269 infoPtr->nOldHit = nHit;
3271 btnPtr->fsState |= TBSTATE_PRESSED;
3272 btnPtr->bHot = FALSE;
3274 RedrawWindow(hwnd,&btnPtr->rect,0,
3275 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3278 return 0;
3281 static LRESULT
3282 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3284 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3285 TBUTTON_INFO *btnPtr;
3286 POINT pt;
3287 INT nHit;
3288 INT nOldIndex = -1;
3289 BOOL bSendMessage = TRUE;
3291 if (infoPtr->hwndToolTip)
3292 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3293 WM_LBUTTONUP, wParam, lParam);
3295 pt.x = (INT)LOWORD(lParam);
3296 pt.y = (INT)HIWORD(lParam);
3297 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3299 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3300 if(infoPtr->nHotItem >= 0)
3301 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3303 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3304 infoPtr->bCaptured = FALSE;
3305 ReleaseCapture ();
3306 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3307 btnPtr->fsState &= ~TBSTATE_PRESSED;
3309 if (nHit == infoPtr->nButtonDown) {
3310 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3311 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3312 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3313 infoPtr->nButtonDown);
3314 if (nOldIndex == infoPtr->nButtonDown)
3315 bSendMessage = FALSE;
3316 if ((nOldIndex != infoPtr->nButtonDown) &&
3317 (nOldIndex != -1))
3318 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3319 btnPtr->fsState |= TBSTATE_CHECKED;
3321 else {
3322 if (btnPtr->fsState & TBSTATE_CHECKED)
3323 btnPtr->fsState &= ~TBSTATE_CHECKED;
3324 else
3325 btnPtr->fsState |= TBSTATE_CHECKED;
3329 else
3330 bSendMessage = FALSE;
3332 if (nOldIndex != -1)
3333 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,0,
3334 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3335 RedrawWindow(hwnd,&btnPtr->rect,0,
3336 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3338 if (bSendMessage) {
3339 SendMessageA (GetParent(hwnd), WM_COMMAND,
3340 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3342 // if ((GetWindowLongA(hwnd, GWL_STYLE) & TBSTYLE_DROPDOWN) ||
3343 // (btnPtr->fsStyle & 0x08/* BTNS_DROPDOWN */)) {
3345 * This appears to be an error. Instead of checking the style of the
3346 * button in question wine was checking the style of the toolbar
3347 * itself. This caused a number of strange behaviors. In my
3348 * invistigation i think the whole dropdown thing is still fairly
3349 * broken. but this helps fix some of the problems.
3352 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
3353 NMTOOLBARW nmtb;
3355 nmtb.hdr.hwndFrom = hwnd;
3356 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3357 nmtb.hdr.code = TBN_DROPDOWN;
3358 nmtb.iItem = nHit;
3359 /* nmtb.tbButton not used with TBN_DROPDOWN */
3360 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) {
3361 nmtb.pszText = infoPtr->strings[btnPtr->iString];
3362 nmtb.cchText = lstrlenW(nmtb.pszText);
3363 } else {
3364 nmtb.pszText = NULL;
3365 nmtb.cchText = 0;
3367 nmtb.rcButton = btnPtr->rect;
3369 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
3370 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3373 infoPtr->nButtonDown = -1;
3374 infoPtr->nOldHit = -1;
3377 return 0;
3380 static LRESULT
3381 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3383 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3384 TBUTTON_INFO *hotBtnPtr;
3386 if (infoPtr->nOldHit < 0)
3387 return TRUE;
3389 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3391 /* Redraw the button if the last button we were over is the hot button and it
3392 is enabled */
3393 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3395 hotBtnPtr->bHot = FALSE;
3397 InvalidateRect (hwnd, &hotBtnPtr->rect, TRUE);
3400 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3401 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3403 return TRUE;
3406 static LRESULT
3407 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3409 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3410 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3411 POINT pt;
3412 INT nHit;
3413 TRACKMOUSEEVENT trackinfo;
3415 /* fill in the TRACKMOUSEEVENT struct */
3416 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3417 trackinfo.dwFlags = TME_QUERY;
3418 trackinfo.hwndTrack = hwnd;
3419 trackinfo.dwHoverTime = HOVER_DEFAULT;
3421 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3422 _TrackMouseEvent(&trackinfo);
3424 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3425 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3426 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3428 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3429 /* and can properly deactivate the hot toolbar button */
3430 _TrackMouseEvent(&trackinfo);
3433 if (infoPtr->hwndToolTip)
3434 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3435 WM_MOUSEMOVE, wParam, lParam);
3437 pt.x = (INT)LOWORD(lParam);
3438 pt.y = (INT)HIWORD(lParam);
3440 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3442 if (infoPtr->nOldHit != nHit)
3444 /* Remove the effect of an old hot button if the button was enabled and was
3445 drawn with the hot button effect */
3446 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
3447 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3449 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3450 oldBtnPtr->bHot = FALSE;
3452 InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
3455 /* It's not a separator or in nowhere. It's a hot button. */
3456 if (nHit >= 0)
3458 btnPtr = &infoPtr->buttons[nHit];
3459 btnPtr->bHot = TRUE;
3461 infoPtr->nHotItem = nHit;
3463 /* only enabled buttons show hot effect */
3464 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3466 RedrawWindow(hwnd,&btnPtr->rect,0,
3467 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3471 if (infoPtr->bCaptured) {
3472 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3473 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3474 btnPtr->fsState &= ~TBSTATE_PRESSED;
3475 RedrawWindow(hwnd,&btnPtr->rect,0,
3476 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3478 else if (nHit == infoPtr->nButtonDown) {
3479 btnPtr->fsState |= TBSTATE_PRESSED;
3480 RedrawWindow(hwnd,&btnPtr->rect,0,
3481 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3484 infoPtr->nOldHit = nHit;
3486 return 0;
3490 inline static LRESULT
3491 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3493 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3494 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3495 /* else */
3496 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3500 inline static LRESULT
3501 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3503 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3504 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3506 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3510 static LRESULT
3511 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3513 TOOLBAR_INFO *infoPtr;
3515 /* allocate memory for info structure */
3516 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3517 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3519 /* paranoid!! */
3520 infoPtr->dwStructSize = sizeof(TBBUTTON);
3522 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3523 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3524 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3525 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3528 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3532 static LRESULT
3533 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3535 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3536 RECT rcWindow;
3537 HDC hdc;
3539 if (dwStyle & WS_MINIMIZE)
3540 return 0; /* Nothing to do */
3542 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3544 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3545 return 0;
3547 if (!(dwStyle & CCS_NODIVIDER))
3549 GetWindowRect (hwnd, &rcWindow);
3550 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3551 if( dwStyle & WS_BORDER )
3552 OffsetRect (&rcWindow, 1, 1);
3553 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3556 ReleaseDC( hwnd, hdc );
3558 return 0;
3562 inline static LRESULT
3563 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3565 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3566 LPNMHDR lpnmh = (LPNMHDR)lParam;
3568 TRACE("passing WM_NOTIFY!\n");
3570 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3571 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3573 #if 0
3574 if (lpnmh->code == TTN_GETDISPINFOA) {
3575 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3577 FIXME("retrieving ASCII string\n");
3580 else if (lpnmh->code == TTN_GETDISPINFOW) {
3581 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3583 FIXME("retrieving UNICODE string\n");
3586 #endif
3589 return 0;
3593 static LRESULT
3594 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3596 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3597 HDC hdc;
3598 PAINTSTRUCT ps;
3600 /* fill ps.rcPaint with a default rect */
3601 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
3603 TOOLBAR_CalcToolbar( hwnd );
3604 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
3605 TOOLBAR_Refresh (hwnd, hdc, &ps);
3606 if (!wParam) EndPaint (hwnd, &ps);
3608 return 0;
3612 static LRESULT
3613 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3615 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3616 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3617 RECT parent_rect;
3618 RECT window_rect;
3619 HWND parent;
3620 INT x, y;
3621 INT cx, cy;
3622 INT flags;
3623 UINT uPosFlags = 0;
3625 /* Resize deadlock check */
3626 if (infoPtr->bAutoSize) {
3627 infoPtr->bAutoSize = FALSE;
3628 return 0;
3631 flags = (INT) wParam;
3633 /* FIXME for flags =
3634 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3637 TRACE("sizing toolbar!\n");
3639 if (flags == SIZE_RESTORED) {
3640 /* width and height don't apply */
3641 parent = GetParent (hwnd);
3642 GetClientRect(parent, &parent_rect);
3643 x = parent_rect.left;
3644 y = parent_rect.top;
3646 if (dwStyle & CCS_NORESIZE) {
3647 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3650 * this sets the working width of the toolbar, and
3651 * Calc Toolbar will not adjust it, only the height
3653 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3654 cy = infoPtr->nHeight;
3655 cx = infoPtr->nWidth;
3656 TOOLBAR_CalcToolbar (hwnd);
3657 infoPtr->nWidth = cx;
3658 infoPtr->nHeight = cy;
3660 else {
3661 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3662 TOOLBAR_CalcToolbar (hwnd);
3663 cy = infoPtr->nHeight;
3664 cx = infoPtr->nWidth;
3666 if (dwStyle & CCS_NOMOVEY) {
3667 GetWindowRect(hwnd, &window_rect);
3668 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3669 y = window_rect.top;
3673 if (dwStyle & CCS_NOPARENTALIGN) {
3674 uPosFlags |= SWP_NOMOVE;
3675 cy = infoPtr->nHeight;
3676 cx = infoPtr->nWidth;
3679 if (!(dwStyle & CCS_NODIVIDER))
3680 cy += GetSystemMetrics(SM_CYEDGE);
3682 if (dwStyle & WS_BORDER)
3684 x = y = 1;
3685 cy += GetSystemMetrics(SM_CYEDGE);
3686 cx += GetSystemMetrics(SM_CYEDGE);
3689 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3690 cx, cy, uPosFlags | SWP_NOZORDER);
3692 return 0;
3696 static LRESULT
3697 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3699 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3701 if (nType == GWL_STYLE) {
3702 if (lpStyle->styleNew & TBSTYLE_LIST) {
3703 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3705 else {
3706 infoPtr->dwDTFlags = DT_CENTER;
3710 TOOLBAR_AutoSize (hwnd);
3712 InvalidateRect(hwnd, NULL, FALSE);
3714 return 0;
3719 static LRESULT WINAPI
3720 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3723 switch (uMsg)
3725 case WM_DESTROY:
3726 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3728 case WM_NCCREATE:
3729 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3732 if (!TOOLBAR_GetInfoPtr (hwnd))
3734 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3737 switch (uMsg)
3739 case TB_ADDBITMAP:
3740 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3742 case TB_ADDBUTTONSA:
3743 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3745 case TB_ADDBUTTONSW:
3746 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3748 case TB_ADDSTRINGA:
3749 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3751 case TB_ADDSTRINGW:
3752 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3754 case TB_AUTOSIZE:
3755 return TOOLBAR_AutoSize (hwnd);
3757 case TB_BUTTONCOUNT:
3758 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3760 case TB_BUTTONSTRUCTSIZE:
3761 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3763 case TB_CHANGEBITMAP:
3764 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3766 case TB_CHECKBUTTON:
3767 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3769 case TB_COMMANDTOINDEX:
3770 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3772 case TB_CUSTOMIZE:
3773 return TOOLBAR_Customize (hwnd);
3775 case TB_DELETEBUTTON:
3776 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3778 case TB_ENABLEBUTTON:
3779 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3781 case TB_GETANCHORHIGHLIGHT:
3782 return TOOLBAR_GetAnchorHighlight (hwnd);
3784 case TB_GETBITMAP:
3785 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3787 case TB_GETBITMAPFLAGS:
3788 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3790 case TB_GETBUTTON:
3791 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3793 case TB_GETBUTTONINFOA:
3794 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3796 case TB_GETBUTTONINFOW:
3797 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3799 case TB_GETBUTTONSIZE:
3800 return TOOLBAR_GetButtonSize (hwnd);
3802 case TB_GETBUTTONTEXTA:
3803 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3805 case TB_GETBUTTONTEXTW:
3806 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
3808 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
3810 case TB_GETDISABLEDIMAGELIST:
3811 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3813 case TB_GETEXTENDEDSTYLE:
3814 return TOOLBAR_GetExtendedStyle (hwnd);
3816 case TB_GETHOTIMAGELIST:
3817 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3819 case TB_GETHOTITEM:
3820 return TOOLBAR_GetHotItem (hwnd);
3822 case TB_GETIMAGELIST:
3823 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3825 /* case TB_GETINSERTMARK: */ /* 4.71 */
3826 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
3828 case TB_GETITEMRECT:
3829 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3831 case TB_GETMAXSIZE:
3832 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3834 /* case TB_GETOBJECT: */ /* 4.71 */
3835 /* case TB_GETPADDING: */ /* 4.71 */
3837 case TB_GETRECT:
3838 return TOOLBAR_GetRect (hwnd, wParam, lParam);
3840 case TB_GETROWS:
3841 return TOOLBAR_GetRows (hwnd, wParam, lParam);
3843 case TB_GETSTATE:
3844 return TOOLBAR_GetState (hwnd, wParam, lParam);
3846 case TB_GETSTYLE:
3847 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3849 case TB_GETTEXTROWS:
3850 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3852 case TB_GETTOOLTIPS:
3853 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3855 case TB_GETUNICODEFORMAT:
3856 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3858 case CCM_GETVERSION:
3859 return TOOLBAR_GetVersion (hwnd);
3861 case TB_HIDEBUTTON:
3862 return TOOLBAR_HideButton (hwnd, wParam, lParam);
3864 case TB_HITTEST:
3865 return TOOLBAR_HitTest (hwnd, wParam, lParam);
3867 case TB_INDETERMINATE:
3868 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3870 case TB_INSERTBUTTONA:
3871 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3873 case TB_INSERTBUTTONW:
3874 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
3876 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
3878 case TB_ISBUTTONCHECKED:
3879 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3881 case TB_ISBUTTONENABLED:
3882 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3884 case TB_ISBUTTONHIDDEN:
3885 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3887 case TB_ISBUTTONHIGHLIGHTED:
3888 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3890 case TB_ISBUTTONINDETERMINATE:
3891 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3893 case TB_ISBUTTONPRESSED:
3894 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3896 case TB_LOADIMAGES: /* 4.70 */
3897 FIXME("missing standard imagelists\n");
3898 return 0;
3900 /* case TB_MAPACCELERATORA: */ /* 4.71 */
3901 /* case TB_MAPACCELERATORW: */ /* 4.71 */
3902 /* case TB_MARKBUTTON: */ /* 4.71 */
3903 /* case TB_MOVEBUTTON: */ /* 4.71 */
3905 case TB_PRESSBUTTON:
3906 return TOOLBAR_PressButton (hwnd, wParam, lParam);
3908 /* case TB_REPLACEBITMAP: */
3910 case TB_SAVERESTOREA:
3911 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3913 case TB_SAVERESTOREW:
3914 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
3916 case TB_SETANCHORHIGHLIGHT:
3917 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
3919 case TB_SETBITMAPSIZE:
3920 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3922 case TB_SETBUTTONINFOA:
3923 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3925 case TB_SETBUTTONINFOW:
3926 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
3928 case TB_SETBUTTONSIZE:
3929 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3931 case TB_SETBUTTONWIDTH:
3932 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3934 case TB_SETCMDID:
3935 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3937 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
3939 case TB_SETDISABLEDIMAGELIST:
3940 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3942 case TB_SETDRAWTEXTFLAGS:
3943 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3945 case TB_SETEXTENDEDSTYLE:
3946 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3948 case TB_SETHOTIMAGELIST:
3949 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3951 case TB_SETHOTITEM:
3952 return TOOLBAR_SetHotItem (hwnd, wParam);
3954 case TB_SETIMAGELIST:
3955 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3957 case TB_SETINDENT:
3958 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3960 /* case TB_SETINSERTMARK: */ /* 4.71 */
3962 case TB_SETINSERTMARKCOLOR:
3963 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3965 case TB_SETMAXTEXTROWS:
3966 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3968 /* case TB_SETPADDING: */ /* 4.71 */
3970 case TB_SETPARENT:
3971 return TOOLBAR_SetParent (hwnd, wParam, lParam);
3973 case TB_SETROWS:
3974 return TOOLBAR_SetRows (hwnd, wParam, lParam);
3976 case TB_SETSTATE:
3977 return TOOLBAR_SetState (hwnd, wParam, lParam);
3979 case TB_SETSTYLE:
3980 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3982 case TB_SETTOOLTIPS:
3983 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3985 case TB_SETUNICODEFORMAT:
3986 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3988 case CCM_SETVERSION:
3989 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
3992 /* case WM_CHAR: */
3994 case WM_CREATE:
3995 return TOOLBAR_Create (hwnd, wParam, lParam);
3997 case WM_ERASEBKGND:
3998 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
4000 case WM_GETFONT:
4001 return TOOLBAR_GetFont (hwnd, wParam, lParam);
4003 /* case WM_KEYDOWN: */
4004 /* case WM_KILLFOCUS: */
4006 case WM_LBUTTONDBLCLK:
4007 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
4009 case WM_LBUTTONDOWN:
4010 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
4012 case WM_LBUTTONUP:
4013 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4015 case WM_MOUSEMOVE:
4016 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4018 case WM_MOUSELEAVE:
4019 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
4021 case WM_NCACTIVATE:
4022 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4024 case WM_NCCALCSIZE:
4025 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4027 case WM_NCPAINT:
4028 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4030 case WM_NOTIFY:
4031 return TOOLBAR_Notify (hwnd, wParam, lParam);
4033 /* case WM_NOTIFYFORMAT: */
4035 case WM_PAINT:
4036 return TOOLBAR_Paint (hwnd, wParam);
4038 case WM_SIZE:
4039 return TOOLBAR_Size (hwnd, wParam, lParam);
4041 case WM_STYLECHANGED:
4042 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4044 /* case WM_SYSCOLORCHANGE: */
4046 /* case WM_WININICHANGE: */
4048 case WM_CHARTOITEM:
4049 case WM_COMMAND:
4050 case WM_DRAWITEM:
4051 case WM_MEASUREITEM:
4052 case WM_VKEYTOITEM:
4053 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4055 default:
4056 if (uMsg >= WM_USER)
4057 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4058 uMsg, wParam, lParam);
4059 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4061 return 0;
4065 VOID
4066 TOOLBAR_Register (void)
4068 WNDCLASSA wndClass;
4070 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4071 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4072 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4073 wndClass.cbClsExtra = 0;
4074 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4075 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4076 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4077 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4079 RegisterClassA (&wndClass);
4083 VOID
4084 TOOLBAR_Unregister (void)
4086 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);