Fixes the line of garbage at the bottom of images and the fact that
[wine/hacks.git] / dlls / comctl32 / toolbar.c
blob0deab8e46b928dcf7011dbd0ab8b33dfe71dc760
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).
17 * Testing:
18 * - Run tests using Waite Group Windows95 API Bible Volume 2.
19 * The second cdrom contains executables addstr.exe, btncount.exe,
20 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
21 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
22 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
23 * setparnt.exe, setrows.exe, toolwnd.exe.
24 * - Microsofts controlspy examples.
27 #include <string.h>
29 #include "winbase.h"
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "commctrl.h"
34 #include "cache.h"
35 #include "comctl32.h"
36 #include "toolbar.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(toolbar)
41 #define SEPARATOR_WIDTH 8
42 #define TOP_BORDER 2
43 #define BOTTOM_BORDER 2
45 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
48 static void
49 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
51 INT x = (lpRect->left + lpRect->right) / 2 - 1;
52 INT yBottom = lpRect->bottom - 3;
53 INT yTop = lpRect->top + 1;
55 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
56 MoveToEx (hdc, x, yBottom, NULL);
57 LineTo (hdc, x, yTop);
58 x++;
59 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
60 MoveToEx (hdc, x, yBottom, NULL);
61 LineTo (hdc, x, yTop);
65 * Draw the text string for this button.
66 * note: himl is not used, except to determine whether this button has
67 * an associated bitmap. If so, the text is drawn below it, otherwise
68 * the text is drawn within the rectangle of the button itself.
70 static void
71 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
72 HDC hdc, INT nState, DWORD dwStyle, HIMAGELIST himl)
74 RECT rcText = btnPtr->rect;
75 HFONT hOldFont;
76 INT nOldBkMode;
77 COLORREF clrOld;
79 /* draw text */
80 if ((btnPtr->iString > -1) && (btnPtr->iString < infoPtr->nNumStrings)) {
82 InflateRect (&rcText, -3, -3);
84 if (himl && btnPtr->iBitmap>=0) {
85 if (dwStyle & TBSTYLE_LIST) {
86 rcText.left += infoPtr->nBitmapWidth;
88 else {
89 rcText.top += infoPtr->nBitmapHeight;
93 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
94 OffsetRect (&rcText, 1, 1);
96 hOldFont = SelectObject (hdc, infoPtr->hFont);
97 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
98 if (!(nState & TBSTATE_ENABLED)) {
99 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
100 OffsetRect (&rcText, 1, 1);
101 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
102 &rcText, infoPtr->dwDTFlags);
103 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
104 OffsetRect (&rcText, -1, -1);
105 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
106 &rcText, infoPtr->dwDTFlags);
108 else if (nState & TBSTATE_INDETERMINATE) {
109 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
110 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
111 &rcText, infoPtr->dwDTFlags);
113 else {
114 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
115 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
116 &rcText, infoPtr->dwDTFlags);
119 SetTextColor (hdc, clrOld);
120 SelectObject (hdc, hOldFont);
121 if (nOldBkMode != TRANSPARENT)
122 SetBkMode (hdc, nOldBkMode);
127 static void
128 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
130 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
131 INT cx = lpRect->right - lpRect->left;
132 INT cy = lpRect->bottom - lpRect->top;
133 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
134 SelectObject (hdc, hbr);
138 static void
139 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
140 HDC hdc, INT x, INT y)
142 /* FIXME: this function is a hack since it uses image list
143 internals directly */
145 HIMAGELIST himl = infoPtr->himlDef;
146 HBITMAP hbmMask;
147 HDC hdcImageList;
148 HDC hdcMask;
150 if (!himl)
151 return;
153 /* create new dc's */
154 hdcImageList = CreateCompatibleDC (0);
155 hdcMask = CreateCompatibleDC (0);
157 /* create new bitmap */
158 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
159 SelectObject (hdcMask, hbmMask);
161 /* copy the mask bitmap */
162 SelectObject (hdcImageList, himl->hbmMask);
163 SetBkColor (hdcImageList, RGB(255, 255, 255));
164 SetTextColor (hdcImageList, RGB(0, 0, 0));
165 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
166 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
168 #if 0
169 /* add white mask from image */
170 SelectObject (hdcImageList, himl->hbmImage);
171 SetBkColor (hdcImageList, RGB(0, 0, 0));
172 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
173 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
174 #endif
176 /* draw the new mask */
177 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
178 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
179 hdcMask, 0, 0, 0xB8074A);
181 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
182 BitBlt (hdc, x, y, himl->cx, himl->cy,
183 hdcMask, 0, 0, 0xB8074A);
185 DeleteObject (hbmMask);
186 DeleteDC (hdcMask);
187 DeleteDC (hdcImageList);
191 static void
192 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
194 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
195 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
196 RECT rc;
198 if (btnPtr->fsState & TBSTATE_HIDDEN)
199 return;
201 rc = btnPtr->rect;
203 /* separator */
204 if (btnPtr->fsStyle & TBSTYLE_SEP) {
205 if ((dwStyle & TBSTYLE_FLAT) && (btnPtr->iBitmap == 0))
206 TOOLBAR_DrawFlatSeparator (&rc, hdc);
207 return;
210 /* disabled */
211 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
212 if (!(dwStyle & TBSTYLE_FLAT))
213 DrawEdge (hdc, &rc, EDGE_RAISED,
214 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
216 if (infoPtr->himlDis && btnPtr->iBitmap>=0)
217 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
218 rc.left+1, rc.top+1, ILD_NORMAL);
219 else
220 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
222 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
223 infoPtr->himlDis);
224 return;
227 /* pressed TBSTYLE_BUTTON */
228 if (btnPtr->fsState & TBSTATE_PRESSED) {
229 if (dwStyle & TBSTYLE_FLAT)
230 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
231 else
232 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
233 if (btnPtr->iBitmap>=0)
234 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
235 rc.left+2, rc.top+2, ILD_NORMAL);
236 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
237 infoPtr->himlDef);
238 return;
241 /* checked TBSTYLE_CHECK */
242 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
243 (btnPtr->fsState & TBSTATE_CHECKED)) {
244 if (dwStyle & TBSTYLE_FLAT)
245 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
246 BF_RECT | BF_MIDDLE | BF_ADJUST);
247 else
248 DrawEdge (hdc, &rc, EDGE_SUNKEN,
249 BF_RECT | BF_MIDDLE | BF_ADJUST);
251 TOOLBAR_DrawPattern (hdc, &rc);
253 if (btnPtr->iBitmap>=0)
254 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
255 rc.left+2, rc.top+2, ILD_NORMAL);
257 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
258 infoPtr->himlDef);
259 return;
262 /* indeterminate */
263 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
264 DrawEdge (hdc, &rc, EDGE_RAISED,
265 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
267 TOOLBAR_DrawPattern (hdc, &rc);
268 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
269 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
270 infoPtr->himlDef);
271 return;
274 /* normal state */
275 if (dwStyle & TBSTYLE_FLAT)
277 if (btnPtr->bHot)
278 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
279 if (btnPtr->bHot && infoPtr->himlHot && btnPtr->iBitmap>=0)
280 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
281 rc.left +2, rc.top +2, ILD_NORMAL);
282 else if (btnPtr->iBitmap>=0)
283 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
284 rc.left +2, rc.top +2, ILD_NORMAL);
286 else
288 DrawEdge (hdc, &rc, EDGE_RAISED,
289 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
291 if (btnPtr->iBitmap>=0)
292 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
293 rc.left+1, rc.top+1, ILD_NORMAL);
296 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
297 infoPtr->himlDef);
301 static void
302 TOOLBAR_Refresh (HWND hwnd, HDC hdc)
304 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
305 TBUTTON_INFO *btnPtr;
306 INT i;
308 /* draw buttons */
309 btnPtr = infoPtr->buttons;
310 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
311 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
315 static void
316 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
318 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
319 TBUTTON_INFO *btnPtr;
320 INT i;
321 HDC hdc;
322 HFONT hOldFont;
323 SIZE sz;
326 lpSize->cx = 0;
327 lpSize->cy = 0;
328 hdc = GetDC (0);
329 hOldFont = SelectObject (hdc, infoPtr->hFont);
331 btnPtr = infoPtr->buttons;
332 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
333 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
334 (btnPtr->iString > -1) &&
335 (btnPtr->iString < infoPtr->nNumStrings)) {
336 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
337 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), &sz);
338 if (sz.cx > lpSize->cx)
339 lpSize->cx = sz.cx;
340 if (sz.cy > lpSize->cy)
341 lpSize->cy = sz.cy;
345 SelectObject (hdc, hOldFont);
346 ReleaseDC (0, hdc);
348 TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
351 /***********************************************************************
352 * TOOLBAR_WrapToolbar
354 * This function walks through the buttons and seperators in the
355 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
356 * wrapping should occur based on the width of the toolbar window.
357 * It does *not* calculate button placement itself. That task
358 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
359 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
360 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
363 static void
364 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
366 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
367 TBUTTON_INFO *btnPtr;
368 INT x, cx, i, j;
369 RECT rc;
370 BOOL bWrap, bButtonWrap;
372 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
373 /* no layout is necessary. Applications may use this style */
374 /* to perform their own layout on the toolbar. */
375 if( !(dwStyle & TBSTYLE_WRAPABLE) )
376 return;
378 btnPtr = infoPtr->buttons;
379 x = infoPtr->nIndent;
381 /* this can get the parents width, to know how far we can extend
382 * this toolbar. We cannot use its height, as there may be multiple
383 * toolbars in a rebar control
385 GetClientRect( GetParent(hwnd), &rc );
386 infoPtr->nWidth = rc.right - rc.left;
387 bButtonWrap = FALSE;
389 for (i = 0; i < infoPtr->nNumButtons; i++ )
391 bWrap = FALSE;
392 btnPtr[i].fsState &= ~TBSTATE_WRAP;
394 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
395 continue;
397 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
398 /* it is the actual width of the separator. This is used for */
399 /* custom controls in toolbars. */
400 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
401 cx = (btnPtr[i].iBitmap > 0) ?
402 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
403 else
404 cx = infoPtr->nButtonWidth;
406 /* Two or more adjacent separators form a separator group. */
407 /* The first separator in a group should be wrapped to the */
408 /* next row if the previous wrapping is on a button. */
409 if( bButtonWrap &&
410 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
411 (i + 1 < infoPtr->nNumButtons ) &&
412 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
414 btnPtr[i].fsState |= TBSTATE_WRAP;
415 x = infoPtr->nIndent;
416 i++;
417 bButtonWrap = FALSE;
418 continue;
421 /* The layout makes sure the bitmap is visible, but not the button. */
422 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
423 > infoPtr->nWidth )
425 BOOL bFound = FALSE;
427 /* If the current button is a separator and not hidden, */
428 /* go to the next until it reaches a non separator. */
429 /* Wrap the last separator if it is before a button. */
430 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
431 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
432 i < infoPtr->nNumButtons )
434 i++;
435 bFound = TRUE;
438 if( bFound && i < infoPtr->nNumButtons )
440 i--;
441 btnPtr[i].fsState |= TBSTATE_WRAP;
442 x = infoPtr->nIndent;
443 bButtonWrap = FALSE;
444 continue;
446 else if ( i >= infoPtr->nNumButtons)
447 break;
449 /* If the current button is not a separator, find the last */
450 /* separator and wrap it. */
451 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
453 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
454 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
456 bFound = TRUE;
457 i = j;
458 x = infoPtr->nIndent;
459 btnPtr[j].fsState |= TBSTATE_WRAP;
460 bButtonWrap = FALSE;
461 break;
465 /* If no separator available for wrapping, wrap one of */
466 /* non-hidden previous button. */
467 if (!bFound)
469 for ( j = i - 1;
470 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
472 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
473 continue;
475 bFound = TRUE;
476 i = j;
477 x = infoPtr->nIndent;
478 btnPtr[j].fsState |= TBSTATE_WRAP;
479 bButtonWrap = TRUE;
480 break;
484 /* If all above failed, wrap the current button. */
485 if (!bFound)
487 btnPtr[i].fsState |= TBSTATE_WRAP;
488 bFound = TRUE;
489 x = infoPtr->nIndent;
490 if (btnPtr[i].fsState & TBSTYLE_SEP )
491 bButtonWrap = FALSE;
492 else
493 bButtonWrap = TRUE;
496 else
497 x += cx;
501 /***********************************************************************
502 * TOOLBAR_CalcToolbar
504 * This function calculates button and separator placement. It first
505 * calculates the button sizes, gets the toolbar window width and then
506 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
507 * on. It assigns a new location to each item and sends this location to
508 * the tooltip window if appropriate. Finally, it updates the rcBound
509 * rect and calculates the new required toolbar window height.
512 static void
513 TOOLBAR_CalcToolbar (HWND hwnd)
515 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
516 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
517 TBUTTON_INFO *btnPtr;
518 INT i, nRows, nSepRows;
519 INT x, y, cx, cy;
520 SIZE sizeString;
521 BOOL bWrap;
523 TOOLBAR_CalcStrings (hwnd, &sizeString);
525 if (dwStyle & TBSTYLE_LIST) {
526 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
527 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
529 else {
530 BOOL usesBitmaps = FALSE;
531 INT i;
533 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
534 if (infoPtr->buttons[i].iBitmap >=0)
535 usesBitmaps = TRUE;
537 if (sizeString.cy > 0)
538 if (usesBitmaps)
539 infoPtr->nButtonHeight = sizeString.cy + infoPtr->nBitmapHeight + 6;
540 else
541 infoPtr->nButtonHeight = sizeString.cy + 6;
542 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
543 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
545 if (sizeString.cx > infoPtr->nBitmapWidth)
546 infoPtr->nButtonWidth = sizeString.cx + 6;
547 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
548 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
551 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
552 infoPtr->nButtonWidth = infoPtr->cxMin;
553 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
554 infoPtr->nButtonWidth = infoPtr->cxMax;
556 TOOLBAR_WrapToolbar( hwnd, dwStyle );
558 x = infoPtr->nIndent;
559 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
562 * We wills et the height below, and we set the width on entry
563 * so we do not reset them here..
565 #if 0
566 GetClientRect( hwnd, &rc );
567 /* get initial values for toolbar */
568 infoPtr->nWidth = rc.right - rc.left;
569 infoPtr->nHeight = rc.bottom - rc.top;
570 #endif
572 /* from above, minimum is a button, and possible text */
573 cx = infoPtr->nButtonWidth;
574 /* cannot use just ButtonHeight, we may have no buttons! */
575 if (infoPtr->nNumButtons > 0)
576 infoPtr->nHeight = infoPtr->nButtonHeight;
577 cy = infoPtr->nHeight;
579 nRows = nSepRows = 0;
581 infoPtr->rcBound.top = y;
582 infoPtr->rcBound.left = x;
583 infoPtr->rcBound.bottom = y + cy;
584 infoPtr->rcBound.right = x;
586 btnPtr = infoPtr->buttons;
588 /* do not base height/width on parent, if the parent is a */
589 /* rebar control it could have multiple rows of toolbars */
590 /* GetClientRect( GetParent(hwnd), &rc ); */
591 /* cx = rc.right - rc.left; */
592 /* cy = rc.bottom - rc.top; */
594 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
596 bWrap = FALSE;
597 if (btnPtr->fsState & TBSTATE_HIDDEN)
599 SetRectEmpty (&btnPtr->rect);
600 continue;
603 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
604 /* it is the actual width of the separator. This is used for */
605 /* custom controls in toolbars. */
606 if (btnPtr->fsStyle & TBSTYLE_SEP)
607 cx = (btnPtr->iBitmap > 0) ?
608 btnPtr->iBitmap : SEPARATOR_WIDTH;
609 else {
610 cx = infoPtr->nButtonWidth;
612 cy = infoPtr->nHeight;
614 if (btnPtr->fsState & TBSTATE_WRAP )
615 bWrap = TRUE;
617 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
619 if (infoPtr->rcBound.left > x)
620 infoPtr->rcBound.left = x;
621 if (infoPtr->rcBound.right < x + cx)
622 infoPtr->rcBound.right = x + cx;
623 if (infoPtr->rcBound.bottom < y + cy)
624 infoPtr->rcBound.bottom = y + cy;
626 /* Set the toolTip only for non-hidden, non-separator button */
627 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
629 TTTOOLINFOA ti;
631 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
632 ti.cbSize = sizeof(TTTOOLINFOA);
633 ti.hwnd = hwnd;
634 ti.uId = btnPtr->idCommand;
635 ti.rect = btnPtr->rect;
636 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
637 0, (LPARAM)&ti);
640 /* btnPtr->nRow is zero based. The space between the rows is */
641 /* also considered as a row. */
642 btnPtr->nRow = nRows + nSepRows;
643 if( bWrap )
645 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
646 y += cy;
647 else
649 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
650 /* it is the actual width of the separator. This is used for */
651 /* custom controls in toolbars. */
652 y += cy + ( (btnPtr->iBitmap > 0 ) ?
653 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
655 /* nSepRows is used to calculate the extra height follwoing */
656 /* the last row. */
657 nSepRows++;
659 x = infoPtr->nIndent;
660 nRows++;
662 else
663 x += cx;
666 /* infoPtr->nRows is the number of rows on the toolbar */
667 infoPtr->nRows = nRows + nSepRows + 1;
669 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
670 /* the last row. */
671 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
672 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
673 nSepRows * (infoPtr->nBitmapHeight + 1) +
674 BOTTOM_BORDER;
675 TRACE("toolbar height %d\n", infoPtr->nHeight);
679 static INT
680 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
682 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
683 TBUTTON_INFO *btnPtr;
684 INT i;
686 btnPtr = infoPtr->buttons;
687 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
688 if (btnPtr->fsState & TBSTATE_HIDDEN)
689 continue;
691 if (btnPtr->fsStyle & TBSTYLE_SEP) {
692 if (PtInRect (&btnPtr->rect, *lpPt)) {
693 TRACE(" ON SEPARATOR %d!\n", i);
694 return -i;
697 else {
698 if (PtInRect (&btnPtr->rect, *lpPt)) {
699 TRACE(" ON BUTTON %d!\n", i);
700 return i;
705 TRACE(" NOWHERE!\n");
706 return -1;
710 static INT
711 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
713 TBUTTON_INFO *btnPtr;
714 INT i;
716 btnPtr = infoPtr->buttons;
717 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
718 if (btnPtr->idCommand == idCommand) {
719 TRACE("command=%d index=%d\n", idCommand, i);
720 return i;
723 TRACE("no index found for command=%d\n", idCommand);
724 return -1;
728 static INT
729 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
731 TBUTTON_INFO *btnPtr;
732 INT nRunIndex;
734 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
735 return -1;
737 /* check index button */
738 btnPtr = &infoPtr->buttons[nIndex];
739 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
740 if (btnPtr->fsState & TBSTATE_CHECKED)
741 return nIndex;
744 /* check previous buttons */
745 nRunIndex = nIndex - 1;
746 while (nRunIndex >= 0) {
747 btnPtr = &infoPtr->buttons[nRunIndex];
748 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
749 if (btnPtr->fsState & TBSTATE_CHECKED)
750 return nRunIndex;
752 else
753 break;
754 nRunIndex--;
757 /* check next buttons */
758 nRunIndex = nIndex + 1;
759 while (nRunIndex < infoPtr->nNumButtons) {
760 btnPtr = &infoPtr->buttons[nRunIndex];
761 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
762 if (btnPtr->fsState & TBSTATE_CHECKED)
763 return nRunIndex;
765 else
766 break;
767 nRunIndex++;
770 return -1;
774 static VOID
775 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
776 WPARAM wParam, LPARAM lParam)
778 MSG msg;
780 msg.hwnd = hwndMsg;
781 msg.message = uMsg;
782 msg.wParam = wParam;
783 msg.lParam = lParam;
784 msg.time = GetMessageTime ();
785 msg.pt.x = LOWORD(GetMessagePos ());
786 msg.pt.y = HIWORD(GetMessagePos ());
788 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
792 /***********************************************************************
793 * TOOLBAR_CustomizeDialogProc
794 * This function implements the toolbar customization dialog.
796 static BOOL WINAPI
797 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
799 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
800 static HDSA hDsa = NULL;
802 switch (uMsg)
804 case WM_INITDIALOG:
805 infoPtr = (TOOLBAR_INFO *)lParam;
806 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
808 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
810 if (infoPtr)
812 TBUTTON_INFO *btnPtr;
813 INT i;
815 /* insert 'virtual' separator button into 'available buttons' list */
816 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
818 /* copy all buttons and append them to the right listbox */
819 btnPtr = infoPtr->buttons;
820 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
822 DSA_InsertItem (hDsa, i, btnPtr);
824 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
825 if (btnPtr->fsState & TBSTATE_HIDDEN)
827 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
829 else
831 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
835 /* append 'virtual' separator button to the 'toolbar buttons' list */
836 /* TODO */
838 return TRUE;
840 case WM_CLOSE:
841 EndDialog(hwnd, FALSE);
842 return TRUE;
844 case WM_COMMAND:
845 switch (LOWORD(wParam))
847 case IDCANCEL:
848 EndDialog(hwnd, FALSE);
849 break;
851 return TRUE;
853 case WM_DESTROY:
854 if (hDsa)
855 DSA_Destroy (hDsa);
856 return TRUE;
858 case WM_DRAWITEM:
859 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
861 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
862 TBUTTON_INFO btnPtr;
863 RECT rcButton;
864 RECT rcText;
865 HPEN hOldPen;
866 HBRUSH hOldBrush;
867 COLORREF oldText = 0;
868 COLORREF oldBk = 0;
870 FIXME("action: %x itemState: %x\n",
871 lpdis->itemAction, lpdis->itemState);
873 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
875 if (lpdis->itemState & ODS_FOCUS)
877 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
878 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
881 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
882 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
884 /* fill background rectangle */
885 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
886 lpdis->rcItem.right, lpdis->rcItem.bottom);
888 /* calculate button and text rectangles */
889 CopyRect (&rcButton, &lpdis->rcItem);
890 InflateRect (&rcButton, -1, -1);
891 CopyRect (&rcText, &rcButton);
892 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
893 rcText.left = rcButton.right + 2;
895 /* draw focus rectangle */
896 if (lpdis->itemState & ODS_FOCUS)
897 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
899 /* draw button */
900 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
902 /* draw image and text */
903 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
905 /* virtual separator in the 'available' list */
906 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
907 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
909 else
911 /* real button */
913 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
914 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
916 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
917 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
921 if (lpdis->itemState & ODS_FOCUS)
923 SetBkColor (lpdis->hDC, oldBk);
924 SetTextColor (lpdis->hDC, oldText);
927 SelectObject (lpdis->hDC, hOldBrush);
928 SelectObject (lpdis->hDC, hOldPen);
930 return TRUE;
932 return FALSE;
934 case WM_MEASUREITEM:
935 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
937 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
939 if (infoPtr)
940 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
941 else
942 lpmis->itemHeight = 15 + 8; /* default height */
944 return TRUE;
946 return FALSE;
948 default:
949 return FALSE;
954 /***********************************************************************
955 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
958 static LRESULT
959 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
961 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
962 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
963 INT nIndex = 0, nButtons;
964 HBITMAP hbmLoad;
966 if (!lpAddBmp)
967 return -1;
969 if (lpAddBmp->hInst == HINST_COMMCTRL)
971 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
972 nButtons = 15;
973 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
974 nButtons = 13;
975 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
976 nButtons = 5;
977 else
978 return -1;
980 TRACE ("adding %d internal bitmaps!\n", nButtons);
982 /* Windows resize all the buttons to the size of a newly added standard image */
983 if (lpAddBmp->nID & 1)
985 /* large icons */
986 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
987 MAKELPARAM((WORD)26, (WORD)26));
988 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
989 MAKELPARAM((WORD)33, (WORD)33));
991 else
993 /* small icons */
994 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
995 MAKELPARAM((WORD)16, (WORD)16));
996 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
997 MAKELPARAM((WORD)22, (WORD)22));
1000 TOOLBAR_CalcToolbar (hwnd);
1002 else
1004 nButtons = (INT)wParam;
1005 if (nButtons <= 0)
1006 return -1;
1008 TRACE ("adding %d bitmaps!\n", nButtons);
1011 if (!(infoPtr->himlDef)) {
1012 /* create new default image list */
1013 TRACE ("creating default image list!\n");
1015 infoPtr->himlDef =
1016 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1017 ILC_COLOR | ILC_MASK, nButtons, 2);
1018 infoPtr->himlInt = infoPtr->himlDef;
1021 /* Add bitmaps to the default image list */
1022 if (lpAddBmp->hInst == (HINSTANCE)0)
1024 nIndex =
1025 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1026 CLR_DEFAULT);
1028 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1030 /* Add system bitmaps */
1031 switch (lpAddBmp->nID)
1033 case IDB_STD_SMALL_COLOR:
1034 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1035 MAKEINTRESOURCEA(IDB_STD_SMALL));
1036 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1037 hbmLoad, CLR_DEFAULT);
1038 DeleteObject (hbmLoad);
1039 break;
1041 case IDB_STD_LARGE_COLOR:
1042 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1043 MAKEINTRESOURCEA(IDB_STD_LARGE));
1044 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1045 hbmLoad, CLR_DEFAULT);
1046 DeleteObject (hbmLoad);
1047 break;
1049 case IDB_VIEW_SMALL_COLOR:
1050 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1051 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1052 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1053 hbmLoad, CLR_DEFAULT);
1054 DeleteObject (hbmLoad);
1055 break;
1057 case IDB_VIEW_LARGE_COLOR:
1058 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1059 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1060 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1061 hbmLoad, CLR_DEFAULT);
1062 DeleteObject (hbmLoad);
1063 break;
1065 case IDB_HIST_SMALL_COLOR:
1066 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1067 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1068 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1069 hbmLoad, CLR_DEFAULT);
1070 DeleteObject (hbmLoad);
1071 break;
1073 case IDB_HIST_LARGE_COLOR:
1074 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1075 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1076 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1077 hbmLoad, CLR_DEFAULT);
1078 DeleteObject (hbmLoad);
1079 break;
1081 default:
1082 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1083 ERR ("invalid imagelist!\n");
1084 break;
1087 else
1089 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1090 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1091 DeleteObject (hbmLoad);
1094 infoPtr->nNumBitmaps += nButtons;
1096 return nIndex;
1100 static LRESULT
1101 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1103 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1104 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1105 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1107 TRACE("adding %d buttons!\n", wParam);
1109 nAddButtons = (UINT)wParam;
1110 nOldButtons = infoPtr->nNumButtons;
1111 nNewButtons = nOldButtons + nAddButtons;
1113 if (infoPtr->nNumButtons == 0) {
1114 infoPtr->buttons =
1115 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1117 else {
1118 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1119 infoPtr->buttons =
1120 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1121 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1122 nOldButtons * sizeof(TBUTTON_INFO));
1123 COMCTL32_Free (oldButtons);
1126 infoPtr->nNumButtons = nNewButtons;
1128 /* insert new button data */
1129 for (nCount = 0; nCount < nAddButtons; nCount++) {
1130 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1131 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1132 btnPtr->idCommand = lpTbb[nCount].idCommand;
1133 btnPtr->fsState = lpTbb[nCount].fsState;
1134 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1135 btnPtr->dwData = lpTbb[nCount].dwData;
1136 btnPtr->iString = lpTbb[nCount].iString;
1137 btnPtr->bHot = FALSE;
1139 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1140 TTTOOLINFOA ti;
1142 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1143 ti.cbSize = sizeof (TTTOOLINFOA);
1144 ti.hwnd = hwnd;
1145 ti.uId = btnPtr->idCommand;
1146 ti.hinst = 0;
1147 ti.lpszText = LPSTR_TEXTCALLBACKA;
1149 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1150 0, (LPARAM)&ti);
1154 TOOLBAR_CalcToolbar (hwnd);
1156 InvalidateRect(hwnd, NULL, FALSE);
1158 return TRUE;
1162 static LRESULT
1163 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1165 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1166 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1167 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1169 TRACE("adding %d buttons!\n", wParam);
1171 nAddButtons = (UINT)wParam;
1172 nOldButtons = infoPtr->nNumButtons;
1173 nNewButtons = nOldButtons + nAddButtons;
1175 if (infoPtr->nNumButtons == 0) {
1176 infoPtr->buttons =
1177 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1179 else {
1180 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1181 infoPtr->buttons =
1182 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1183 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1184 nOldButtons * sizeof(TBUTTON_INFO));
1185 COMCTL32_Free (oldButtons);
1188 infoPtr->nNumButtons = nNewButtons;
1190 /* insert new button data */
1191 for (nCount = 0; nCount < nAddButtons; nCount++) {
1192 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1193 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1194 btnPtr->idCommand = lpTbb[nCount].idCommand;
1195 btnPtr->fsState = lpTbb[nCount].fsState;
1196 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1197 btnPtr->dwData = lpTbb[nCount].dwData;
1198 btnPtr->iString = lpTbb[nCount].iString;
1199 btnPtr->bHot = FALSE;
1201 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1202 TTTOOLINFOW ti;
1204 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1205 ti.cbSize = sizeof (TTTOOLINFOW);
1206 ti.hwnd = hwnd;
1207 ti.uId = btnPtr->idCommand;
1208 ti.hinst = 0;
1209 ti.lpszText = LPSTR_TEXTCALLBACKW;
1211 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1212 0, (LPARAM)&ti);
1216 TOOLBAR_CalcToolbar (hwnd);
1218 InvalidateRect(hwnd, NULL, FALSE);
1220 return TRUE;
1224 static LRESULT
1225 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1227 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1228 INT nIndex;
1230 if ((wParam) && (HIWORD(lParam) == 0)) {
1231 char szString[256];
1232 INT len;
1233 TRACE("adding string from resource!\n");
1235 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1236 szString, 256);
1238 TRACE("len=%d \"%s\"\n", len, szString);
1239 nIndex = infoPtr->nNumStrings;
1240 if (infoPtr->nNumStrings == 0) {
1241 infoPtr->strings =
1242 COMCTL32_Alloc (sizeof(LPWSTR));
1244 else {
1245 LPWSTR *oldStrings = infoPtr->strings;
1246 infoPtr->strings =
1247 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1248 memcpy (&infoPtr->strings[0], &oldStrings[0],
1249 sizeof(LPWSTR) * infoPtr->nNumStrings);
1250 COMCTL32_Free (oldStrings);
1253 infoPtr->strings[infoPtr->nNumStrings] =
1254 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1255 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1256 infoPtr->nNumStrings++;
1258 else {
1259 LPSTR p = (LPSTR)lParam;
1260 INT len;
1262 if (p == NULL)
1263 return -1;
1264 TRACE("adding string(s) from array!\n");
1265 nIndex = infoPtr->nNumStrings;
1266 while (*p) {
1267 len = lstrlenA (p);
1268 TRACE("len=%d \"%s\"\n", len, p);
1270 if (infoPtr->nNumStrings == 0) {
1271 infoPtr->strings =
1272 COMCTL32_Alloc (sizeof(LPWSTR));
1274 else {
1275 LPWSTR *oldStrings = infoPtr->strings;
1276 infoPtr->strings =
1277 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1278 memcpy (&infoPtr->strings[0], &oldStrings[0],
1279 sizeof(LPWSTR) * infoPtr->nNumStrings);
1280 COMCTL32_Free (oldStrings);
1283 infoPtr->strings[infoPtr->nNumStrings] =
1284 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1285 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1286 infoPtr->nNumStrings++;
1288 p += (len+1);
1292 return nIndex;
1296 static LRESULT
1297 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1299 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1300 INT nIndex;
1302 if ((wParam) && (HIWORD(lParam) == 0)) {
1303 WCHAR szString[256];
1304 INT len;
1305 TRACE("adding string from resource!\n");
1307 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1308 szString, 256);
1310 TRACE("len=%d \"%s\"\n", len, debugstr_w(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 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1328 infoPtr->nNumStrings++;
1330 else {
1331 LPWSTR p = (LPWSTR)lParam;
1332 INT len;
1334 if (p == NULL)
1335 return -1;
1336 TRACE("adding string(s) from array!\n");
1337 nIndex = infoPtr->nNumStrings;
1338 while (*p) {
1339 len = lstrlenW (p);
1340 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1342 if (infoPtr->nNumStrings == 0) {
1343 infoPtr->strings =
1344 COMCTL32_Alloc (sizeof(LPWSTR));
1346 else {
1347 LPWSTR *oldStrings = infoPtr->strings;
1348 infoPtr->strings =
1349 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1350 memcpy (&infoPtr->strings[0], &oldStrings[0],
1351 sizeof(LPWSTR) * infoPtr->nNumStrings);
1352 COMCTL32_Free (oldStrings);
1355 infoPtr->strings[infoPtr->nNumStrings] =
1356 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1357 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1358 infoPtr->nNumStrings++;
1360 p += (len+1);
1364 return nIndex;
1368 static LRESULT
1369 TOOLBAR_AutoSize (HWND hwnd)
1371 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1372 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1373 RECT parent_rect;
1374 RECT window_rect;
1375 HWND parent;
1376 INT x, y;
1377 INT cx, cy;
1378 UINT uPosFlags = 0;
1380 TRACE("resize forced!\n");
1382 parent = GetParent (hwnd);
1383 GetClientRect(parent, &parent_rect);
1385 x = parent_rect.left;
1386 y = parent_rect.top;
1388 if (dwStyle & CCS_NORESIZE) {
1389 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1390 cx = 0;
1391 cy = 0;
1393 else {
1394 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1395 TOOLBAR_CalcToolbar (hwnd);
1396 InvalidateRect( hwnd, NULL, TRUE );
1397 cy = infoPtr->nHeight;
1398 cx = infoPtr->nWidth;
1400 if (dwStyle & CCS_NOMOVEY) {
1401 GetWindowRect(hwnd, &window_rect);
1402 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1403 y = window_rect.top;
1407 if (dwStyle & CCS_NOPARENTALIGN)
1408 uPosFlags |= SWP_NOMOVE;
1410 if (!(dwStyle & CCS_NODIVIDER))
1411 cy += GetSystemMetrics(SM_CYEDGE);
1413 if (dwStyle & WS_BORDER)
1415 x = y = 1;
1416 cy += GetSystemMetrics(SM_CYEDGE);
1417 cx += GetSystemMetrics(SM_CYEDGE);
1420 infoPtr->bAutoSize = TRUE;
1421 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1422 cx, cy, uPosFlags);
1423 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1424 * the setwindowpos calls */
1425 infoPtr->bAutoSize = FALSE;
1427 return 0;
1431 static LRESULT
1432 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1434 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1436 return infoPtr->nNumButtons;
1440 static LRESULT
1441 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1443 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1445 if (infoPtr == NULL) {
1446 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1447 ERR("infoPtr == NULL!\n");
1448 return 0;
1451 infoPtr->dwStructSize = (DWORD)wParam;
1453 return 0;
1457 static LRESULT
1458 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1460 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1461 TBUTTON_INFO *btnPtr;
1462 INT nIndex;
1464 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1465 if (nIndex == -1)
1466 return FALSE;
1468 btnPtr = &infoPtr->buttons[nIndex];
1469 btnPtr->iBitmap = LOWORD(lParam);
1471 RedrawWindow(hwnd,&btnPtr->rect,NULL,RDW_ERASE|RDW_INVALIDATE);
1473 return TRUE;
1477 static LRESULT
1478 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1480 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1481 TBUTTON_INFO *btnPtr;
1482 INT nIndex;
1483 INT nOldIndex = -1;
1484 BOOL bChecked = FALSE;
1486 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1487 if (nIndex == -1)
1488 return FALSE;
1490 btnPtr = &infoPtr->buttons[nIndex];
1492 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1493 return FALSE;
1495 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1497 if (LOWORD(lParam) == FALSE)
1498 btnPtr->fsState &= ~TBSTATE_CHECKED;
1499 else {
1500 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1501 nOldIndex =
1502 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1503 if (nOldIndex == nIndex)
1504 return 0;
1505 if (nOldIndex != -1)
1506 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1508 btnPtr->fsState |= TBSTATE_CHECKED;
1511 if( bChecked != LOWORD(lParam) )
1513 if (nOldIndex != -1)
1514 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,NULL,
1515 RDW_ERASE|RDW_INVALIDATE);
1516 RedrawWindow(hwnd,&btnPtr->rect,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1519 /* FIXME: Send a WM_NOTIFY?? */
1521 return TRUE;
1525 static LRESULT
1526 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1528 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1530 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1534 static LRESULT
1535 TOOLBAR_Customize (HWND hwnd)
1537 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1538 LRESULT ret;
1539 LPCVOID template;
1540 HRSRC hRes;
1541 NMHDR nmhdr;
1543 /* send TBN_BEGINADJUST notification */
1544 nmhdr.hwndFrom = hwnd;
1545 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1546 nmhdr.code = TBN_BEGINADJUST;
1548 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1549 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1551 if (!(hRes = FindResourceA (COMCTL32_hModule,
1552 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1553 RT_DIALOGA)))
1554 return FALSE;
1556 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1557 return FALSE;
1559 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1560 (LPDLGTEMPLATEA)template,
1561 hwnd,
1562 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1563 (LPARAM)infoPtr);
1565 /* send TBN_ENDADJUST notification */
1566 nmhdr.code = TBN_ENDADJUST;
1568 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1569 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1571 return ret;
1575 static LRESULT
1576 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1578 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1579 INT nIndex = (INT)wParam;
1581 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1582 return FALSE;
1584 if ((infoPtr->hwndToolTip) &&
1585 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1586 TTTOOLINFOA ti;
1588 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1589 ti.cbSize = sizeof (TTTOOLINFOA);
1590 ti.hwnd = hwnd;
1591 ti.uId = infoPtr->buttons[nIndex].idCommand;
1593 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1596 if (infoPtr->nNumButtons == 1) {
1597 TRACE(" simple delete!\n");
1598 COMCTL32_Free (infoPtr->buttons);
1599 infoPtr->buttons = NULL;
1600 infoPtr->nNumButtons = 0;
1602 else {
1603 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1604 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1606 infoPtr->nNumButtons--;
1607 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1608 if (nIndex > 0) {
1609 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1610 nIndex * sizeof(TBUTTON_INFO));
1613 if (nIndex < infoPtr->nNumButtons) {
1614 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1615 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1618 COMCTL32_Free (oldButtons);
1621 TOOLBAR_CalcToolbar (hwnd);
1623 InvalidateRect (hwnd, NULL, TRUE);
1625 return TRUE;
1629 static LRESULT
1630 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1632 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1633 TBUTTON_INFO *btnPtr;
1634 INT nIndex;
1635 DWORD bState;
1637 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1638 if (nIndex == -1)
1639 return FALSE;
1641 btnPtr = &infoPtr->buttons[nIndex];
1643 bState = btnPtr->fsState & TBSTATE_ENABLED;
1645 /* update the toolbar button state */
1646 if(LOWORD(lParam) == FALSE) {
1647 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1648 } else {
1649 btnPtr->fsState |= TBSTATE_ENABLED;
1652 /* redraw the button only if the state of the button changed */
1653 if(bState != (btnPtr->fsState & TBSTATE_ENABLED)) {
1654 RedrawWindow(hwnd,&btnPtr->rect,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1657 return TRUE;
1661 static inline LRESULT
1662 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1664 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1666 return infoPtr->bAnchor;
1670 static LRESULT
1671 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1673 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1674 INT nIndex;
1676 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1677 if (nIndex == -1)
1678 return -1;
1680 return infoPtr->buttons[nIndex].iBitmap;
1684 static inline LRESULT
1685 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1687 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1691 static LRESULT
1692 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1694 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1695 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1696 INT nIndex = (INT)wParam;
1697 TBUTTON_INFO *btnPtr;
1699 if (infoPtr == NULL)
1700 return FALSE;
1702 if (lpTbb == NULL)
1703 return FALSE;
1705 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1706 return FALSE;
1708 btnPtr = &infoPtr->buttons[nIndex];
1709 lpTbb->iBitmap = btnPtr->iBitmap;
1710 lpTbb->idCommand = btnPtr->idCommand;
1711 lpTbb->fsState = btnPtr->fsState;
1712 lpTbb->fsStyle = btnPtr->fsStyle;
1713 lpTbb->dwData = btnPtr->dwData;
1714 lpTbb->iString = btnPtr->iString;
1716 return TRUE;
1720 static LRESULT
1721 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1723 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1724 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1725 TBUTTON_INFO *btnPtr;
1726 INT nIndex;
1728 if (infoPtr == NULL)
1729 return -1;
1730 if (lpTbInfo == NULL)
1731 return -1;
1732 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1733 return -1;
1735 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1736 if (nIndex == -1)
1737 return -1;
1739 btnPtr = &infoPtr->buttons[nIndex];
1741 if (lpTbInfo->dwMask & TBIF_COMMAND)
1742 lpTbInfo->idCommand = btnPtr->idCommand;
1743 if (lpTbInfo->dwMask & TBIF_IMAGE)
1744 lpTbInfo->iImage = btnPtr->iBitmap;
1745 if (lpTbInfo->dwMask & TBIF_LPARAM)
1746 lpTbInfo->lParam = btnPtr->dwData;
1747 if (lpTbInfo->dwMask & TBIF_SIZE)
1748 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1749 if (lpTbInfo->dwMask & TBIF_STATE)
1750 lpTbInfo->fsState = btnPtr->fsState;
1751 if (lpTbInfo->dwMask & TBIF_STYLE)
1752 lpTbInfo->fsStyle = btnPtr->fsStyle;
1753 if (lpTbInfo->dwMask & TBIF_TEXT) {
1754 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1755 lstrcpynWtoA (lpTbInfo->pszText,
1756 (LPWSTR)infoPtr->strings[btnPtr->iString],
1757 lpTbInfo->cchText);
1760 return nIndex;
1764 static LRESULT
1765 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1767 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1768 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
1769 TBUTTON_INFO *btnPtr;
1770 INT nIndex;
1772 if (infoPtr == NULL)
1773 return -1;
1774 if (lpTbInfo == NULL)
1775 return -1;
1776 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
1777 return -1;
1779 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1780 if (nIndex == -1)
1781 return -1;
1783 btnPtr = &infoPtr->buttons[nIndex];
1785 if (lpTbInfo->dwMask & TBIF_COMMAND)
1786 lpTbInfo->idCommand = btnPtr->idCommand;
1787 if (lpTbInfo->dwMask & TBIF_IMAGE)
1788 lpTbInfo->iImage = btnPtr->iBitmap;
1789 if (lpTbInfo->dwMask & TBIF_LPARAM)
1790 lpTbInfo->lParam = btnPtr->dwData;
1791 if (lpTbInfo->dwMask & TBIF_SIZE)
1792 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1793 if (lpTbInfo->dwMask & TBIF_STATE)
1794 lpTbInfo->fsState = btnPtr->fsState;
1795 if (lpTbInfo->dwMask & TBIF_STYLE)
1796 lpTbInfo->fsStyle = btnPtr->fsStyle;
1797 if (lpTbInfo->dwMask & TBIF_TEXT) {
1798 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1799 lstrcpynW (lpTbInfo->pszText,
1800 (LPWSTR)infoPtr->strings[btnPtr->iString],
1801 lpTbInfo->cchText);
1804 return nIndex;
1808 static LRESULT
1809 TOOLBAR_GetButtonSize (HWND hwnd)
1811 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1813 return MAKELONG((WORD)infoPtr->nButtonWidth,
1814 (WORD)infoPtr->nButtonHeight);
1818 static LRESULT
1819 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1821 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1822 INT nIndex, nStringIndex;
1824 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1825 if (nIndex == -1)
1826 return -1;
1828 nStringIndex = infoPtr->buttons[nIndex].iString;
1830 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1832 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1833 return -1;
1835 if (lParam == 0)
1836 return -1;
1838 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1840 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1844 static LRESULT
1845 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1847 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1848 INT nIndex, nStringIndex;
1850 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1851 if (nIndex == -1)
1852 return -1;
1854 nStringIndex = infoPtr->buttons[nIndex].iString;
1856 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1858 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1859 return -1;
1861 if (lParam == 0)
1862 return -1;
1864 lstrcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1866 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1870 /* << TOOLBAR_GetColorScheme >> */
1873 static LRESULT
1874 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1876 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1878 return (LRESULT)infoPtr->himlDis;
1882 inline static LRESULT
1883 TOOLBAR_GetExtendedStyle (HWND hwnd)
1885 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1887 return infoPtr->dwExStyle;
1891 static LRESULT
1892 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1894 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1896 return (LRESULT)infoPtr->himlHot;
1900 static LRESULT
1901 TOOLBAR_GetHotItem (HWND hwnd)
1903 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1905 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
1906 return -1;
1908 if (infoPtr->nHotItem < 0)
1909 return -1;
1911 return (LRESULT)infoPtr->nHotItem;
1915 static LRESULT
1916 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1918 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1920 return (LRESULT)infoPtr->himlDef;
1924 /* << TOOLBAR_GetInsertMark >> */
1925 /* << TOOLBAR_GetInsertMarkColor >> */
1928 static LRESULT
1929 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1931 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1932 TBUTTON_INFO *btnPtr;
1933 LPRECT lpRect;
1934 INT nIndex;
1936 if (infoPtr == NULL)
1937 return FALSE;
1938 nIndex = (INT)wParam;
1939 btnPtr = &infoPtr->buttons[nIndex];
1940 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1941 return FALSE;
1942 lpRect = (LPRECT)lParam;
1943 if (lpRect == NULL)
1944 return FALSE;
1945 if (btnPtr->fsState & TBSTATE_HIDDEN)
1946 return FALSE;
1948 TOOLBAR_CalcToolbar( hwnd );
1950 lpRect->left = btnPtr->rect.left;
1951 lpRect->right = btnPtr->rect.right;
1952 lpRect->bottom = btnPtr->rect.bottom;
1953 lpRect->top = btnPtr->rect.top;
1955 return TRUE;
1959 static LRESULT
1960 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1962 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1963 LPSIZE lpSize = (LPSIZE)lParam;
1965 if (lpSize == NULL)
1966 return FALSE;
1968 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
1969 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
1971 TRACE("maximum size %d x %d\n",
1972 infoPtr->rcBound.right - infoPtr->rcBound.left,
1973 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
1975 return TRUE;
1979 /* << TOOLBAR_GetObject >> */
1980 /* << TOOLBAR_GetPadding >> */
1983 static LRESULT
1984 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1986 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1987 TBUTTON_INFO *btnPtr;
1988 LPRECT lpRect;
1989 INT nIndex;
1991 if (infoPtr == NULL)
1992 return FALSE;
1993 nIndex = (INT)wParam;
1994 btnPtr = &infoPtr->buttons[nIndex];
1995 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1996 return FALSE;
1997 lpRect = (LPRECT)lParam;
1998 if (lpRect == NULL)
1999 return FALSE;
2001 lpRect->left = btnPtr->rect.left;
2002 lpRect->right = btnPtr->rect.right;
2003 lpRect->bottom = btnPtr->rect.bottom;
2004 lpRect->top = btnPtr->rect.top;
2006 return TRUE;
2010 static LRESULT
2011 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2013 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2015 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2016 return infoPtr->nRows;
2017 else
2018 return 1;
2022 static LRESULT
2023 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2025 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2026 INT nIndex;
2028 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2029 if (nIndex == -1)
2030 return -1;
2032 return infoPtr->buttons[nIndex].fsState;
2036 static LRESULT
2037 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2039 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2040 INT nIndex;
2042 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2043 if (nIndex == -1)
2044 return -1;
2046 return infoPtr->buttons[nIndex].fsStyle;
2050 static LRESULT
2051 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2053 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2055 if (infoPtr == NULL)
2056 return 0;
2058 return infoPtr->nMaxTextRows;
2062 static LRESULT
2063 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2065 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2067 if (infoPtr == NULL)
2068 return 0;
2069 return infoPtr->hwndToolTip;
2073 static LRESULT
2074 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2076 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2078 TRACE("%s hwnd=0x%x stub!\n",
2079 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2081 return infoPtr->bUnicode;
2085 inline static LRESULT
2086 TOOLBAR_GetVersion (HWND hwnd)
2088 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2089 return infoPtr->iVersion;
2093 static LRESULT
2094 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2096 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2097 TBUTTON_INFO *btnPtr;
2098 INT nIndex;
2100 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2101 if (nIndex == -1)
2102 return FALSE;
2104 btnPtr = &infoPtr->buttons[nIndex];
2105 if (LOWORD(lParam) == FALSE)
2106 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2107 else
2108 btnPtr->fsState |= TBSTATE_HIDDEN;
2110 TOOLBAR_CalcToolbar (hwnd);
2112 InvalidateRect (hwnd, NULL, TRUE);
2114 return TRUE;
2118 inline static LRESULT
2119 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2121 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2125 static LRESULT
2126 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2128 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2129 TBUTTON_INFO *btnPtr;
2130 INT nIndex;
2132 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2133 if (nIndex == -1)
2134 return FALSE;
2136 btnPtr = &infoPtr->buttons[nIndex];
2137 if (LOWORD(lParam) == FALSE)
2138 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2139 else
2140 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2142 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2143 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2145 return TRUE;
2149 static LRESULT
2150 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2152 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2153 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2154 INT nIndex = (INT)wParam;
2155 TBUTTON_INFO *oldButtons;
2157 if (lpTbb == NULL)
2158 return FALSE;
2160 if (nIndex == -1) {
2161 /* EPP: this seems to be an undocumented call (from my IE4)
2162 * I assume in that case that:
2163 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2164 * - index of insertion is at the end of existing buttons
2165 * I only see this happen with nIndex == -1, but it could have a special
2166 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2168 int len = lstrlenA((char*)lpTbb->iString) + 2;
2169 LPSTR ptr = COMCTL32_Alloc(len);
2171 nIndex = infoPtr->nNumButtons;
2172 strcpy(ptr, (char*)lpTbb->iString);
2173 ptr[len - 1] = 0; /* ended by two '\0' */
2174 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2175 COMCTL32_Free(ptr);
2177 } else if (nIndex < 0)
2178 return FALSE;
2180 TRACE("inserting button index=%d\n", nIndex);
2181 if (nIndex > infoPtr->nNumButtons) {
2182 nIndex = infoPtr->nNumButtons;
2183 TRACE("adjust index=%d\n", nIndex);
2186 oldButtons = infoPtr->buttons;
2187 infoPtr->nNumButtons++;
2188 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2189 /* pre insert copy */
2190 if (nIndex > 0) {
2191 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2192 nIndex * sizeof(TBUTTON_INFO));
2195 /* insert new button */
2196 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2197 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2198 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2199 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2200 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2201 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2203 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2204 TTTOOLINFOA ti;
2206 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2207 ti.cbSize = sizeof (TTTOOLINFOA);
2208 ti.hwnd = hwnd;
2209 ti.uId = lpTbb->idCommand;
2210 ti.hinst = 0;
2211 ti.lpszText = LPSTR_TEXTCALLBACKA;
2213 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2214 0, (LPARAM)&ti);
2217 /* post insert copy */
2218 if (nIndex < infoPtr->nNumButtons - 1) {
2219 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2220 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2223 COMCTL32_Free (oldButtons);
2225 TOOLBAR_CalcToolbar (hwnd);
2227 InvalidateRect (hwnd, NULL, FALSE);
2229 return TRUE;
2233 static LRESULT
2234 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2236 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2237 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2238 INT nIndex = (INT)wParam;
2239 TBUTTON_INFO *oldButtons;
2241 if (lpTbb == NULL)
2242 return FALSE;
2243 if (nIndex < 0)
2244 return FALSE;
2246 TRACE("inserting button index=%d\n", nIndex);
2247 if (nIndex > infoPtr->nNumButtons) {
2248 nIndex = infoPtr->nNumButtons;
2249 TRACE("adjust index=%d\n", nIndex);
2252 oldButtons = infoPtr->buttons;
2253 infoPtr->nNumButtons++;
2254 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2255 /* pre insert copy */
2256 if (nIndex > 0) {
2257 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2258 nIndex * sizeof(TBUTTON_INFO));
2261 /* insert new button */
2262 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2263 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2264 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2265 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2266 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2267 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2269 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2270 TTTOOLINFOW ti;
2272 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2273 ti.cbSize = sizeof (TTTOOLINFOW);
2274 ti.hwnd = hwnd;
2275 ti.uId = lpTbb->idCommand;
2276 ti.hinst = 0;
2277 ti.lpszText = LPSTR_TEXTCALLBACKW;
2279 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2280 0, (LPARAM)&ti);
2283 /* post insert copy */
2284 if (nIndex < infoPtr->nNumButtons - 1) {
2285 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2286 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2289 COMCTL32_Free (oldButtons);
2291 TOOLBAR_CalcToolbar (hwnd);
2293 InvalidateRect (hwnd, NULL, FALSE);
2295 return TRUE;
2299 /* << TOOLBAR_InsertMarkHitTest >> */
2302 static LRESULT
2303 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2305 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2306 INT nIndex;
2308 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2309 if (nIndex == -1)
2310 return FALSE;
2312 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2316 static LRESULT
2317 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2319 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2320 INT nIndex;
2322 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2323 if (nIndex == -1)
2324 return FALSE;
2326 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2330 static LRESULT
2331 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2333 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2334 INT nIndex;
2336 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2337 if (nIndex == -1)
2338 return FALSE;
2340 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2344 static LRESULT
2345 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2347 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2348 INT nIndex;
2350 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2351 if (nIndex == -1)
2352 return FALSE;
2354 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2358 static LRESULT
2359 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2361 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2362 INT nIndex;
2364 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2365 if (nIndex == -1)
2366 return FALSE;
2368 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2372 static LRESULT
2373 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2375 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2376 INT nIndex;
2378 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2379 if (nIndex == -1)
2380 return FALSE;
2382 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2386 /* << TOOLBAR_LoadImages >> */
2387 /* << TOOLBAR_MapAccelerator >> */
2388 /* << TOOLBAR_MarkButton >> */
2389 /* << TOOLBAR_MoveButton >> */
2392 static LRESULT
2393 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2395 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2396 TBUTTON_INFO *btnPtr;
2397 INT nIndex;
2399 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2400 if (nIndex == -1)
2401 return FALSE;
2403 btnPtr = &infoPtr->buttons[nIndex];
2404 if (LOWORD(lParam) == FALSE)
2405 btnPtr->fsState &= ~TBSTATE_PRESSED;
2406 else
2407 btnPtr->fsState |= TBSTATE_PRESSED;
2409 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2410 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2412 return TRUE;
2416 /* << TOOLBAR_ReplaceBitmap >> */
2419 static LRESULT
2420 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2422 #if 0
2423 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2424 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2426 if (lpSave == NULL) return 0;
2428 if ((BOOL)wParam) {
2429 /* save toolbar information */
2430 FIXME("save to \"%s\" \"%s\"\n",
2431 lpSave->pszSubKey, lpSave->pszValueName);
2435 else {
2436 /* restore toolbar information */
2438 FIXME("restore from \"%s\" \"%s\"\n",
2439 lpSave->pszSubKey, lpSave->pszValueName);
2443 #endif
2445 return 0;
2449 static LRESULT
2450 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2452 #if 0
2453 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2454 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2456 if (lpSave == NULL)
2457 return 0;
2459 if ((BOOL)wParam) {
2460 /* save toolbar information */
2461 FIXME("save to \"%s\" \"%s\"\n",
2462 lpSave->pszSubKey, lpSave->pszValueName);
2466 else {
2467 /* restore toolbar information */
2469 FIXME("restore from \"%s\" \"%s\"\n",
2470 lpSave->pszSubKey, lpSave->pszValueName);
2474 #endif
2476 return 0;
2480 static LRESULT
2481 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2483 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2484 BOOL bOldAnchor = infoPtr->bAnchor;
2486 infoPtr->bAnchor = (BOOL)wParam;
2488 return (LRESULT)bOldAnchor;
2492 static LRESULT
2493 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2495 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2497 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2498 return FALSE;
2500 /* Bitmap size can only be set before adding any button to the toolbar
2501 according to the documentation. */
2502 if( infoPtr->nNumButtons != 0 )
2503 return FALSE;
2505 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2506 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2508 return TRUE;
2512 static LRESULT
2513 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2515 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2516 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2517 TBUTTON_INFO *btnPtr;
2518 INT nIndex;
2520 if (lptbbi == NULL)
2521 return FALSE;
2522 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2523 return FALSE;
2525 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2526 if (nIndex == -1)
2527 return FALSE;
2529 btnPtr = &infoPtr->buttons[nIndex];
2530 if (lptbbi->dwMask & TBIF_COMMAND)
2531 btnPtr->idCommand = lptbbi->idCommand;
2532 if (lptbbi->dwMask & TBIF_IMAGE)
2533 btnPtr->iBitmap = lptbbi->iImage;
2534 if (lptbbi->dwMask & TBIF_LPARAM)
2535 btnPtr->dwData = lptbbi->lParam;
2536 /* if (lptbbi->dwMask & TBIF_SIZE) */
2537 /* btnPtr->cx = lptbbi->cx; */
2538 if (lptbbi->dwMask & TBIF_STATE)
2539 btnPtr->fsState = lptbbi->fsState;
2540 if (lptbbi->dwMask & TBIF_STYLE)
2541 btnPtr->fsStyle = lptbbi->fsStyle;
2543 if (lptbbi->dwMask & TBIF_TEXT) {
2544 if ((btnPtr->iString >= 0) ||
2545 (btnPtr->iString < infoPtr->nNumStrings)) {
2546 TRACE("Ooooooch\n");
2547 #if 0
2548 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2549 INT len = lstrlenA (lptbbi->pszText);
2550 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2551 #endif
2553 /* this is the ultimate sollution */
2554 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2558 return TRUE;
2562 static LRESULT
2563 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2565 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2566 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2567 TBUTTON_INFO *btnPtr;
2568 INT nIndex;
2570 if (lptbbi == NULL)
2571 return FALSE;
2572 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2573 return FALSE;
2575 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2576 if (nIndex == -1)
2577 return FALSE;
2579 btnPtr = &infoPtr->buttons[nIndex];
2580 if (lptbbi->dwMask & TBIF_COMMAND)
2581 btnPtr->idCommand = lptbbi->idCommand;
2582 if (lptbbi->dwMask & TBIF_IMAGE)
2583 btnPtr->iBitmap = lptbbi->iImage;
2584 if (lptbbi->dwMask & TBIF_LPARAM)
2585 btnPtr->dwData = lptbbi->lParam;
2586 /* if (lptbbi->dwMask & TBIF_SIZE) */
2587 /* btnPtr->cx = lptbbi->cx; */
2588 if (lptbbi->dwMask & TBIF_STATE)
2589 btnPtr->fsState = lptbbi->fsState;
2590 if (lptbbi->dwMask & TBIF_STYLE)
2591 btnPtr->fsStyle = lptbbi->fsStyle;
2593 if (lptbbi->dwMask & TBIF_TEXT) {
2594 if ((btnPtr->iString >= 0) ||
2595 (btnPtr->iString < infoPtr->nNumStrings)) {
2596 #if 0
2597 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2598 INT len = lstrlenW (lptbbi->pszText);
2599 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2600 #endif
2602 /* this is the ultimate sollution */
2603 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2607 return TRUE;
2611 static LRESULT
2612 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2614 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2616 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2617 return FALSE;
2619 /* Button size can only be set before adding any button to the toolbar
2620 according to the documentation. */
2621 if( infoPtr->nNumButtons != 0 )
2622 return FALSE;
2624 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2625 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2626 return TRUE;
2630 static LRESULT
2631 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2633 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2635 if (infoPtr == NULL)
2636 return FALSE;
2638 infoPtr->cxMin = (INT)LOWORD(lParam);
2639 infoPtr->cxMax = (INT)HIWORD(lParam);
2641 return TRUE;
2645 static LRESULT
2646 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2648 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2649 INT nIndex = (INT)wParam;
2651 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2652 return FALSE;
2654 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2656 if (infoPtr->hwndToolTip) {
2658 FIXME("change tool tip!\n");
2662 return TRUE;
2666 /* << TOOLBAR_SetColorScheme >> */
2669 static LRESULT
2670 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2673 HIMAGELIST himlTemp;
2676 himlTemp = infoPtr->himlDis;
2677 infoPtr->himlDis = (HIMAGELIST)lParam;
2679 /* FIXME: redraw ? */
2681 return (LRESULT)himlTemp;
2685 static LRESULT
2686 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2688 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2689 DWORD dwTemp;
2691 dwTemp = infoPtr->dwDTFlags;
2692 infoPtr->dwDTFlags =
2693 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2695 return (LRESULT)dwTemp;
2699 static LRESULT
2700 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2702 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2703 DWORD dwTemp;
2705 dwTemp = infoPtr->dwExStyle;
2706 infoPtr->dwExStyle = (DWORD)lParam;
2708 return (LRESULT)dwTemp;
2712 static LRESULT
2713 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2715 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2716 HIMAGELIST himlTemp;
2718 himlTemp = infoPtr->himlHot;
2719 infoPtr->himlHot = (HIMAGELIST)lParam;
2721 /* FIXME: redraw ? */
2723 return (LRESULT)himlTemp;
2727 static LRESULT
2728 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
2730 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2731 INT nOldHotItem = infoPtr->nHotItem;
2733 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
2735 infoPtr->nHotItem = (INT)wParam;
2737 /* FIXME: What else must be done ??? */
2741 if (nOldHotItem < 0)
2742 return -1;
2744 return (LRESULT)nOldHotItem;
2748 static LRESULT
2749 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2751 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2752 HIMAGELIST himlTemp;
2754 himlTemp = infoPtr->himlDef;
2755 infoPtr->himlDef = (HIMAGELIST)lParam;
2757 /* FIXME: redraw ? */
2759 return (LRESULT)himlTemp;
2763 static LRESULT
2764 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2766 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2768 infoPtr->nIndent = (INT)wParam;
2770 TOOLBAR_CalcToolbar (hwnd);
2772 InvalidateRect(hwnd, NULL, FALSE);
2774 return TRUE;
2778 /* << TOOLBAR_SetInsertMark >> */
2781 static LRESULT
2782 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2784 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2786 infoPtr->clrInsertMark = (COLORREF)lParam;
2788 /* FIXME : redraw ??*/
2790 return 0;
2794 static LRESULT
2795 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2797 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2799 if (infoPtr == NULL)
2800 return FALSE;
2802 infoPtr->nMaxTextRows = (INT)wParam;
2804 return TRUE;
2808 /* << TOOLBAR_SetPadding >> */
2811 static LRESULT
2812 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2814 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2815 HWND hwndOldNotify;
2817 if (infoPtr == NULL)
2818 return 0;
2819 hwndOldNotify = infoPtr->hwndNotify;
2820 infoPtr->hwndNotify = (HWND)wParam;
2822 return hwndOldNotify;
2826 static LRESULT
2827 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2829 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2830 LPRECT lprc = (LPRECT)lParam;
2832 if (LOWORD(wParam) > 1) {
2834 FIXME("multiple rows not supported!\n");
2838 /* recalculate toolbar */
2839 TOOLBAR_CalcToolbar (hwnd);
2841 /* return bounding rectangle */
2842 if (lprc) {
2843 lprc->left = infoPtr->rcBound.left;
2844 lprc->right = infoPtr->rcBound.right;
2845 lprc->top = infoPtr->rcBound.top;
2846 lprc->bottom = infoPtr->rcBound.bottom;
2849 /* repaint toolbar */
2850 InvalidateRect(hwnd, NULL, FALSE);
2852 return 0;
2856 static LRESULT
2857 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2859 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2860 TBUTTON_INFO *btnPtr;
2861 INT nIndex;
2863 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2864 if (nIndex == -1)
2865 return FALSE;
2867 btnPtr = &infoPtr->buttons[nIndex];
2868 btnPtr->fsState = LOWORD(lParam);
2870 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2871 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2873 return TRUE;
2877 static LRESULT
2878 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2880 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2881 TBUTTON_INFO *btnPtr;
2882 INT nIndex;
2884 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2885 if (nIndex == -1)
2886 return FALSE;
2888 btnPtr = &infoPtr->buttons[nIndex];
2889 btnPtr->fsStyle = LOWORD(lParam);
2891 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2892 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2894 if (infoPtr->hwndToolTip) {
2896 FIXME("change tool tip!\n");
2900 return TRUE;
2904 inline static LRESULT
2905 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2907 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2909 if (infoPtr == NULL)
2910 return 0;
2911 infoPtr->hwndToolTip = (HWND)wParam;
2912 return 0;
2916 static LRESULT
2917 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2919 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2920 BOOL bTemp;
2922 TRACE("%s hwnd=0x%04x stub!\n",
2923 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
2925 bTemp = infoPtr->bUnicode;
2926 infoPtr->bUnicode = (BOOL)wParam;
2928 return bTemp;
2932 static LRESULT
2933 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
2935 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2936 INT iOldVersion = infoPtr->iVersion;
2938 infoPtr->iVersion = iVersion;
2940 return iOldVersion;
2944 static LRESULT
2945 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
2947 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2948 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2949 LOGFONTA logFont;
2951 /* initialize info structure */
2952 infoPtr->nButtonHeight = 22;
2953 infoPtr->nButtonWidth = 24;
2954 infoPtr->nBitmapHeight = 15;
2955 infoPtr->nBitmapWidth = 16;
2957 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
2958 infoPtr->nRows = 1;
2959 infoPtr->nMaxTextRows = 1;
2960 infoPtr->cxMin = -1;
2961 infoPtr->cxMax = -1;
2963 infoPtr->bCaptured = FALSE;
2964 infoPtr->bUnicode = IsWindowUnicode (hwnd);
2965 infoPtr->nButtonDown = -1;
2966 infoPtr->nOldHit = -1;
2967 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
2968 infoPtr->hwndNotify = GetParent (hwnd);
2969 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
2970 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
2971 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
2972 infoPtr->iVersion = 0;
2974 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
2975 infoPtr->hFont = CreateFontIndirectA (&logFont);
2977 if (dwStyle & TBSTYLE_TOOLTIPS) {
2978 /* Create tooltip control */
2979 infoPtr->hwndToolTip =
2980 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
2981 CW_USEDEFAULT, CW_USEDEFAULT,
2982 CW_USEDEFAULT, CW_USEDEFAULT,
2983 hwnd, 0, 0, 0);
2985 /* Send NM_TOOLTIPSCREATED notification */
2986 if (infoPtr->hwndToolTip) {
2987 NMTOOLTIPSCREATED nmttc;
2989 nmttc.hdr.hwndFrom = hwnd;
2990 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
2991 nmttc.hdr.code = NM_TOOLTIPSCREATED;
2992 nmttc.hwndToolTips = infoPtr->hwndToolTip;
2994 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
2995 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
2999 return 0;
3003 static LRESULT
3004 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3006 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3008 /* delete tooltip control */
3009 if (infoPtr->hwndToolTip)
3010 DestroyWindow (infoPtr->hwndToolTip);
3012 /* delete button data */
3013 if (infoPtr->buttons)
3014 COMCTL32_Free (infoPtr->buttons);
3016 /* delete strings */
3017 if (infoPtr->strings) {
3018 INT i;
3019 for (i = 0; i < infoPtr->nNumStrings; i++)
3020 if (infoPtr->strings[i])
3021 COMCTL32_Free (infoPtr->strings[i]);
3023 COMCTL32_Free (infoPtr->strings);
3026 /* destroy internal image list */
3027 if (infoPtr->himlInt)
3028 ImageList_Destroy (infoPtr->himlInt);
3030 /* delete default font */
3031 if (infoPtr->hFont)
3032 DeleteObject (infoPtr->hFont);
3034 /* free toolbar info data */
3035 COMCTL32_Free (infoPtr);
3036 SetWindowLongA (hwnd, 0, 0);
3038 return 0;
3042 static LRESULT
3043 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3045 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3047 if (infoPtr->bTransparent)
3048 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3050 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3054 static LRESULT
3055 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3057 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3059 return infoPtr->hFont;
3063 static LRESULT
3064 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3066 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3067 TBUTTON_INFO *btnPtr;
3068 POINT pt;
3069 INT nHit;
3071 pt.x = (INT)LOWORD(lParam);
3072 pt.y = (INT)HIWORD(lParam);
3073 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3075 if (nHit >= 0) {
3076 btnPtr = &infoPtr->buttons[nHit];
3077 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3078 return 0;
3079 SetCapture (hwnd);
3080 infoPtr->bCaptured = TRUE;
3081 infoPtr->nButtonDown = nHit;
3083 btnPtr->fsState |= TBSTATE_PRESSED;
3085 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3086 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3088 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3089 TOOLBAR_Customize (hwnd);
3091 return 0;
3095 static LRESULT
3096 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3098 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3099 TBUTTON_INFO *btnPtr;
3100 POINT pt;
3101 INT nHit;
3103 if (infoPtr->hwndToolTip)
3104 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3105 WM_LBUTTONDOWN, wParam, lParam);
3107 pt.x = (INT)LOWORD(lParam);
3108 pt.y = (INT)HIWORD(lParam);
3109 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3111 if (nHit >= 0) {
3112 btnPtr = &infoPtr->buttons[nHit];
3113 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3114 return 0;
3116 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
3118 NMTOOLBARA nmtb;
3120 nmtb.hdr.hwndFrom = hwnd;
3121 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3122 nmtb.hdr.code = TBN_DROPDOWN;
3123 nmtb.iItem = btnPtr->idCommand;
3125 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3126 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3129 SetCapture (hwnd);
3130 infoPtr->bCaptured = TRUE;
3131 infoPtr->nButtonDown = nHit;
3132 infoPtr->nOldHit = nHit;
3134 btnPtr->fsState |= TBSTATE_PRESSED;
3135 btnPtr->bHot = FALSE;
3137 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3138 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3141 return 0;
3144 static LRESULT
3145 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3147 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3148 TBUTTON_INFO *btnPtr;
3149 POINT pt;
3150 INT nHit;
3151 INT nOldIndex = -1;
3152 BOOL bSendMessage = TRUE;
3154 if (infoPtr->hwndToolTip)
3155 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3156 WM_LBUTTONUP, wParam, lParam);
3158 pt.x = (INT)LOWORD(lParam);
3159 pt.y = (INT)HIWORD(lParam);
3160 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3162 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3163 infoPtr->bCaptured = FALSE;
3164 ReleaseCapture ();
3165 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3166 btnPtr->fsState &= ~TBSTATE_PRESSED;
3168 if (nHit == infoPtr->nButtonDown) {
3169 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3170 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3171 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3172 infoPtr->nButtonDown);
3173 if (nOldIndex == infoPtr->nButtonDown)
3174 bSendMessage = FALSE;
3175 if ((nOldIndex != infoPtr->nButtonDown) &&
3176 (nOldIndex != -1))
3177 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3178 btnPtr->fsState |= TBSTATE_CHECKED;
3180 else {
3181 if (btnPtr->fsState & TBSTATE_CHECKED)
3182 btnPtr->fsState &= ~TBSTATE_CHECKED;
3183 else
3184 btnPtr->fsState |= TBSTATE_CHECKED;
3188 else
3189 bSendMessage = FALSE;
3191 if (nOldIndex != -1)
3192 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,NULL,
3193 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3194 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3195 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3197 if (bSendMessage) {
3198 SendMessageA (GetParent(hwnd), WM_COMMAND,
3199 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3201 // if ((GetWindowLongA(hwnd, GWL_STYLE) & TBSTYLE_DROPDOWN) ||
3202 // (btnPtr->fsStyle & 0x08/* BTNS_DROPDOWN */)) {
3204 * This appears to be an error. Instead of checking the style of the
3205 * button in question wine was checking the style of the toolbar
3206 * itself. This caused a number of strange behaviors. In my
3207 * invistigation i think the whole dropdown thing is still fairly
3208 * broken. but this helps fix some of the problems.
3211 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
3212 NMTOOLBARW nmtb;
3214 nmtb.hdr.hwndFrom = hwnd;
3215 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3216 nmtb.hdr.code = TBN_DROPDOWN;
3217 nmtb.iItem = nHit;
3218 /* nmtb.tbButton not used with TBN_DROPDOWN */
3219 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) {
3220 nmtb.pszText = infoPtr->strings[btnPtr->iString];
3221 nmtb.cchText = lstrlenW(nmtb.pszText);
3222 } else {
3223 nmtb.pszText = NULL;
3224 nmtb.cchText = 0;
3226 nmtb.rcButton = btnPtr->rect;
3228 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
3229 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3232 infoPtr->nButtonDown = -1;
3233 infoPtr->nOldHit = -1;
3236 return 0;
3239 static LRESULT
3240 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3242 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3243 TBUTTON_INFO *hotBtnPtr;
3245 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3247 /* Redraw the button if the last button we were over is the hot button and it
3248 is enabled */
3249 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3251 hotBtnPtr->bHot = FALSE;
3253 InvalidateRect (hwnd, &hotBtnPtr->rect, TRUE);
3256 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3257 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3259 return TRUE;
3262 static LRESULT
3263 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3265 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3266 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3267 POINT pt;
3268 INT nHit;
3269 TRACKMOUSEEVENT trackinfo;
3271 /* fill in the TRACKMOUSEEVENT struct */
3272 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3273 trackinfo.dwFlags = TME_QUERY;
3274 trackinfo.hwndTrack = hwnd;
3275 trackinfo.dwHoverTime = HOVER_DEFAULT;
3277 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3278 _TrackMouseEvent(&trackinfo);
3280 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3281 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3282 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3284 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3285 /* and can properly deactivate the hot toolbar button */
3286 _TrackMouseEvent(&trackinfo);
3289 if (infoPtr->hwndToolTip)
3290 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3291 WM_MOUSEMOVE, wParam, lParam);
3293 pt.x = (INT)LOWORD(lParam);
3294 pt.y = (INT)HIWORD(lParam);
3296 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3298 if (infoPtr->nOldHit != nHit)
3300 /* Remove the effect of an old hot button if the button was enabled and was
3301 drawn with the hot button effect */
3302 if(infoPtr->nOldHit == infoPtr->nHotItem &&
3303 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3305 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3306 oldBtnPtr->bHot = FALSE;
3308 InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
3311 /* It's not a separator or in nowhere. It's a hot button. */
3312 if (nHit >= 0)
3314 btnPtr = &infoPtr->buttons[nHit];
3315 btnPtr->bHot = TRUE;
3317 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3318 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3320 infoPtr->nHotItem = nHit;
3323 if (infoPtr->bCaptured) {
3324 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3325 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3326 btnPtr->fsState &= ~TBSTATE_PRESSED;
3327 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3328 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3330 else if (nHit == infoPtr->nButtonDown) {
3331 btnPtr->fsState |= TBSTATE_PRESSED;
3332 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3333 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3336 infoPtr->nOldHit = nHit;
3338 return 0;
3342 inline static LRESULT
3343 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3345 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3346 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3347 /* else */
3348 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3352 inline static LRESULT
3353 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3355 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3356 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3358 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3362 static LRESULT
3363 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3365 TOOLBAR_INFO *infoPtr;
3367 /* allocate memory for info structure */
3368 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3369 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3371 /* paranoid!! */
3372 infoPtr->dwStructSize = sizeof(TBBUTTON);
3374 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3375 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3376 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3377 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3380 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3384 static LRESULT
3385 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3387 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3388 RECT rcWindow;
3389 HDC hdc;
3391 if (dwStyle & WS_MINIMIZE)
3392 return 0; /* Nothing to do */
3394 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3396 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3397 return 0;
3399 if (!(dwStyle & CCS_NODIVIDER))
3401 GetWindowRect (hwnd, &rcWindow);
3402 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3403 if( dwStyle & WS_BORDER )
3404 OffsetRect (&rcWindow, 1, 1);
3405 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3408 ReleaseDC( hwnd, hdc );
3410 return 0;
3414 inline static LRESULT
3415 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3417 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3418 LPNMHDR lpnmh = (LPNMHDR)lParam;
3420 TRACE("passing WM_NOTIFY!\n");
3422 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3423 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3425 #if 0
3426 if (lpnmh->code == TTN_GETDISPINFOA) {
3427 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3429 FIXME("retrieving ASCII string\n");
3432 else if (lpnmh->code == TTN_GETDISPINFOW) {
3433 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3435 FIXME("retrieving UNICODE string\n");
3438 #endif
3441 return 0;
3445 static LRESULT
3446 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3448 HDC hdc;
3449 PAINTSTRUCT ps;
3451 TOOLBAR_CalcToolbar( hwnd );
3452 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
3453 TOOLBAR_Refresh (hwnd, hdc);
3454 if (!wParam)
3455 EndPaint (hwnd, &ps);
3456 return 0;
3460 static LRESULT
3461 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3463 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3464 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3465 RECT parent_rect;
3466 RECT window_rect;
3467 HWND parent;
3468 INT x, y;
3469 INT cx, cy;
3470 INT flags;
3471 UINT uPosFlags = 0;
3473 /* Resize deadlock check */
3474 if (infoPtr->bAutoSize) {
3475 infoPtr->bAutoSize = FALSE;
3476 return 0;
3479 flags = (INT) wParam;
3481 /* FIXME for flags =
3482 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3485 TRACE("sizing toolbar!\n");
3487 if (flags == SIZE_RESTORED) {
3488 /* width and height don't apply */
3489 parent = GetParent (hwnd);
3490 GetClientRect(parent, &parent_rect);
3491 x = parent_rect.left;
3492 y = parent_rect.top;
3494 if (dwStyle & CCS_NORESIZE) {
3495 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3498 * this sets the working width of the toolbar, and
3499 * Calc Toolbar will not adjust it, only the height
3501 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3502 cy = infoPtr->nHeight;
3503 cx = infoPtr->nWidth;
3504 TOOLBAR_CalcToolbar (hwnd);
3505 infoPtr->nWidth = cx;
3506 infoPtr->nHeight = cy;
3508 else {
3509 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3510 TOOLBAR_CalcToolbar (hwnd);
3511 cy = infoPtr->nHeight;
3512 cx = infoPtr->nWidth;
3514 if (dwStyle & CCS_NOMOVEY) {
3515 GetWindowRect(hwnd, &window_rect);
3516 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3517 y = window_rect.top;
3521 if (dwStyle & CCS_NOPARENTALIGN) {
3522 uPosFlags |= SWP_NOMOVE;
3523 cy = infoPtr->nHeight;
3524 cx = infoPtr->nWidth;
3527 if (!(dwStyle & CCS_NODIVIDER))
3528 cy += GetSystemMetrics(SM_CYEDGE);
3530 if (dwStyle & WS_BORDER)
3532 x = y = 1;
3533 cy += GetSystemMetrics(SM_CYEDGE);
3534 cx += GetSystemMetrics(SM_CYEDGE);
3537 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3538 cx, cy, uPosFlags | SWP_NOZORDER);
3540 return 0;
3544 static LRESULT
3545 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3547 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3549 if (nType == GWL_STYLE) {
3550 if (lpStyle->styleNew & TBSTYLE_LIST) {
3551 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3553 else {
3554 infoPtr->dwDTFlags = DT_CENTER;
3558 TOOLBAR_AutoSize (hwnd);
3560 InvalidateRect(hwnd, NULL, FALSE);
3562 return 0;
3567 static LRESULT WINAPI
3568 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3571 switch (uMsg)
3573 case WM_DESTROY:
3574 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3576 case WM_NCCREATE:
3577 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3580 if (!TOOLBAR_GetInfoPtr (hwnd))
3582 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3585 switch (uMsg)
3587 case TB_ADDBITMAP:
3588 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3590 case TB_ADDBUTTONSA:
3591 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3593 case TB_ADDBUTTONSW:
3594 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3596 case TB_ADDSTRINGA:
3597 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3599 case TB_ADDSTRINGW:
3600 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3602 case TB_AUTOSIZE:
3603 return TOOLBAR_AutoSize (hwnd);
3605 case TB_BUTTONCOUNT:
3606 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3608 case TB_BUTTONSTRUCTSIZE:
3609 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3611 case TB_CHANGEBITMAP:
3612 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3614 case TB_CHECKBUTTON:
3615 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3617 case TB_COMMANDTOINDEX:
3618 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3620 case TB_CUSTOMIZE:
3621 return TOOLBAR_Customize (hwnd);
3623 case TB_DELETEBUTTON:
3624 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3626 case TB_ENABLEBUTTON:
3627 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3629 case TB_GETANCHORHIGHLIGHT:
3630 return TOOLBAR_GetAnchorHighlight (hwnd);
3632 case TB_GETBITMAP:
3633 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3635 case TB_GETBITMAPFLAGS:
3636 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3638 case TB_GETBUTTON:
3639 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3641 case TB_GETBUTTONINFOA:
3642 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3644 case TB_GETBUTTONINFOW:
3645 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3647 case TB_GETBUTTONSIZE:
3648 return TOOLBAR_GetButtonSize (hwnd);
3650 case TB_GETBUTTONTEXTA:
3651 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3653 case TB_GETBUTTONTEXTW:
3654 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
3656 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
3658 case TB_GETDISABLEDIMAGELIST:
3659 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3661 case TB_GETEXTENDEDSTYLE:
3662 return TOOLBAR_GetExtendedStyle (hwnd);
3664 case TB_GETHOTIMAGELIST:
3665 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3667 case TB_GETHOTITEM:
3668 return TOOLBAR_GetHotItem (hwnd);
3670 case TB_GETIMAGELIST:
3671 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3673 /* case TB_GETINSERTMARK: */ /* 4.71 */
3674 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
3676 case TB_GETITEMRECT:
3677 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3679 case TB_GETMAXSIZE:
3680 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3682 /* case TB_GETOBJECT: */ /* 4.71 */
3683 /* case TB_GETPADDING: */ /* 4.71 */
3685 case TB_GETRECT:
3686 return TOOLBAR_GetRect (hwnd, wParam, lParam);
3688 case TB_GETROWS:
3689 return TOOLBAR_GetRows (hwnd, wParam, lParam);
3691 case TB_GETSTATE:
3692 return TOOLBAR_GetState (hwnd, wParam, lParam);
3694 case TB_GETSTYLE:
3695 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3697 case TB_GETTEXTROWS:
3698 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3700 case TB_GETTOOLTIPS:
3701 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3703 case TB_GETUNICODEFORMAT:
3704 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3706 case CCM_GETVERSION:
3707 return TOOLBAR_GetVersion (hwnd);
3709 case TB_HIDEBUTTON:
3710 return TOOLBAR_HideButton (hwnd, wParam, lParam);
3712 case TB_HITTEST:
3713 return TOOLBAR_HitTest (hwnd, wParam, lParam);
3715 case TB_INDETERMINATE:
3716 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3718 case TB_INSERTBUTTONA:
3719 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3721 case TB_INSERTBUTTONW:
3722 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
3724 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
3726 case TB_ISBUTTONCHECKED:
3727 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3729 case TB_ISBUTTONENABLED:
3730 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3732 case TB_ISBUTTONHIDDEN:
3733 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3735 case TB_ISBUTTONHIGHLIGHTED:
3736 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3738 case TB_ISBUTTONINDETERMINATE:
3739 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3741 case TB_ISBUTTONPRESSED:
3742 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3744 case TB_LOADIMAGES: /* 4.70 */
3745 FIXME("missing standard imagelists\n");
3746 return 0;
3748 /* case TB_MAPACCELERATORA: */ /* 4.71 */
3749 /* case TB_MAPACCELERATORW: */ /* 4.71 */
3750 /* case TB_MARKBUTTON: */ /* 4.71 */
3751 /* case TB_MOVEBUTTON: */ /* 4.71 */
3753 case TB_PRESSBUTTON:
3754 return TOOLBAR_PressButton (hwnd, wParam, lParam);
3756 /* case TB_REPLACEBITMAP: */
3758 case TB_SAVERESTOREA:
3759 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3761 case TB_SAVERESTOREW:
3762 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
3764 case TB_SETANCHORHIGHLIGHT:
3765 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
3767 case TB_SETBITMAPSIZE:
3768 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3770 case TB_SETBUTTONINFOA:
3771 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3773 case TB_SETBUTTONINFOW:
3774 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
3776 case TB_SETBUTTONSIZE:
3777 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3779 case TB_SETBUTTONWIDTH:
3780 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3782 case TB_SETCMDID:
3783 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3785 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
3787 case TB_SETDISABLEDIMAGELIST:
3788 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3790 case TB_SETDRAWTEXTFLAGS:
3791 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3793 case TB_SETEXTENDEDSTYLE:
3794 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3796 case TB_SETHOTIMAGELIST:
3797 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3799 case TB_SETHOTITEM:
3800 return TOOLBAR_SetHotItem (hwnd, wParam);
3802 case TB_SETIMAGELIST:
3803 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3805 case TB_SETINDENT:
3806 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3808 /* case TB_SETINSERTMARK: */ /* 4.71 */
3810 case TB_SETINSERTMARKCOLOR:
3811 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3813 case TB_SETMAXTEXTROWS:
3814 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3816 /* case TB_SETPADDING: */ /* 4.71 */
3818 case TB_SETPARENT:
3819 return TOOLBAR_SetParent (hwnd, wParam, lParam);
3821 case TB_SETROWS:
3822 return TOOLBAR_SetRows (hwnd, wParam, lParam);
3824 case TB_SETSTATE:
3825 return TOOLBAR_SetState (hwnd, wParam, lParam);
3827 case TB_SETSTYLE:
3828 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3830 case TB_SETTOOLTIPS:
3831 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3833 case TB_SETUNICODEFORMAT:
3834 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3836 case CCM_SETVERSION:
3837 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
3840 /* case WM_CHAR: */
3842 case WM_CREATE:
3843 return TOOLBAR_Create (hwnd, wParam, lParam);
3845 case WM_ERASEBKGND:
3846 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
3848 case WM_GETFONT:
3849 return TOOLBAR_GetFont (hwnd, wParam, lParam);
3851 /* case WM_KEYDOWN: */
3852 /* case WM_KILLFOCUS: */
3854 case WM_LBUTTONDBLCLK:
3855 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
3857 case WM_LBUTTONDOWN:
3858 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
3860 case WM_LBUTTONUP:
3861 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
3863 case WM_MOUSEMOVE:
3864 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
3866 case WM_MOUSELEAVE:
3867 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
3869 case WM_NCACTIVATE:
3870 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
3872 case WM_NCCALCSIZE:
3873 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
3875 case WM_NCPAINT:
3876 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
3878 case WM_NOTIFY:
3879 return TOOLBAR_Notify (hwnd, wParam, lParam);
3881 /* case WM_NOTIFYFORMAT: */
3883 case WM_PAINT:
3884 return TOOLBAR_Paint (hwnd, wParam);
3886 case WM_SIZE:
3887 return TOOLBAR_Size (hwnd, wParam, lParam);
3889 case WM_STYLECHANGED:
3890 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
3892 /* case WM_SYSCOLORCHANGE: */
3894 /* case WM_WININICHANGE: */
3896 case WM_CHARTOITEM:
3897 case WM_COMMAND:
3898 case WM_DRAWITEM:
3899 case WM_MEASUREITEM:
3900 case WM_VKEYTOITEM:
3901 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
3903 default:
3904 if (uMsg >= WM_USER)
3905 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
3906 uMsg, wParam, lParam);
3907 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3909 return 0;
3913 VOID
3914 TOOLBAR_Register (void)
3916 WNDCLASSA wndClass;
3918 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
3919 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
3920 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
3921 wndClass.cbClsExtra = 0;
3922 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
3923 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
3924 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
3925 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
3927 RegisterClassA (&wndClass);
3931 VOID
3932 TOOLBAR_Unregister (void)
3934 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);