- Cleaned up some of the drawing code, specifically dealing with
[wine/hacks.git] / dlls / comctl32 / toolbar.c
blobe7131e0da82d1a731cc7eb44061cb9bd023be503
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);
83 if (himl && btnPtr->iBitmap>0) {
84 if (dwStyle & TBSTYLE_LIST) {
85 rcText.left += infoPtr->nBitmapWidth;
87 else {
88 rcText.top += infoPtr->nBitmapHeight;
92 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
93 OffsetRect (&rcText, 1, 1);
95 hOldFont = SelectObject (hdc, infoPtr->hFont);
96 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
97 if (!(nState & TBSTATE_ENABLED)) {
98 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
99 OffsetRect (&rcText, 1, 1);
100 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
101 &rcText, infoPtr->dwDTFlags);
102 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
103 OffsetRect (&rcText, -1, -1);
104 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
105 &rcText, infoPtr->dwDTFlags);
107 else if (nState & TBSTATE_INDETERMINATE) {
108 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
109 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
110 &rcText, infoPtr->dwDTFlags);
112 else {
113 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
114 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
115 &rcText, infoPtr->dwDTFlags);
118 SetTextColor (hdc, clrOld);
119 SelectObject (hdc, hOldFont);
120 if (nOldBkMode != TRANSPARENT)
121 SetBkMode (hdc, nOldBkMode);
126 static void
127 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
129 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
130 INT cx = lpRect->right - lpRect->left;
131 INT cy = lpRect->bottom - lpRect->top;
132 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
133 SelectObject (hdc, hbr);
137 static void
138 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
139 HDC hdc, INT x, INT y)
141 /* FIXME: this function is a hack since it uses image list
142 internals directly */
144 HIMAGELIST himl = infoPtr->himlDef;
145 HBITMAP hbmMask;
146 HDC hdcImageList;
147 HDC hdcMask;
149 if (!himl)
150 return;
152 /* create new dc's */
153 hdcImageList = CreateCompatibleDC (0);
154 hdcMask = CreateCompatibleDC (0);
156 /* create new bitmap */
157 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
158 SelectObject (hdcMask, hbmMask);
160 /* copy the mask bitmap */
161 SelectObject (hdcImageList, himl->hbmMask);
162 SetBkColor (hdcImageList, RGB(255, 255, 255));
163 SetTextColor (hdcImageList, RGB(0, 0, 0));
164 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
165 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
167 #if 0
168 /* add white mask from image */
169 SelectObject (hdcImageList, himl->hbmImage);
170 SetBkColor (hdcImageList, RGB(0, 0, 0));
171 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
172 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
173 #endif
175 /* draw the new mask */
176 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
177 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
178 hdcMask, 0, 0, 0xB8074A);
180 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
181 BitBlt (hdc, x, y, himl->cx, himl->cy,
182 hdcMask, 0, 0, 0xB8074A);
184 DeleteObject (hbmMask);
185 DeleteDC (hdcMask);
186 DeleteDC (hdcImageList);
190 static void
191 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
193 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
194 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
195 RECT rc;
197 if (btnPtr->fsState & TBSTATE_HIDDEN)
198 return;
200 rc = btnPtr->rect;
202 /* separator */
203 if (btnPtr->fsStyle & TBSTYLE_SEP) {
204 if ((dwStyle & TBSTYLE_FLAT) && (btnPtr->iBitmap == 0))
205 TOOLBAR_DrawFlatSeparator (&rc, hdc);
206 return;
209 /* disabled */
210 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
211 if (!(dwStyle & TBSTYLE_FLAT))
212 DrawEdge (hdc, &rc, EDGE_RAISED,
213 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
215 if (infoPtr->himlDis && btnPtr->iBitmap>=0)
216 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
217 rc.left+1, rc.top+1, ILD_NORMAL);
218 else
219 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
221 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
222 infoPtr->himlDis);
223 return;
226 /* pressed TBSTYLE_BUTTON */
227 if (btnPtr->fsState & TBSTATE_PRESSED) {
228 if (dwStyle & TBSTYLE_FLAT)
229 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
230 else
231 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
232 if (btnPtr->iBitmap>0)
233 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
234 rc.left+2, rc.top+2, ILD_NORMAL);
235 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
236 infoPtr->himlDef);
237 return;
240 /* checked TBSTYLE_CHECK */
241 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
242 (btnPtr->fsState & TBSTATE_CHECKED)) {
243 if (dwStyle & TBSTYLE_FLAT)
244 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
245 BF_RECT | BF_MIDDLE | BF_ADJUST);
246 else
247 DrawEdge (hdc, &rc, EDGE_SUNKEN,
248 BF_RECT | BF_MIDDLE | BF_ADJUST);
250 TOOLBAR_DrawPattern (hdc, &rc);
252 if (btnPtr->iBitmap>0)
253 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
254 rc.left+2, rc.top+2, ILD_NORMAL);
256 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
257 infoPtr->himlDef);
258 return;
261 /* indeterminate */
262 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
263 DrawEdge (hdc, &rc, EDGE_RAISED,
264 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
266 TOOLBAR_DrawPattern (hdc, &rc);
267 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
268 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
269 infoPtr->himlDef);
270 return;
273 /* normal state */
274 if (dwStyle & TBSTYLE_FLAT)
276 if (btnPtr->bHot)
277 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
278 if (btnPtr->bHot && infoPtr->himlHot && btnPtr->iBitmap>0)
279 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
280 rc.left +2, rc.top +2, ILD_NORMAL);
281 else if (btnPtr->iBitmap>0)
282 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
283 rc.left +2, rc.top +2, ILD_NORMAL);
285 else
287 DrawEdge (hdc, &rc, EDGE_RAISED,
288 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
290 if (btnPtr->iBitmap>0)
291 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
292 rc.left+1, rc.top+1, ILD_NORMAL);
295 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle,
296 infoPtr->himlDef);
300 static void
301 TOOLBAR_Refresh (HWND hwnd, HDC hdc)
303 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
304 TBUTTON_INFO *btnPtr;
305 INT i;
307 /* draw buttons */
308 btnPtr = infoPtr->buttons;
309 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
310 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
314 static void
315 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
317 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
318 TBUTTON_INFO *btnPtr;
319 INT i;
320 HDC hdc;
321 HFONT hOldFont;
322 SIZE sz;
325 lpSize->cx = 0;
326 lpSize->cy = 0;
327 hdc = GetDC (0);
328 hOldFont = SelectObject (hdc, infoPtr->hFont);
330 btnPtr = infoPtr->buttons;
331 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
332 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
333 (btnPtr->iString > -1) &&
334 (btnPtr->iString < infoPtr->nNumStrings)) {
335 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
336 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), &sz);
337 if (sz.cx > lpSize->cx)
338 lpSize->cx = sz.cx;
339 if (sz.cy > lpSize->cy)
340 lpSize->cy = sz.cy;
344 SelectObject (hdc, hOldFont);
345 ReleaseDC (0, hdc);
347 TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
350 /***********************************************************************
351 * TOOLBAR_WrapToolbar
353 * This function walks through the buttons and seperators in the
354 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
355 * wrapping should occur based on the width of the toolbar window.
356 * It does *not* calculate button placement itself. That task
357 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
358 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
359 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
362 static void
363 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
365 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
366 TBUTTON_INFO *btnPtr;
367 INT x, cx, i, j;
368 RECT rc;
369 BOOL bWrap, bButtonWrap;
371 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
372 /* no layout is necessary. Applications may use this style */
373 /* to perform their own layout on the toolbar. */
374 if( !(dwStyle & TBSTYLE_WRAPABLE) )
375 return;
377 btnPtr = infoPtr->buttons;
378 x = infoPtr->nIndent;
380 /* this can get the parents width, to know how far we can extend
381 * this toolbar. We cannot use its height, as there may be multiple
382 * toolbars in a rebar control
384 GetClientRect( GetParent(hwnd), &rc );
385 infoPtr->nWidth = rc.right - rc.left;
386 bButtonWrap = FALSE;
388 for (i = 0; i < infoPtr->nNumButtons; i++ )
390 bWrap = FALSE;
391 btnPtr[i].fsState &= ~TBSTATE_WRAP;
393 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
394 continue;
396 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
397 /* it is the actual width of the separator. This is used for */
398 /* custom controls in toolbars. */
399 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
400 cx = (btnPtr[i].iBitmap > 0) ?
401 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
402 else
403 cx = infoPtr->nButtonWidth;
405 /* Two or more adjacent separators form a separator group. */
406 /* The first separator in a group should be wrapped to the */
407 /* next row if the previous wrapping is on a button. */
408 if( bButtonWrap &&
409 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
410 (i + 1 < infoPtr->nNumButtons ) &&
411 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
413 btnPtr[i].fsState |= TBSTATE_WRAP;
414 x = infoPtr->nIndent;
415 i++;
416 bButtonWrap = FALSE;
417 continue;
420 /* The layout makes sure the bitmap is visible, but not the button. */
421 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
422 > infoPtr->nWidth )
424 BOOL bFound = FALSE;
426 /* If the current button is a separator and not hidden, */
427 /* go to the next until it reaches a non separator. */
428 /* Wrap the last separator if it is before a button. */
429 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
430 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
431 i < infoPtr->nNumButtons )
433 i++;
434 bFound = TRUE;
437 if( bFound && i < infoPtr->nNumButtons )
439 i--;
440 btnPtr[i].fsState |= TBSTATE_WRAP;
441 x = infoPtr->nIndent;
442 bButtonWrap = FALSE;
443 continue;
445 else if ( i >= infoPtr->nNumButtons)
446 break;
448 /* If the current button is not a separator, find the last */
449 /* separator and wrap it. */
450 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
452 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
453 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
455 bFound = TRUE;
456 i = j;
457 x = infoPtr->nIndent;
458 btnPtr[j].fsState |= TBSTATE_WRAP;
459 bButtonWrap = FALSE;
460 break;
464 /* If no separator available for wrapping, wrap one of */
465 /* non-hidden previous button. */
466 if (!bFound)
468 for ( j = i - 1;
469 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
471 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
472 continue;
474 bFound = TRUE;
475 i = j;
476 x = infoPtr->nIndent;
477 btnPtr[j].fsState |= TBSTATE_WRAP;
478 bButtonWrap = TRUE;
479 break;
483 /* If all above failed, wrap the current button. */
484 if (!bFound)
486 btnPtr[i].fsState |= TBSTATE_WRAP;
487 bFound = TRUE;
488 x = infoPtr->nIndent;
489 if (btnPtr[i].fsState & TBSTYLE_SEP )
490 bButtonWrap = FALSE;
491 else
492 bButtonWrap = TRUE;
495 else
496 x += cx;
500 /***********************************************************************
501 * TOOLBAR_CalcToolbar
503 * This function calculates button and separator placement. It first
504 * calculates the button sizes, gets the toolbar window width and then
505 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
506 * on. It assigns a new location to each item and sends this location to
507 * the tooltip window if appropriate. Finally, it updates the rcBound
508 * rect and calculates the new required toolbar window height.
511 static void
512 TOOLBAR_CalcToolbar (HWND hwnd)
514 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
515 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
516 TBUTTON_INFO *btnPtr;
517 INT i, nRows, nSepRows;
518 INT x, y, cx, cy;
519 SIZE sizeString;
520 RECT rc;
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 if (sizeString.cy > 0)
531 infoPtr->nButtonHeight = sizeString.cy + infoPtr->nBitmapHeight + 6;
532 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
533 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
535 if (sizeString.cx > infoPtr->nBitmapWidth)
536 infoPtr->nButtonWidth = sizeString.cx + 6;
537 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
538 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
541 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
542 infoPtr->nButtonWidth = infoPtr->cxMin;
543 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
544 infoPtr->nButtonWidth = infoPtr->cxMax;
546 TOOLBAR_WrapToolbar( hwnd, dwStyle );
548 x = infoPtr->nIndent;
549 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
551 GetClientRect( hwnd, &rc );
552 /* get initial values for toolbar */
553 infoPtr->nWidth = rc.right - rc.left;
554 infoPtr->nHeight = rc.bottom - rc.top;
556 /* from above, minimum is a button, and possible text */
557 cx = infoPtr->nButtonWidth;
558 /* cannot use just ButtonHeight, we may have no buttons! */
559 cy = infoPtr->nHeight;
561 nRows = nSepRows = 0;
563 infoPtr->rcBound.top = y;
564 infoPtr->rcBound.left = x;
565 infoPtr->rcBound.bottom = y + cy;
566 infoPtr->rcBound.right = x;
568 btnPtr = infoPtr->buttons;
570 /* do not base height/width on parent, if the parent is a */
571 /* rebar control it could have multiple rows of toolbars */
572 /* GetClientRect( GetParent(hwnd), &rc ); */
573 /* cx = rc.right - rc.left; */
574 /* cy = rc.bottom - rc.top; */
576 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
578 bWrap = FALSE;
579 if (btnPtr->fsState & TBSTATE_HIDDEN)
581 SetRectEmpty (&btnPtr->rect);
582 continue;
585 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
586 /* it is the actual width of the separator. This is used for */
587 /* custom controls in toolbars. */
588 if (btnPtr->fsStyle & TBSTYLE_SEP)
589 cx = (btnPtr->iBitmap > 0) ?
590 btnPtr->iBitmap : SEPARATOR_WIDTH;
591 else {
592 cx = infoPtr->nButtonWidth;
594 cy = infoPtr->nHeight;
596 if (btnPtr->fsState & TBSTATE_WRAP )
597 bWrap = TRUE;
599 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
601 if (infoPtr->rcBound.left > x)
602 infoPtr->rcBound.left = x;
603 if (infoPtr->rcBound.right < x + cx)
604 infoPtr->rcBound.right = x + cx;
605 if (infoPtr->rcBound.bottom < y + cy)
606 infoPtr->rcBound.bottom = y + cy;
608 /* Set the toolTip only for non-hidden, non-separator button */
609 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
611 TTTOOLINFOA ti;
613 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
614 ti.cbSize = sizeof(TTTOOLINFOA);
615 ti.hwnd = hwnd;
616 ti.uId = btnPtr->idCommand;
617 ti.rect = btnPtr->rect;
618 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
619 0, (LPARAM)&ti);
622 /* btnPtr->nRow is zero based. The space between the rows is */
623 /* also considered as a row. */
624 btnPtr->nRow = nRows + nSepRows;
625 if( bWrap )
627 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
628 y += cy;
629 else
631 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
632 /* it is the actual width of the separator. This is used for */
633 /* custom controls in toolbars. */
634 y += cy + ( (btnPtr->iBitmap > 0 ) ?
635 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
637 /* nSepRows is used to calculate the extra height follwoing */
638 /* the last row. */
639 nSepRows++;
641 x = infoPtr->nIndent;
642 nRows++;
644 else
645 x += cx;
648 /* infoPtr->nRows is the number of rows on the toolbar */
649 infoPtr->nRows = nRows + nSepRows + 1;
651 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
652 /* the last row. */
653 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
654 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
655 nSepRows * (infoPtr->nBitmapHeight + 1) +
656 BOTTOM_BORDER;
657 TRACE("toolbar height %d\n", infoPtr->nHeight);
661 static INT
662 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
664 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
665 TBUTTON_INFO *btnPtr;
666 INT i;
668 btnPtr = infoPtr->buttons;
669 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
670 if (btnPtr->fsState & TBSTATE_HIDDEN)
671 continue;
673 if (btnPtr->fsStyle & TBSTYLE_SEP) {
674 if (PtInRect (&btnPtr->rect, *lpPt)) {
675 TRACE(" ON SEPARATOR %d!\n", i);
676 return -i;
679 else {
680 if (PtInRect (&btnPtr->rect, *lpPt)) {
681 TRACE(" ON BUTTON %d!\n", i);
682 return i;
687 TRACE(" NOWHERE!\n");
688 return -1;
692 static INT
693 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
695 TBUTTON_INFO *btnPtr;
696 INT i;
698 btnPtr = infoPtr->buttons;
699 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
700 if (btnPtr->idCommand == idCommand) {
701 TRACE("command=%d index=%d\n", idCommand, i);
702 return i;
705 TRACE("no index found for command=%d\n", idCommand);
706 return -1;
710 static INT
711 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
713 TBUTTON_INFO *btnPtr;
714 INT nRunIndex;
716 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
717 return -1;
719 /* check index button */
720 btnPtr = &infoPtr->buttons[nIndex];
721 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
722 if (btnPtr->fsState & TBSTATE_CHECKED)
723 return nIndex;
726 /* check previous buttons */
727 nRunIndex = nIndex - 1;
728 while (nRunIndex >= 0) {
729 btnPtr = &infoPtr->buttons[nRunIndex];
730 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
731 if (btnPtr->fsState & TBSTATE_CHECKED)
732 return nRunIndex;
734 else
735 break;
736 nRunIndex--;
739 /* check next buttons */
740 nRunIndex = nIndex + 1;
741 while (nRunIndex < infoPtr->nNumButtons) {
742 btnPtr = &infoPtr->buttons[nRunIndex];
743 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
744 if (btnPtr->fsState & TBSTATE_CHECKED)
745 return nRunIndex;
747 else
748 break;
749 nRunIndex++;
752 return -1;
756 static VOID
757 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
758 WPARAM wParam, LPARAM lParam)
760 MSG msg;
762 msg.hwnd = hwndMsg;
763 msg.message = uMsg;
764 msg.wParam = wParam;
765 msg.lParam = lParam;
766 msg.time = GetMessageTime ();
767 msg.pt.x = LOWORD(GetMessagePos ());
768 msg.pt.y = HIWORD(GetMessagePos ());
770 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
774 /***********************************************************************
775 * TOOLBAR_CustomizeDialogProc
776 * This function implements the toolbar customization dialog.
778 static BOOL WINAPI
779 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
781 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
782 static HDSA hDsa = NULL;
784 switch (uMsg)
786 case WM_INITDIALOG:
787 infoPtr = (TOOLBAR_INFO *)lParam;
788 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
790 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
792 if (infoPtr)
794 TBUTTON_INFO *btnPtr;
795 INT i;
797 /* insert 'virtual' separator button into 'available buttons' list */
798 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
800 /* copy all buttons and append them to the right listbox */
801 btnPtr = infoPtr->buttons;
802 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
804 DSA_InsertItem (hDsa, i, btnPtr);
806 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
807 if (btnPtr->fsState & TBSTATE_HIDDEN)
809 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
811 else
813 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
817 /* append 'virtual' separator button to the 'toolbar buttons' list */
818 /* TODO */
820 return TRUE;
822 case WM_CLOSE:
823 EndDialog(hwnd, FALSE);
824 return TRUE;
826 case WM_COMMAND:
827 switch (LOWORD(wParam))
829 case IDCANCEL:
830 EndDialog(hwnd, FALSE);
831 break;
833 return TRUE;
835 case WM_DESTROY:
836 if (hDsa)
837 DSA_Destroy (hDsa);
838 return TRUE;
840 case WM_DRAWITEM:
841 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
843 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
844 TBUTTON_INFO btnPtr;
845 RECT rcButton;
846 RECT rcText;
847 HPEN hOldPen;
848 HBRUSH hOldBrush;
849 COLORREF oldText = 0;
850 COLORREF oldBk = 0;
852 FIXME("action: %x itemState: %x\n",
853 lpdis->itemAction, lpdis->itemState);
855 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
857 if (lpdis->itemState & ODS_FOCUS)
859 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
860 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
863 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
864 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
866 /* fill background rectangle */
867 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
868 lpdis->rcItem.right, lpdis->rcItem.bottom);
870 /* calculate button and text rectangles */
871 CopyRect (&rcButton, &lpdis->rcItem);
872 InflateRect (&rcButton, -1, -1);
873 CopyRect (&rcText, &rcButton);
874 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
875 rcText.left = rcButton.right + 2;
877 /* draw focus rectangle */
878 if (lpdis->itemState & ODS_FOCUS)
879 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
881 /* draw button */
882 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
884 /* draw image and text */
885 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
887 /* virtual separator in the 'available' list */
888 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
889 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
891 else
893 /* real button */
895 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
896 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
898 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
899 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
903 if (lpdis->itemState & ODS_FOCUS)
905 SetBkColor (lpdis->hDC, oldBk);
906 SetTextColor (lpdis->hDC, oldText);
909 SelectObject (lpdis->hDC, hOldBrush);
910 SelectObject (lpdis->hDC, hOldPen);
912 return TRUE;
914 return FALSE;
916 case WM_MEASUREITEM:
917 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
919 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
921 if (infoPtr)
922 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
923 else
924 lpmis->itemHeight = 15 + 8; /* default height */
926 return TRUE;
928 return FALSE;
930 default:
931 return FALSE;
936 /***********************************************************************
937 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
940 static LRESULT
941 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
943 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
944 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
945 INT nIndex = 0, nButtons;
946 HBITMAP hbmLoad;
948 if (!lpAddBmp)
949 return -1;
951 if (lpAddBmp->hInst == HINST_COMMCTRL)
953 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
954 nButtons = 15;
955 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
956 nButtons = 13;
957 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
958 nButtons = 5;
959 else
960 return -1;
962 TRACE ("adding %d internal bitmaps!\n", nButtons);
964 /* Windows resize all the buttons to the size of a newly added standard image */
965 if (lpAddBmp->nID & 1)
967 /* large icons */
968 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
969 MAKELPARAM((WORD)26, (WORD)26));
970 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
971 MAKELPARAM((WORD)33, (WORD)33));
973 else
975 /* small icons */
976 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
977 MAKELPARAM((WORD)16, (WORD)16));
978 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
979 MAKELPARAM((WORD)22, (WORD)22));
982 TOOLBAR_CalcToolbar (hwnd);
984 else
986 nButtons = (INT)wParam;
987 if (nButtons <= 0)
988 return -1;
990 TRACE ("adding %d bitmaps!\n", nButtons);
993 if (!(infoPtr->himlDef)) {
994 /* create new default image list */
995 TRACE ("creating default image list!\n");
997 infoPtr->himlDef =
998 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight + 1,
999 ILC_COLOR | ILC_MASK, nButtons, 2);
1000 infoPtr->himlInt = infoPtr->himlDef;
1003 /* Add bitmaps to the default image list */
1004 if (lpAddBmp->hInst == (HINSTANCE)0)
1006 nIndex =
1007 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1008 CLR_DEFAULT);
1010 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1012 /* Add system bitmaps */
1013 switch (lpAddBmp->nID)
1015 case IDB_STD_SMALL_COLOR:
1016 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1017 MAKEINTRESOURCEA(IDB_STD_SMALL));
1018 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1019 hbmLoad, CLR_DEFAULT);
1020 DeleteObject (hbmLoad);
1021 break;
1023 case IDB_STD_LARGE_COLOR:
1024 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1025 MAKEINTRESOURCEA(IDB_STD_LARGE));
1026 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1027 hbmLoad, CLR_DEFAULT);
1028 DeleteObject (hbmLoad);
1029 break;
1031 case IDB_VIEW_SMALL_COLOR:
1032 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1033 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1034 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1035 hbmLoad, CLR_DEFAULT);
1036 DeleteObject (hbmLoad);
1037 break;
1039 case IDB_VIEW_LARGE_COLOR:
1040 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1041 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1042 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1043 hbmLoad, CLR_DEFAULT);
1044 DeleteObject (hbmLoad);
1045 break;
1047 case IDB_HIST_SMALL_COLOR:
1048 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1049 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1050 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1051 hbmLoad, CLR_DEFAULT);
1052 DeleteObject (hbmLoad);
1053 break;
1055 case IDB_HIST_LARGE_COLOR:
1056 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1057 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1058 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1059 hbmLoad, CLR_DEFAULT);
1060 DeleteObject (hbmLoad);
1061 break;
1063 default:
1064 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1065 ERR ("invalid imagelist!\n");
1066 break;
1069 else
1071 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1072 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1073 DeleteObject (hbmLoad);
1076 infoPtr->nNumBitmaps += nButtons;
1078 return nIndex;
1082 static LRESULT
1083 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1085 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1086 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1087 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1089 TRACE("adding %d buttons!\n", wParam);
1091 nAddButtons = (UINT)wParam;
1092 nOldButtons = infoPtr->nNumButtons;
1093 nNewButtons = nOldButtons + nAddButtons;
1095 if (infoPtr->nNumButtons == 0) {
1096 infoPtr->buttons =
1097 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1099 else {
1100 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1101 infoPtr->buttons =
1102 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1103 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1104 nOldButtons * sizeof(TBUTTON_INFO));
1105 COMCTL32_Free (oldButtons);
1108 infoPtr->nNumButtons = nNewButtons;
1110 /* insert new button data */
1111 for (nCount = 0; nCount < nAddButtons; nCount++) {
1112 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1113 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1114 btnPtr->idCommand = lpTbb[nCount].idCommand;
1115 btnPtr->fsState = lpTbb[nCount].fsState;
1116 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1117 btnPtr->dwData = lpTbb[nCount].dwData;
1118 btnPtr->iString = lpTbb[nCount].iString;
1119 btnPtr->bHot = FALSE;
1121 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1122 TTTOOLINFOA ti;
1124 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1125 ti.cbSize = sizeof (TTTOOLINFOA);
1126 ti.hwnd = hwnd;
1127 ti.uId = btnPtr->idCommand;
1128 ti.hinst = 0;
1129 ti.lpszText = LPSTR_TEXTCALLBACKA;
1131 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1132 0, (LPARAM)&ti);
1136 TOOLBAR_CalcToolbar (hwnd);
1138 InvalidateRect(hwnd, NULL, FALSE);
1140 return TRUE;
1144 static LRESULT
1145 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1147 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1148 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1149 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1151 TRACE("adding %d buttons!\n", wParam);
1153 nAddButtons = (UINT)wParam;
1154 nOldButtons = infoPtr->nNumButtons;
1155 nNewButtons = nOldButtons + nAddButtons;
1157 if (infoPtr->nNumButtons == 0) {
1158 infoPtr->buttons =
1159 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1161 else {
1162 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1163 infoPtr->buttons =
1164 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1165 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1166 nOldButtons * sizeof(TBUTTON_INFO));
1167 COMCTL32_Free (oldButtons);
1170 infoPtr->nNumButtons = nNewButtons;
1172 /* insert new button data */
1173 for (nCount = 0; nCount < nAddButtons; nCount++) {
1174 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1175 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1176 btnPtr->idCommand = lpTbb[nCount].idCommand;
1177 btnPtr->fsState = lpTbb[nCount].fsState;
1178 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1179 btnPtr->dwData = lpTbb[nCount].dwData;
1180 btnPtr->iString = lpTbb[nCount].iString;
1181 btnPtr->bHot = FALSE;
1183 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1184 TTTOOLINFOW ti;
1186 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1187 ti.cbSize = sizeof (TTTOOLINFOW);
1188 ti.hwnd = hwnd;
1189 ti.uId = btnPtr->idCommand;
1190 ti.hinst = 0;
1191 ti.lpszText = LPSTR_TEXTCALLBACKW;
1193 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1194 0, (LPARAM)&ti);
1198 TOOLBAR_CalcToolbar (hwnd);
1200 InvalidateRect(hwnd, NULL, FALSE);
1202 return TRUE;
1206 static LRESULT
1207 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1209 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1210 INT nIndex;
1212 if ((wParam) && (HIWORD(lParam) == 0)) {
1213 char szString[256];
1214 INT len;
1215 TRACE("adding string from resource!\n");
1217 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1218 szString, 256);
1220 TRACE("len=%d \"%s\"\n", len, szString);
1221 nIndex = infoPtr->nNumStrings;
1222 if (infoPtr->nNumStrings == 0) {
1223 infoPtr->strings =
1224 COMCTL32_Alloc (sizeof(LPWSTR));
1226 else {
1227 LPWSTR *oldStrings = infoPtr->strings;
1228 infoPtr->strings =
1229 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1230 memcpy (&infoPtr->strings[0], &oldStrings[0],
1231 sizeof(LPWSTR) * infoPtr->nNumStrings);
1232 COMCTL32_Free (oldStrings);
1235 infoPtr->strings[infoPtr->nNumStrings] =
1236 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1237 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1238 infoPtr->nNumStrings++;
1240 else {
1241 LPSTR p = (LPSTR)lParam;
1242 INT len;
1244 if (p == NULL)
1245 return -1;
1246 TRACE("adding string(s) from array!\n");
1247 nIndex = infoPtr->nNumStrings;
1248 while (*p) {
1249 len = lstrlenA (p);
1250 TRACE("len=%d \"%s\"\n", len, p);
1252 if (infoPtr->nNumStrings == 0) {
1253 infoPtr->strings =
1254 COMCTL32_Alloc (sizeof(LPWSTR));
1256 else {
1257 LPWSTR *oldStrings = infoPtr->strings;
1258 infoPtr->strings =
1259 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1260 memcpy (&infoPtr->strings[0], &oldStrings[0],
1261 sizeof(LPWSTR) * infoPtr->nNumStrings);
1262 COMCTL32_Free (oldStrings);
1265 infoPtr->strings[infoPtr->nNumStrings] =
1266 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1267 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1268 infoPtr->nNumStrings++;
1270 p += (len+1);
1274 return nIndex;
1278 static LRESULT
1279 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1281 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1282 INT nIndex;
1284 if ((wParam) && (HIWORD(lParam) == 0)) {
1285 WCHAR szString[256];
1286 INT len;
1287 TRACE("adding string from resource!\n");
1289 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1290 szString, 256);
1292 TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1293 nIndex = infoPtr->nNumStrings;
1294 if (infoPtr->nNumStrings == 0) {
1295 infoPtr->strings =
1296 COMCTL32_Alloc (sizeof(LPWSTR));
1298 else {
1299 LPWSTR *oldStrings = infoPtr->strings;
1300 infoPtr->strings =
1301 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1302 memcpy (&infoPtr->strings[0], &oldStrings[0],
1303 sizeof(LPWSTR) * infoPtr->nNumStrings);
1304 COMCTL32_Free (oldStrings);
1307 infoPtr->strings[infoPtr->nNumStrings] =
1308 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1309 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1310 infoPtr->nNumStrings++;
1312 else {
1313 LPWSTR p = (LPWSTR)lParam;
1314 INT len;
1316 if (p == NULL)
1317 return -1;
1318 TRACE("adding string(s) from array!\n");
1319 nIndex = infoPtr->nNumStrings;
1320 while (*p) {
1321 len = lstrlenW (p);
1322 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1324 if (infoPtr->nNumStrings == 0) {
1325 infoPtr->strings =
1326 COMCTL32_Alloc (sizeof(LPWSTR));
1328 else {
1329 LPWSTR *oldStrings = infoPtr->strings;
1330 infoPtr->strings =
1331 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1332 memcpy (&infoPtr->strings[0], &oldStrings[0],
1333 sizeof(LPWSTR) * infoPtr->nNumStrings);
1334 COMCTL32_Free (oldStrings);
1337 infoPtr->strings[infoPtr->nNumStrings] =
1338 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1339 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1340 infoPtr->nNumStrings++;
1342 p += (len+1);
1346 return nIndex;
1350 static LRESULT
1351 TOOLBAR_AutoSize (HWND hwnd)
1353 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1354 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1355 RECT parent_rect;
1356 RECT window_rect;
1357 HWND parent;
1358 INT x, y;
1359 INT cx, cy;
1360 UINT uPosFlags = 0;
1362 TRACE("resize forced!\n");
1364 parent = GetParent (hwnd);
1365 GetClientRect(parent, &parent_rect);
1367 x = parent_rect.left;
1368 y = parent_rect.top;
1370 if (dwStyle & CCS_NORESIZE) {
1371 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1372 cx = 0;
1373 cy = 0;
1375 else {
1376 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1377 TOOLBAR_CalcToolbar (hwnd);
1378 InvalidateRect( hwnd, NULL, TRUE );
1379 cy = infoPtr->nHeight;
1380 cx = infoPtr->nWidth;
1382 if (dwStyle & CCS_NOMOVEY) {
1383 GetWindowRect(hwnd, &window_rect);
1384 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1385 y = window_rect.top;
1389 if (dwStyle & CCS_NOPARENTALIGN)
1390 uPosFlags |= SWP_NOMOVE;
1392 if (!(dwStyle & CCS_NODIVIDER))
1393 cy += GetSystemMetrics(SM_CYEDGE);
1395 if (dwStyle & WS_BORDER)
1397 x = y = 1;
1398 cy += GetSystemMetrics(SM_CYEDGE);
1399 cx += GetSystemMetrics(SM_CYEDGE);
1402 infoPtr->bAutoSize = TRUE;
1403 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1404 cx, cy, uPosFlags);
1405 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1406 * the setwindowpos calls */
1407 infoPtr->bAutoSize = FALSE;
1409 return 0;
1413 static LRESULT
1414 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1416 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1418 return infoPtr->nNumButtons;
1422 static LRESULT
1423 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1425 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1427 if (infoPtr == NULL) {
1428 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1429 ERR("infoPtr == NULL!\n");
1430 return 0;
1433 infoPtr->dwStructSize = (DWORD)wParam;
1435 return 0;
1439 static LRESULT
1440 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1442 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1443 TBUTTON_INFO *btnPtr;
1444 INT nIndex;
1446 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1447 if (nIndex == -1)
1448 return FALSE;
1450 btnPtr = &infoPtr->buttons[nIndex];
1451 btnPtr->iBitmap = LOWORD(lParam);
1453 RedrawWindow(hwnd,&btnPtr->rect,NULL,RDW_ERASE|RDW_INVALIDATE);
1455 return TRUE;
1459 static LRESULT
1460 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1462 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1463 TBUTTON_INFO *btnPtr;
1464 INT nIndex;
1465 INT nOldIndex = -1;
1466 BOOL bChecked = FALSE;
1468 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1469 if (nIndex == -1)
1470 return FALSE;
1472 btnPtr = &infoPtr->buttons[nIndex];
1474 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1475 return FALSE;
1477 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1479 if (LOWORD(lParam) == FALSE)
1480 btnPtr->fsState &= ~TBSTATE_CHECKED;
1481 else {
1482 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1483 nOldIndex =
1484 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1485 if (nOldIndex == nIndex)
1486 return 0;
1487 if (nOldIndex != -1)
1488 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1490 btnPtr->fsState |= TBSTATE_CHECKED;
1493 if( bChecked != LOWORD(lParam) )
1495 if (nOldIndex != -1)
1496 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,NULL,
1497 RDW_ERASE|RDW_INVALIDATE);
1498 RedrawWindow(hwnd,&btnPtr->rect,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1501 /* FIXME: Send a WM_NOTIFY?? */
1503 return TRUE;
1507 static LRESULT
1508 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1510 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1512 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1516 static LRESULT
1517 TOOLBAR_Customize (HWND hwnd)
1519 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1520 LRESULT ret;
1521 LPCVOID template;
1522 HRSRC hRes;
1523 NMHDR nmhdr;
1525 /* send TBN_BEGINADJUST notification */
1526 nmhdr.hwndFrom = hwnd;
1527 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1528 nmhdr.code = TBN_BEGINADJUST;
1530 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1531 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1533 if (!(hRes = FindResourceA (COMCTL32_hModule,
1534 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1535 RT_DIALOGA)))
1536 return FALSE;
1538 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1539 return FALSE;
1541 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1542 (LPDLGTEMPLATEA)template,
1543 hwnd,
1544 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1545 (LPARAM)infoPtr);
1547 /* send TBN_ENDADJUST notification */
1548 nmhdr.code = TBN_ENDADJUST;
1550 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1551 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1553 return ret;
1557 static LRESULT
1558 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1560 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1561 INT nIndex = (INT)wParam;
1563 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1564 return FALSE;
1566 if ((infoPtr->hwndToolTip) &&
1567 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1568 TTTOOLINFOA ti;
1570 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1571 ti.cbSize = sizeof (TTTOOLINFOA);
1572 ti.hwnd = hwnd;
1573 ti.uId = infoPtr->buttons[nIndex].idCommand;
1575 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1578 if (infoPtr->nNumButtons == 1) {
1579 TRACE(" simple delete!\n");
1580 COMCTL32_Free (infoPtr->buttons);
1581 infoPtr->buttons = NULL;
1582 infoPtr->nNumButtons = 0;
1584 else {
1585 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1586 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1588 infoPtr->nNumButtons--;
1589 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1590 if (nIndex > 0) {
1591 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1592 nIndex * sizeof(TBUTTON_INFO));
1595 if (nIndex < infoPtr->nNumButtons) {
1596 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1597 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1600 COMCTL32_Free (oldButtons);
1603 TOOLBAR_CalcToolbar (hwnd);
1605 InvalidateRect (hwnd, NULL, TRUE);
1607 return TRUE;
1611 static LRESULT
1612 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1614 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1615 TBUTTON_INFO *btnPtr;
1616 INT nIndex;
1617 DWORD bState;
1619 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1620 if (nIndex == -1)
1621 return FALSE;
1623 btnPtr = &infoPtr->buttons[nIndex];
1625 bState = btnPtr->fsState & TBSTATE_ENABLED;
1627 /* update the toolbar button state */
1628 if(LOWORD(lParam) == FALSE) {
1629 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1630 } else {
1631 btnPtr->fsState |= TBSTATE_ENABLED;
1634 /* redraw the button only if the state of the button changed */
1635 if(bState != (btnPtr->fsState & TBSTATE_ENABLED)) {
1636 RedrawWindow(hwnd,&btnPtr->rect,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
1639 return TRUE;
1643 static inline LRESULT
1644 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1646 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1648 return infoPtr->bAnchor;
1652 static LRESULT
1653 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1655 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1656 INT nIndex;
1658 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1659 if (nIndex == -1)
1660 return -1;
1662 return infoPtr->buttons[nIndex].iBitmap;
1666 static inline LRESULT
1667 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1669 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1673 static LRESULT
1674 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1676 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1677 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1678 INT nIndex = (INT)wParam;
1679 TBUTTON_INFO *btnPtr;
1681 if (infoPtr == NULL)
1682 return FALSE;
1684 if (lpTbb == NULL)
1685 return FALSE;
1687 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1688 return FALSE;
1690 btnPtr = &infoPtr->buttons[nIndex];
1691 lpTbb->iBitmap = btnPtr->iBitmap;
1692 lpTbb->idCommand = btnPtr->idCommand;
1693 lpTbb->fsState = btnPtr->fsState;
1694 lpTbb->fsStyle = btnPtr->fsStyle;
1695 lpTbb->dwData = btnPtr->dwData;
1696 lpTbb->iString = btnPtr->iString;
1698 return TRUE;
1702 static LRESULT
1703 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1705 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1706 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1707 TBUTTON_INFO *btnPtr;
1708 INT nIndex;
1710 if (infoPtr == NULL)
1711 return -1;
1712 if (lpTbInfo == NULL)
1713 return -1;
1714 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1715 return -1;
1717 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1718 if (nIndex == -1)
1719 return -1;
1721 btnPtr = &infoPtr->buttons[nIndex];
1723 if (lpTbInfo->dwMask & TBIF_COMMAND)
1724 lpTbInfo->idCommand = btnPtr->idCommand;
1725 if (lpTbInfo->dwMask & TBIF_IMAGE)
1726 lpTbInfo->iImage = btnPtr->iBitmap;
1727 if (lpTbInfo->dwMask & TBIF_LPARAM)
1728 lpTbInfo->lParam = btnPtr->dwData;
1729 if (lpTbInfo->dwMask & TBIF_SIZE)
1730 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1731 if (lpTbInfo->dwMask & TBIF_STATE)
1732 lpTbInfo->fsState = btnPtr->fsState;
1733 if (lpTbInfo->dwMask & TBIF_STYLE)
1734 lpTbInfo->fsStyle = btnPtr->fsStyle;
1735 if (lpTbInfo->dwMask & TBIF_TEXT) {
1736 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1737 lstrcpynWtoA (lpTbInfo->pszText,
1738 (LPWSTR)infoPtr->strings[btnPtr->iString],
1739 lpTbInfo->cchText);
1742 return nIndex;
1746 static LRESULT
1747 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1749 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1750 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
1751 TBUTTON_INFO *btnPtr;
1752 INT nIndex;
1754 if (infoPtr == NULL)
1755 return -1;
1756 if (lpTbInfo == NULL)
1757 return -1;
1758 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
1759 return -1;
1761 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1762 if (nIndex == -1)
1763 return -1;
1765 btnPtr = &infoPtr->buttons[nIndex];
1767 if (lpTbInfo->dwMask & TBIF_COMMAND)
1768 lpTbInfo->idCommand = btnPtr->idCommand;
1769 if (lpTbInfo->dwMask & TBIF_IMAGE)
1770 lpTbInfo->iImage = btnPtr->iBitmap;
1771 if (lpTbInfo->dwMask & TBIF_LPARAM)
1772 lpTbInfo->lParam = btnPtr->dwData;
1773 if (lpTbInfo->dwMask & TBIF_SIZE)
1774 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1775 if (lpTbInfo->dwMask & TBIF_STATE)
1776 lpTbInfo->fsState = btnPtr->fsState;
1777 if (lpTbInfo->dwMask & TBIF_STYLE)
1778 lpTbInfo->fsStyle = btnPtr->fsStyle;
1779 if (lpTbInfo->dwMask & TBIF_TEXT) {
1780 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1781 lstrcpynW (lpTbInfo->pszText,
1782 (LPWSTR)infoPtr->strings[btnPtr->iString],
1783 lpTbInfo->cchText);
1786 return nIndex;
1790 static LRESULT
1791 TOOLBAR_GetButtonSize (HWND hwnd)
1793 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1795 return MAKELONG((WORD)infoPtr->nButtonWidth,
1796 (WORD)infoPtr->nButtonHeight);
1800 static LRESULT
1801 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1803 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1804 INT nIndex, nStringIndex;
1806 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1807 if (nIndex == -1)
1808 return -1;
1810 nStringIndex = infoPtr->buttons[nIndex].iString;
1812 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1814 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1815 return -1;
1817 if (lParam == 0)
1818 return -1;
1820 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1822 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1826 static LRESULT
1827 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1829 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1830 INT nIndex, nStringIndex;
1832 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1833 if (nIndex == -1)
1834 return -1;
1836 nStringIndex = infoPtr->buttons[nIndex].iString;
1838 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1840 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1841 return -1;
1843 if (lParam == 0)
1844 return -1;
1846 lstrcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1848 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1852 /* << TOOLBAR_GetColorScheme >> */
1855 static LRESULT
1856 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1858 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1860 return (LRESULT)infoPtr->himlDis;
1864 inline static LRESULT
1865 TOOLBAR_GetExtendedStyle (HWND hwnd)
1867 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1869 return infoPtr->dwExStyle;
1873 static LRESULT
1874 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1876 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1878 return (LRESULT)infoPtr->himlHot;
1882 static LRESULT
1883 TOOLBAR_GetHotItem (HWND hwnd)
1885 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1887 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
1888 return -1;
1890 if (infoPtr->nHotItem < 0)
1891 return -1;
1893 return (LRESULT)infoPtr->nHotItem;
1897 static LRESULT
1898 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1900 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1902 return (LRESULT)infoPtr->himlDef;
1906 /* << TOOLBAR_GetInsertMark >> */
1907 /* << TOOLBAR_GetInsertMarkColor >> */
1910 static LRESULT
1911 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1913 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1914 TBUTTON_INFO *btnPtr;
1915 LPRECT lpRect;
1916 INT nIndex;
1918 if (infoPtr == NULL)
1919 return FALSE;
1920 nIndex = (INT)wParam;
1921 btnPtr = &infoPtr->buttons[nIndex];
1922 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1923 return FALSE;
1924 lpRect = (LPRECT)lParam;
1925 if (lpRect == NULL)
1926 return FALSE;
1927 if (btnPtr->fsState & TBSTATE_HIDDEN)
1928 return FALSE;
1930 TOOLBAR_CalcToolbar( hwnd );
1932 lpRect->left = btnPtr->rect.left;
1933 lpRect->right = btnPtr->rect.right;
1934 lpRect->bottom = btnPtr->rect.bottom;
1935 lpRect->top = btnPtr->rect.top;
1937 return TRUE;
1941 static LRESULT
1942 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1944 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1945 LPSIZE lpSize = (LPSIZE)lParam;
1947 if (lpSize == NULL)
1948 return FALSE;
1950 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
1951 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
1953 TRACE("maximum size %d x %d\n",
1954 infoPtr->rcBound.right - infoPtr->rcBound.left,
1955 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
1957 return TRUE;
1961 /* << TOOLBAR_GetObject >> */
1962 /* << TOOLBAR_GetPadding >> */
1965 static LRESULT
1966 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1968 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1969 TBUTTON_INFO *btnPtr;
1970 LPRECT lpRect;
1971 INT nIndex;
1973 if (infoPtr == NULL)
1974 return FALSE;
1975 nIndex = (INT)wParam;
1976 btnPtr = &infoPtr->buttons[nIndex];
1977 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1978 return FALSE;
1979 lpRect = (LPRECT)lParam;
1980 if (lpRect == NULL)
1981 return FALSE;
1983 lpRect->left = btnPtr->rect.left;
1984 lpRect->right = btnPtr->rect.right;
1985 lpRect->bottom = btnPtr->rect.bottom;
1986 lpRect->top = btnPtr->rect.top;
1988 return TRUE;
1992 static LRESULT
1993 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
1995 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1997 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
1998 return infoPtr->nRows;
1999 else
2000 return 1;
2004 static LRESULT
2005 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2007 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2008 INT nIndex;
2010 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2011 if (nIndex == -1)
2012 return -1;
2014 return infoPtr->buttons[nIndex].fsState;
2018 static LRESULT
2019 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2021 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2022 INT nIndex;
2024 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2025 if (nIndex == -1)
2026 return -1;
2028 return infoPtr->buttons[nIndex].fsStyle;
2032 static LRESULT
2033 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2035 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2037 if (infoPtr == NULL)
2038 return 0;
2040 return infoPtr->nMaxTextRows;
2044 static LRESULT
2045 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2047 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2049 if (infoPtr == NULL)
2050 return 0;
2051 return infoPtr->hwndToolTip;
2055 static LRESULT
2056 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2058 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2060 TRACE("%s hwnd=0x%x stub!\n",
2061 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2063 return infoPtr->bUnicode;
2067 inline static LRESULT
2068 TOOLBAR_GetVersion (HWND hwnd)
2070 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2071 return infoPtr->iVersion;
2075 static LRESULT
2076 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2078 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2079 TBUTTON_INFO *btnPtr;
2080 INT nIndex;
2082 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2083 if (nIndex == -1)
2084 return FALSE;
2086 btnPtr = &infoPtr->buttons[nIndex];
2087 if (LOWORD(lParam) == FALSE)
2088 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2089 else
2090 btnPtr->fsState |= TBSTATE_HIDDEN;
2092 TOOLBAR_CalcToolbar (hwnd);
2094 InvalidateRect (hwnd, NULL, TRUE);
2096 return TRUE;
2100 inline static LRESULT
2101 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2103 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2107 static LRESULT
2108 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2110 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2111 TBUTTON_INFO *btnPtr;
2112 INT nIndex;
2114 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2115 if (nIndex == -1)
2116 return FALSE;
2118 btnPtr = &infoPtr->buttons[nIndex];
2119 if (LOWORD(lParam) == FALSE)
2120 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2121 else
2122 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2124 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2125 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2127 return TRUE;
2131 static LRESULT
2132 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2134 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2135 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2136 INT nIndex = (INT)wParam;
2137 TBUTTON_INFO *oldButtons;
2139 if (lpTbb == NULL)
2140 return FALSE;
2142 if (nIndex == -1) {
2143 /* EPP: this seems to be an undocumented call (from my IE4)
2144 * I assume in that case that:
2145 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2146 * - index of insertion is at the end of existing buttons
2147 * I only see this happen with nIndex == -1, but it could have a special
2148 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2150 int len = lstrlenA((char*)lpTbb->iString) + 2;
2151 LPSTR ptr = COMCTL32_Alloc(len);
2153 nIndex = infoPtr->nNumButtons;
2154 strcpy(ptr, (char*)lpTbb->iString);
2155 ptr[len - 1] = 0; /* ended by two '\0' */
2156 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2157 COMCTL32_Free(ptr);
2159 } else if (nIndex < 0)
2160 return FALSE;
2162 TRACE("inserting button index=%d\n", nIndex);
2163 if (nIndex > infoPtr->nNumButtons) {
2164 nIndex = infoPtr->nNumButtons;
2165 TRACE("adjust index=%d\n", nIndex);
2168 oldButtons = infoPtr->buttons;
2169 infoPtr->nNumButtons++;
2170 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2171 /* pre insert copy */
2172 if (nIndex > 0) {
2173 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2174 nIndex * sizeof(TBUTTON_INFO));
2177 /* insert new button */
2178 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2179 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2180 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2181 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2182 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2183 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2185 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2186 TTTOOLINFOA ti;
2188 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2189 ti.cbSize = sizeof (TTTOOLINFOA);
2190 ti.hwnd = hwnd;
2191 ti.uId = lpTbb->idCommand;
2192 ti.hinst = 0;
2193 ti.lpszText = LPSTR_TEXTCALLBACKA;
2195 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2196 0, (LPARAM)&ti);
2199 /* post insert copy */
2200 if (nIndex < infoPtr->nNumButtons - 1) {
2201 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2202 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2205 COMCTL32_Free (oldButtons);
2207 TOOLBAR_CalcToolbar (hwnd);
2209 InvalidateRect (hwnd, NULL, FALSE);
2211 return TRUE;
2215 static LRESULT
2216 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2218 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2219 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2220 INT nIndex = (INT)wParam;
2221 TBUTTON_INFO *oldButtons;
2223 if (lpTbb == NULL)
2224 return FALSE;
2225 if (nIndex < 0)
2226 return FALSE;
2228 TRACE("inserting button index=%d\n", nIndex);
2229 if (nIndex > infoPtr->nNumButtons) {
2230 nIndex = infoPtr->nNumButtons;
2231 TRACE("adjust index=%d\n", nIndex);
2234 oldButtons = infoPtr->buttons;
2235 infoPtr->nNumButtons++;
2236 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2237 /* pre insert copy */
2238 if (nIndex > 0) {
2239 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2240 nIndex * sizeof(TBUTTON_INFO));
2243 /* insert new button */
2244 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2245 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2246 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2247 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2248 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2249 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2251 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2252 TTTOOLINFOW ti;
2254 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2255 ti.cbSize = sizeof (TTTOOLINFOW);
2256 ti.hwnd = hwnd;
2257 ti.uId = lpTbb->idCommand;
2258 ti.hinst = 0;
2259 ti.lpszText = LPSTR_TEXTCALLBACKW;
2261 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2262 0, (LPARAM)&ti);
2265 /* post insert copy */
2266 if (nIndex < infoPtr->nNumButtons - 1) {
2267 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2268 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2271 COMCTL32_Free (oldButtons);
2273 TOOLBAR_CalcToolbar (hwnd);
2275 InvalidateRect (hwnd, NULL, FALSE);
2277 return TRUE;
2281 /* << TOOLBAR_InsertMarkHitTest >> */
2284 static LRESULT
2285 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2287 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2288 INT nIndex;
2290 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2291 if (nIndex == -1)
2292 return FALSE;
2294 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2298 static LRESULT
2299 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2301 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2302 INT nIndex;
2304 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2305 if (nIndex == -1)
2306 return FALSE;
2308 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2312 static LRESULT
2313 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2315 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2316 INT nIndex;
2318 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2319 if (nIndex == -1)
2320 return FALSE;
2322 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2326 static LRESULT
2327 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2329 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2330 INT nIndex;
2332 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2333 if (nIndex == -1)
2334 return FALSE;
2336 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2340 static LRESULT
2341 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2343 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2344 INT nIndex;
2346 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2347 if (nIndex == -1)
2348 return FALSE;
2350 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2354 static LRESULT
2355 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2357 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2358 INT nIndex;
2360 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2361 if (nIndex == -1)
2362 return FALSE;
2364 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2368 /* << TOOLBAR_LoadImages >> */
2369 /* << TOOLBAR_MapAccelerator >> */
2370 /* << TOOLBAR_MarkButton >> */
2371 /* << TOOLBAR_MoveButton >> */
2374 static LRESULT
2375 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2377 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2378 TBUTTON_INFO *btnPtr;
2379 INT nIndex;
2381 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2382 if (nIndex == -1)
2383 return FALSE;
2385 btnPtr = &infoPtr->buttons[nIndex];
2386 if (LOWORD(lParam) == FALSE)
2387 btnPtr->fsState &= ~TBSTATE_PRESSED;
2388 else
2389 btnPtr->fsState |= TBSTATE_PRESSED;
2391 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2392 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2394 return TRUE;
2398 /* << TOOLBAR_ReplaceBitmap >> */
2401 static LRESULT
2402 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2404 #if 0
2405 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2406 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2408 if (lpSave == NULL) return 0;
2410 if ((BOOL)wParam) {
2411 /* save toolbar information */
2412 FIXME("save to \"%s\" \"%s\"\n",
2413 lpSave->pszSubKey, lpSave->pszValueName);
2417 else {
2418 /* restore toolbar information */
2420 FIXME("restore from \"%s\" \"%s\"\n",
2421 lpSave->pszSubKey, lpSave->pszValueName);
2425 #endif
2427 return 0;
2431 static LRESULT
2432 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2434 #if 0
2435 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2436 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2438 if (lpSave == NULL)
2439 return 0;
2441 if ((BOOL)wParam) {
2442 /* save toolbar information */
2443 FIXME("save to \"%s\" \"%s\"\n",
2444 lpSave->pszSubKey, lpSave->pszValueName);
2448 else {
2449 /* restore toolbar information */
2451 FIXME("restore from \"%s\" \"%s\"\n",
2452 lpSave->pszSubKey, lpSave->pszValueName);
2456 #endif
2458 return 0;
2462 static LRESULT
2463 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2465 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2466 BOOL bOldAnchor = infoPtr->bAnchor;
2468 infoPtr->bAnchor = (BOOL)wParam;
2470 return (LRESULT)bOldAnchor;
2474 static LRESULT
2475 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2477 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2479 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2480 return FALSE;
2482 /* Bitmap size can only be set before adding any button to the toolbar
2483 according to the documentation. */
2484 if( infoPtr->nNumButtons != 0 )
2485 return FALSE;
2487 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2488 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2490 return TRUE;
2494 static LRESULT
2495 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2497 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2498 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2499 TBUTTON_INFO *btnPtr;
2500 INT nIndex;
2502 if (lptbbi == NULL)
2503 return FALSE;
2504 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2505 return FALSE;
2507 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2508 if (nIndex == -1)
2509 return FALSE;
2511 btnPtr = &infoPtr->buttons[nIndex];
2512 if (lptbbi->dwMask & TBIF_COMMAND)
2513 btnPtr->idCommand = lptbbi->idCommand;
2514 if (lptbbi->dwMask & TBIF_IMAGE)
2515 btnPtr->iBitmap = lptbbi->iImage;
2516 if (lptbbi->dwMask & TBIF_LPARAM)
2517 btnPtr->dwData = lptbbi->lParam;
2518 /* if (lptbbi->dwMask & TBIF_SIZE) */
2519 /* btnPtr->cx = lptbbi->cx; */
2520 if (lptbbi->dwMask & TBIF_STATE)
2521 btnPtr->fsState = lptbbi->fsState;
2522 if (lptbbi->dwMask & TBIF_STYLE)
2523 btnPtr->fsStyle = lptbbi->fsStyle;
2525 if (lptbbi->dwMask & TBIF_TEXT) {
2526 if ((btnPtr->iString >= 0) ||
2527 (btnPtr->iString < infoPtr->nNumStrings)) {
2528 TRACE("Ooooooch\n");
2529 #if 0
2530 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2531 INT len = lstrlenA (lptbbi->pszText);
2532 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2533 #endif
2535 /* this is the ultimate sollution */
2536 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2540 return TRUE;
2544 static LRESULT
2545 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2547 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2548 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2549 TBUTTON_INFO *btnPtr;
2550 INT nIndex;
2552 if (lptbbi == NULL)
2553 return FALSE;
2554 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2555 return FALSE;
2557 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2558 if (nIndex == -1)
2559 return FALSE;
2561 btnPtr = &infoPtr->buttons[nIndex];
2562 if (lptbbi->dwMask & TBIF_COMMAND)
2563 btnPtr->idCommand = lptbbi->idCommand;
2564 if (lptbbi->dwMask & TBIF_IMAGE)
2565 btnPtr->iBitmap = lptbbi->iImage;
2566 if (lptbbi->dwMask & TBIF_LPARAM)
2567 btnPtr->dwData = lptbbi->lParam;
2568 /* if (lptbbi->dwMask & TBIF_SIZE) */
2569 /* btnPtr->cx = lptbbi->cx; */
2570 if (lptbbi->dwMask & TBIF_STATE)
2571 btnPtr->fsState = lptbbi->fsState;
2572 if (lptbbi->dwMask & TBIF_STYLE)
2573 btnPtr->fsStyle = lptbbi->fsStyle;
2575 if (lptbbi->dwMask & TBIF_TEXT) {
2576 if ((btnPtr->iString >= 0) ||
2577 (btnPtr->iString < infoPtr->nNumStrings)) {
2578 #if 0
2579 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2580 INT len = lstrlenW (lptbbi->pszText);
2581 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2582 #endif
2584 /* this is the ultimate sollution */
2585 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2589 return TRUE;
2593 static LRESULT
2594 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2596 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2598 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2599 return FALSE;
2601 /* Button size can only be set before adding any button to the toolbar
2602 according to the documentation. */
2603 if( infoPtr->nNumButtons != 0 )
2604 return FALSE;
2606 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2607 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2608 return TRUE;
2612 static LRESULT
2613 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2615 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2617 if (infoPtr == NULL)
2618 return FALSE;
2620 infoPtr->cxMin = (INT)LOWORD(lParam);
2621 infoPtr->cxMax = (INT)HIWORD(lParam);
2623 return TRUE;
2627 static LRESULT
2628 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2630 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2631 INT nIndex = (INT)wParam;
2633 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2634 return FALSE;
2636 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2638 if (infoPtr->hwndToolTip) {
2640 FIXME("change tool tip!\n");
2644 return TRUE;
2648 /* << TOOLBAR_SetColorScheme >> */
2651 static LRESULT
2652 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2654 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2655 HIMAGELIST himlTemp;
2658 himlTemp = infoPtr->himlDis;
2659 infoPtr->himlDis = (HIMAGELIST)lParam;
2661 /* FIXME: redraw ? */
2663 return (LRESULT)himlTemp;
2667 static LRESULT
2668 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2670 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2671 DWORD dwTemp;
2673 dwTemp = infoPtr->dwDTFlags;
2674 infoPtr->dwDTFlags =
2675 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2677 return (LRESULT)dwTemp;
2681 static LRESULT
2682 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2684 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2685 DWORD dwTemp;
2687 dwTemp = infoPtr->dwExStyle;
2688 infoPtr->dwExStyle = (DWORD)lParam;
2690 return (LRESULT)dwTemp;
2694 static LRESULT
2695 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2697 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2698 HIMAGELIST himlTemp;
2700 himlTemp = infoPtr->himlHot;
2701 infoPtr->himlHot = (HIMAGELIST)lParam;
2703 /* FIXME: redraw ? */
2705 return (LRESULT)himlTemp;
2709 static LRESULT
2710 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
2712 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2713 INT nOldHotItem = infoPtr->nHotItem;
2715 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
2717 infoPtr->nHotItem = (INT)wParam;
2719 /* FIXME: What else must be done ??? */
2723 if (nOldHotItem < 0)
2724 return -1;
2726 return (LRESULT)nOldHotItem;
2730 static LRESULT
2731 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2733 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2734 HIMAGELIST himlTemp;
2736 himlTemp = infoPtr->himlDef;
2737 infoPtr->himlDef = (HIMAGELIST)lParam;
2739 /* FIXME: redraw ? */
2741 return (LRESULT)himlTemp;
2745 static LRESULT
2746 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2748 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2750 infoPtr->nIndent = (INT)wParam;
2752 TOOLBAR_CalcToolbar (hwnd);
2754 InvalidateRect(hwnd, NULL, FALSE);
2756 return TRUE;
2760 /* << TOOLBAR_SetInsertMark >> */
2763 static LRESULT
2764 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2766 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2768 infoPtr->clrInsertMark = (COLORREF)lParam;
2770 /* FIXME : redraw ??*/
2772 return 0;
2776 static LRESULT
2777 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2779 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2781 if (infoPtr == NULL)
2782 return FALSE;
2784 infoPtr->nMaxTextRows = (INT)wParam;
2786 return TRUE;
2790 /* << TOOLBAR_SetPadding >> */
2793 static LRESULT
2794 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2796 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2797 HWND hwndOldNotify;
2799 if (infoPtr == NULL)
2800 return 0;
2801 hwndOldNotify = infoPtr->hwndNotify;
2802 infoPtr->hwndNotify = (HWND)wParam;
2804 return hwndOldNotify;
2808 static LRESULT
2809 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2811 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2812 LPRECT lprc = (LPRECT)lParam;
2814 if (LOWORD(wParam) > 1) {
2816 FIXME("multiple rows not supported!\n");
2820 /* recalculate toolbar */
2821 TOOLBAR_CalcToolbar (hwnd);
2823 /* return bounding rectangle */
2824 if (lprc) {
2825 lprc->left = infoPtr->rcBound.left;
2826 lprc->right = infoPtr->rcBound.right;
2827 lprc->top = infoPtr->rcBound.top;
2828 lprc->bottom = infoPtr->rcBound.bottom;
2831 /* repaint toolbar */
2832 InvalidateRect(hwnd, NULL, FALSE);
2834 return 0;
2838 static LRESULT
2839 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2841 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2842 TBUTTON_INFO *btnPtr;
2843 INT nIndex;
2845 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2846 if (nIndex == -1)
2847 return FALSE;
2849 btnPtr = &infoPtr->buttons[nIndex];
2850 btnPtr->fsState = LOWORD(lParam);
2852 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2853 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2855 return TRUE;
2859 static LRESULT
2860 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2862 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2863 TBUTTON_INFO *btnPtr;
2864 INT nIndex;
2866 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2867 if (nIndex == -1)
2868 return FALSE;
2870 btnPtr = &infoPtr->buttons[nIndex];
2871 btnPtr->fsStyle = LOWORD(lParam);
2873 RedrawWindow(hwnd,&btnPtr->rect,NULL,
2874 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
2876 if (infoPtr->hwndToolTip) {
2878 FIXME("change tool tip!\n");
2882 return TRUE;
2886 inline static LRESULT
2887 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2889 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2891 if (infoPtr == NULL)
2892 return 0;
2893 infoPtr->hwndToolTip = (HWND)wParam;
2894 return 0;
2898 static LRESULT
2899 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2901 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2902 BOOL bTemp;
2904 TRACE("%s hwnd=0x%04x stub!\n",
2905 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
2907 bTemp = infoPtr->bUnicode;
2908 infoPtr->bUnicode = (BOOL)wParam;
2910 return bTemp;
2914 static LRESULT
2915 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
2917 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2918 INT iOldVersion = infoPtr->iVersion;
2920 infoPtr->iVersion = iVersion;
2922 return iOldVersion;
2926 static LRESULT
2927 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
2929 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2930 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2931 LOGFONTA logFont;
2933 /* initialize info structure */
2934 infoPtr->nButtonHeight = 22;
2935 infoPtr->nButtonWidth = 24;
2936 infoPtr->nBitmapHeight = 15;
2937 infoPtr->nBitmapWidth = 16;
2939 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
2940 infoPtr->nRows = 1;
2941 infoPtr->nMaxTextRows = 1;
2942 infoPtr->cxMin = -1;
2943 infoPtr->cxMax = -1;
2945 infoPtr->bCaptured = FALSE;
2946 infoPtr->bUnicode = IsWindowUnicode (hwnd);
2947 infoPtr->nButtonDown = -1;
2948 infoPtr->nOldHit = -1;
2949 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
2950 infoPtr->hwndNotify = GetParent (hwnd);
2951 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
2952 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
2953 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
2954 infoPtr->iVersion = 0;
2956 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
2957 infoPtr->hFont = CreateFontIndirectA (&logFont);
2959 if (dwStyle & TBSTYLE_TOOLTIPS) {
2960 /* Create tooltip control */
2961 infoPtr->hwndToolTip =
2962 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
2963 CW_USEDEFAULT, CW_USEDEFAULT,
2964 CW_USEDEFAULT, CW_USEDEFAULT,
2965 hwnd, 0, 0, 0);
2967 /* Send NM_TOOLTIPSCREATED notification */
2968 if (infoPtr->hwndToolTip) {
2969 NMTOOLTIPSCREATED nmttc;
2971 nmttc.hdr.hwndFrom = hwnd;
2972 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
2973 nmttc.hdr.code = NM_TOOLTIPSCREATED;
2974 nmttc.hwndToolTips = infoPtr->hwndToolTip;
2976 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
2977 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
2981 return 0;
2985 static LRESULT
2986 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
2988 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2990 /* delete tooltip control */
2991 if (infoPtr->hwndToolTip)
2992 DestroyWindow (infoPtr->hwndToolTip);
2994 /* delete button data */
2995 if (infoPtr->buttons)
2996 COMCTL32_Free (infoPtr->buttons);
2998 /* delete strings */
2999 if (infoPtr->strings) {
3000 INT i;
3001 for (i = 0; i < infoPtr->nNumStrings; i++)
3002 if (infoPtr->strings[i])
3003 COMCTL32_Free (infoPtr->strings[i]);
3005 COMCTL32_Free (infoPtr->strings);
3008 /* destroy internal image list */
3009 if (infoPtr->himlInt)
3010 ImageList_Destroy (infoPtr->himlInt);
3012 /* delete default font */
3013 if (infoPtr->hFont)
3014 DeleteObject (infoPtr->hFont);
3016 /* free toolbar info data */
3017 COMCTL32_Free (infoPtr);
3018 SetWindowLongA (hwnd, 0, 0);
3020 return 0;
3024 static LRESULT
3025 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3027 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3029 if (infoPtr->bTransparent)
3030 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3032 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3036 static LRESULT
3037 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3039 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3041 return infoPtr->hFont;
3045 static LRESULT
3046 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3048 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3049 TBUTTON_INFO *btnPtr;
3050 POINT pt;
3051 INT nHit;
3053 pt.x = (INT)LOWORD(lParam);
3054 pt.y = (INT)HIWORD(lParam);
3055 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3057 if (nHit >= 0) {
3058 btnPtr = &infoPtr->buttons[nHit];
3059 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3060 return 0;
3061 SetCapture (hwnd);
3062 infoPtr->bCaptured = TRUE;
3063 infoPtr->nButtonDown = nHit;
3065 btnPtr->fsState |= TBSTATE_PRESSED;
3067 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3068 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3070 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3071 TOOLBAR_Customize (hwnd);
3073 return 0;
3077 static LRESULT
3078 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3080 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3081 TBUTTON_INFO *btnPtr;
3082 POINT pt;
3083 INT nHit;
3085 if (infoPtr->hwndToolTip)
3086 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3087 WM_LBUTTONDOWN, wParam, lParam);
3089 pt.x = (INT)LOWORD(lParam);
3090 pt.y = (INT)HIWORD(lParam);
3091 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3093 if (nHit >= 0) {
3094 btnPtr = &infoPtr->buttons[nHit];
3095 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3096 return 0;
3098 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
3100 NMTOOLBARA nmtb;
3102 nmtb.hdr.hwndFrom = hwnd;
3103 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3104 nmtb.hdr.code = TBN_DROPDOWN;
3105 nmtb.iItem = btnPtr->idCommand;
3107 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3108 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3111 SetCapture (hwnd);
3112 infoPtr->bCaptured = TRUE;
3113 infoPtr->nButtonDown = nHit;
3114 infoPtr->nOldHit = nHit;
3116 btnPtr->fsState |= TBSTATE_PRESSED;
3117 btnPtr->bHot = FALSE;
3119 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3120 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3123 return 0;
3126 static LRESULT
3127 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3129 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3130 TBUTTON_INFO *btnPtr;
3131 POINT pt;
3132 INT nHit;
3133 INT nOldIndex = -1;
3134 BOOL bSendMessage = TRUE;
3136 if (infoPtr->hwndToolTip)
3137 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3138 WM_LBUTTONUP, wParam, lParam);
3140 pt.x = (INT)LOWORD(lParam);
3141 pt.y = (INT)HIWORD(lParam);
3142 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3144 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3145 infoPtr->bCaptured = FALSE;
3146 ReleaseCapture ();
3147 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3148 btnPtr->fsState &= ~TBSTATE_PRESSED;
3150 if (nHit == infoPtr->nButtonDown) {
3151 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3152 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3153 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3154 infoPtr->nButtonDown);
3155 if (nOldIndex == infoPtr->nButtonDown)
3156 bSendMessage = FALSE;
3157 if ((nOldIndex != infoPtr->nButtonDown) &&
3158 (nOldIndex != -1))
3159 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3160 btnPtr->fsState |= TBSTATE_CHECKED;
3162 else {
3163 if (btnPtr->fsState & TBSTATE_CHECKED)
3164 btnPtr->fsState &= ~TBSTATE_CHECKED;
3165 else
3166 btnPtr->fsState |= TBSTATE_CHECKED;
3170 else
3171 bSendMessage = FALSE;
3173 if (nOldIndex != -1)
3174 RedrawWindow(hwnd,&infoPtr->buttons[nOldIndex].rect,NULL,
3175 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3176 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3177 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3179 if (bSendMessage) {
3180 SendMessageA (GetParent(hwnd), WM_COMMAND,
3181 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3183 // if ((GetWindowLongA(hwnd, GWL_STYLE) & TBSTYLE_DROPDOWN) ||
3184 // (btnPtr->fsStyle & 0x08/* BTNS_DROPDOWN */)) {
3186 * This appears to be an error. Instead of checking the style of the
3187 * button in question wine was checking the style of the toolbar
3188 * itself. This caused a number of strange behaviors. In my
3189 * invistigation i think the whole dropdown thing is still fairly
3190 * broken. but this helps fix some of the problems.
3193 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
3194 NMTOOLBARW nmtb;
3196 nmtb.hdr.hwndFrom = hwnd;
3197 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3198 nmtb.hdr.code = TBN_DROPDOWN;
3199 nmtb.iItem = nHit;
3200 /* nmtb.tbButton not used with TBN_DROPDOWN */
3201 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) {
3202 nmtb.pszText = infoPtr->strings[btnPtr->iString];
3203 nmtb.cchText = lstrlenW(nmtb.pszText);
3204 } else {
3205 nmtb.pszText = NULL;
3206 nmtb.cchText = 0;
3208 nmtb.rcButton = btnPtr->rect;
3210 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
3211 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3214 infoPtr->nButtonDown = -1;
3215 infoPtr->nOldHit = -1;
3218 return 0;
3221 static LRESULT
3222 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3224 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3225 TBUTTON_INFO *hotBtnPtr;
3227 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3229 /* Redraw the button if the last button we were over is the hot button and it
3230 is enabled */
3231 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3233 hotBtnPtr->bHot = FALSE;
3235 InvalidateRect (hwnd, &hotBtnPtr->rect, TRUE);
3238 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3239 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3241 return TRUE;
3244 static LRESULT
3245 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3247 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3248 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3249 POINT pt;
3250 INT nHit;
3251 TRACKMOUSEEVENT trackinfo;
3253 /* fill in the TRACKMOUSEEVENT struct */
3254 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3255 trackinfo.dwFlags = TME_QUERY;
3256 trackinfo.hwndTrack = hwnd;
3257 trackinfo.dwHoverTime = HOVER_DEFAULT;
3259 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3260 _TrackMouseEvent(&trackinfo);
3262 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3263 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3264 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3266 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3267 /* and can properly deactivate the hot toolbar button */
3268 _TrackMouseEvent(&trackinfo);
3271 if (infoPtr->hwndToolTip)
3272 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3273 WM_MOUSEMOVE, wParam, lParam);
3275 pt.x = (INT)LOWORD(lParam);
3276 pt.y = (INT)HIWORD(lParam);
3278 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3280 if (infoPtr->nOldHit != nHit)
3282 /* Remove the effect of an old hot button if the button was enabled and was
3283 drawn with the hot button effect */
3284 if(infoPtr->nOldHit == infoPtr->nHotItem &&
3285 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3287 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3288 oldBtnPtr->bHot = FALSE;
3290 InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
3293 /* It's not a separator or in nowhere. It's a hot button. */
3294 if (nHit >= 0)
3296 btnPtr = &infoPtr->buttons[nHit];
3297 btnPtr->bHot = TRUE;
3299 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3300 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3302 infoPtr->nHotItem = nHit;
3305 if (infoPtr->bCaptured) {
3306 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3307 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3308 btnPtr->fsState &= ~TBSTATE_PRESSED;
3309 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3310 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3312 else if (nHit == infoPtr->nButtonDown) {
3313 btnPtr->fsState |= TBSTATE_PRESSED;
3314 RedrawWindow(hwnd,&btnPtr->rect,NULL,
3315 RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3318 infoPtr->nOldHit = nHit;
3320 return 0;
3324 inline static LRESULT
3325 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3327 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3328 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3329 /* else */
3330 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3334 inline static LRESULT
3335 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3337 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3338 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3340 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3344 static LRESULT
3345 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3347 TOOLBAR_INFO *infoPtr;
3349 /* allocate memory for info structure */
3350 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3351 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3353 /* paranoid!! */
3354 infoPtr->dwStructSize = sizeof(TBBUTTON);
3356 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3357 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3358 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3359 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3362 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3366 static LRESULT
3367 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3369 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3370 RECT rcWindow;
3371 HDC hdc;
3373 if (dwStyle & WS_MINIMIZE)
3374 return 0; /* Nothing to do */
3376 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3378 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3379 return 0;
3381 if (!(dwStyle & CCS_NODIVIDER))
3383 GetWindowRect (hwnd, &rcWindow);
3384 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3385 if( dwStyle & WS_BORDER )
3386 OffsetRect (&rcWindow, 1, 1);
3387 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3390 ReleaseDC( hwnd, hdc );
3392 return 0;
3396 inline static LRESULT
3397 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3399 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3400 LPNMHDR lpnmh = (LPNMHDR)lParam;
3402 TRACE("passing WM_NOTIFY!\n");
3404 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3405 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3407 #if 0
3408 if (lpnmh->code == TTN_GETDISPINFOA) {
3409 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3411 FIXME("retrieving ASCII string\n");
3414 else if (lpnmh->code == TTN_GETDISPINFOW) {
3415 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3417 FIXME("retrieving UNICODE string\n");
3420 #endif
3423 return 0;
3427 static LRESULT
3428 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3430 HDC hdc;
3431 PAINTSTRUCT ps;
3433 TOOLBAR_CalcToolbar( hwnd );
3434 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
3435 TOOLBAR_Refresh (hwnd, hdc);
3436 if (!wParam)
3437 EndPaint (hwnd, &ps);
3438 return 0;
3442 static LRESULT
3443 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3445 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3446 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3447 RECT parent_rect;
3448 RECT window_rect;
3449 HWND parent;
3450 INT x, y;
3451 INT cx, cy;
3452 INT flags;
3453 UINT uPosFlags = 0;
3455 /* Resize deadlock check */
3456 if (infoPtr->bAutoSize) {
3457 infoPtr->bAutoSize = FALSE;
3458 return 0;
3461 flags = (INT) wParam;
3463 /* FIXME for flags =
3464 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3467 TRACE("sizing toolbar!\n");
3469 if (flags == SIZE_RESTORED) {
3470 /* width and height don't apply */
3471 parent = GetParent (hwnd);
3472 GetClientRect(parent, &parent_rect);
3473 x = parent_rect.left;
3474 y = parent_rect.top;
3476 if (dwStyle & CCS_NORESIZE) {
3477 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3479 /* FIXME */
3480 /* infoPtr->nWidth = parent_rect.right - parent_rect.left; */
3481 cy = infoPtr->nHeight;
3482 cx = infoPtr->nWidth;
3483 TOOLBAR_CalcToolbar (hwnd);
3484 infoPtr->nWidth = cx;
3485 infoPtr->nHeight = cy;
3487 else {
3488 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3489 TOOLBAR_CalcToolbar (hwnd);
3490 cy = infoPtr->nHeight;
3491 cx = infoPtr->nWidth;
3493 if (dwStyle & CCS_NOMOVEY) {
3494 GetWindowRect(hwnd, &window_rect);
3495 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3496 y = window_rect.top;
3500 if (dwStyle & CCS_NOPARENTALIGN) {
3501 uPosFlags |= SWP_NOMOVE;
3502 cy = infoPtr->nHeight;
3503 cx = infoPtr->nWidth;
3506 if (!(dwStyle & CCS_NODIVIDER))
3507 cy += GetSystemMetrics(SM_CYEDGE);
3509 if (dwStyle & WS_BORDER)
3511 x = y = 1;
3512 cy += GetSystemMetrics(SM_CYEDGE);
3513 cx += GetSystemMetrics(SM_CYEDGE);
3516 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3517 cx, cy, uPosFlags | SWP_NOZORDER);
3519 return 0;
3523 static LRESULT
3524 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3526 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3528 if (nType == GWL_STYLE) {
3529 if (lpStyle->styleNew & TBSTYLE_LIST) {
3530 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3532 else {
3533 infoPtr->dwDTFlags = DT_CENTER;
3537 TOOLBAR_AutoSize (hwnd);
3539 InvalidateRect(hwnd, NULL, FALSE);
3541 return 0;
3546 static LRESULT WINAPI
3547 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3550 switch (uMsg)
3552 case WM_DESTROY:
3553 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3555 case WM_NCCREATE:
3556 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3559 if (!TOOLBAR_GetInfoPtr (hwnd))
3561 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3564 switch (uMsg)
3566 case TB_ADDBITMAP:
3567 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3569 case TB_ADDBUTTONSA:
3570 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3572 case TB_ADDBUTTONSW:
3573 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3575 case TB_ADDSTRINGA:
3576 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3578 case TB_ADDSTRINGW:
3579 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3581 case TB_AUTOSIZE:
3582 return TOOLBAR_AutoSize (hwnd);
3584 case TB_BUTTONCOUNT:
3585 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3587 case TB_BUTTONSTRUCTSIZE:
3588 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3590 case TB_CHANGEBITMAP:
3591 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3593 case TB_CHECKBUTTON:
3594 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3596 case TB_COMMANDTOINDEX:
3597 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3599 case TB_CUSTOMIZE:
3600 return TOOLBAR_Customize (hwnd);
3602 case TB_DELETEBUTTON:
3603 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3605 case TB_ENABLEBUTTON:
3606 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3608 case TB_GETANCHORHIGHLIGHT:
3609 return TOOLBAR_GetAnchorHighlight (hwnd);
3611 case TB_GETBITMAP:
3612 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3614 case TB_GETBITMAPFLAGS:
3615 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3617 case TB_GETBUTTON:
3618 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3620 case TB_GETBUTTONINFOA:
3621 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3623 case TB_GETBUTTONINFOW:
3624 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3626 case TB_GETBUTTONSIZE:
3627 return TOOLBAR_GetButtonSize (hwnd);
3629 case TB_GETBUTTONTEXTA:
3630 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3632 case TB_GETBUTTONTEXTW:
3633 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
3635 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
3637 case TB_GETDISABLEDIMAGELIST:
3638 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3640 case TB_GETEXTENDEDSTYLE:
3641 return TOOLBAR_GetExtendedStyle (hwnd);
3643 case TB_GETHOTIMAGELIST:
3644 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3646 case TB_GETHOTITEM:
3647 return TOOLBAR_GetHotItem (hwnd);
3649 case TB_GETIMAGELIST:
3650 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3652 /* case TB_GETINSERTMARK: */ /* 4.71 */
3653 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
3655 case TB_GETITEMRECT:
3656 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3658 case TB_GETMAXSIZE:
3659 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3661 /* case TB_GETOBJECT: */ /* 4.71 */
3662 /* case TB_GETPADDING: */ /* 4.71 */
3664 case TB_GETRECT:
3665 return TOOLBAR_GetRect (hwnd, wParam, lParam);
3667 case TB_GETROWS:
3668 return TOOLBAR_GetRows (hwnd, wParam, lParam);
3670 case TB_GETSTATE:
3671 return TOOLBAR_GetState (hwnd, wParam, lParam);
3673 case TB_GETSTYLE:
3674 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3676 case TB_GETTEXTROWS:
3677 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3679 case TB_GETTOOLTIPS:
3680 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3682 case TB_GETUNICODEFORMAT:
3683 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3685 case CCM_GETVERSION:
3686 return TOOLBAR_GetVersion (hwnd);
3688 case TB_HIDEBUTTON:
3689 return TOOLBAR_HideButton (hwnd, wParam, lParam);
3691 case TB_HITTEST:
3692 return TOOLBAR_HitTest (hwnd, wParam, lParam);
3694 case TB_INDETERMINATE:
3695 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3697 case TB_INSERTBUTTONA:
3698 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3700 case TB_INSERTBUTTONW:
3701 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
3703 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
3705 case TB_ISBUTTONCHECKED:
3706 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3708 case TB_ISBUTTONENABLED:
3709 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3711 case TB_ISBUTTONHIDDEN:
3712 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3714 case TB_ISBUTTONHIGHLIGHTED:
3715 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3717 case TB_ISBUTTONINDETERMINATE:
3718 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3720 case TB_ISBUTTONPRESSED:
3721 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3723 case TB_LOADIMAGES: /* 4.70 */
3724 FIXME("missing standard imagelists\n");
3725 return 0;
3727 /* case TB_MAPACCELERATORA: */ /* 4.71 */
3728 /* case TB_MAPACCELERATORW: */ /* 4.71 */
3729 /* case TB_MARKBUTTON: */ /* 4.71 */
3730 /* case TB_MOVEBUTTON: */ /* 4.71 */
3732 case TB_PRESSBUTTON:
3733 return TOOLBAR_PressButton (hwnd, wParam, lParam);
3735 /* case TB_REPLACEBITMAP: */
3737 case TB_SAVERESTOREA:
3738 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3740 case TB_SAVERESTOREW:
3741 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
3743 case TB_SETANCHORHIGHLIGHT:
3744 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
3746 case TB_SETBITMAPSIZE:
3747 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3749 case TB_SETBUTTONINFOA:
3750 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3752 case TB_SETBUTTONINFOW:
3753 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
3755 case TB_SETBUTTONSIZE:
3756 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3758 case TB_SETBUTTONWIDTH:
3759 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3761 case TB_SETCMDID:
3762 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3764 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
3766 case TB_SETDISABLEDIMAGELIST:
3767 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3769 case TB_SETDRAWTEXTFLAGS:
3770 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3772 case TB_SETEXTENDEDSTYLE:
3773 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3775 case TB_SETHOTIMAGELIST:
3776 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3778 case TB_SETHOTITEM:
3779 return TOOLBAR_SetHotItem (hwnd, wParam);
3781 case TB_SETIMAGELIST:
3782 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3784 case TB_SETINDENT:
3785 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3787 /* case TB_SETINSERTMARK: */ /* 4.71 */
3789 case TB_SETINSERTMARKCOLOR:
3790 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3792 case TB_SETMAXTEXTROWS:
3793 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3795 /* case TB_SETPADDING: */ /* 4.71 */
3797 case TB_SETPARENT:
3798 return TOOLBAR_SetParent (hwnd, wParam, lParam);
3800 case TB_SETROWS:
3801 return TOOLBAR_SetRows (hwnd, wParam, lParam);
3803 case TB_SETSTATE:
3804 return TOOLBAR_SetState (hwnd, wParam, lParam);
3806 case TB_SETSTYLE:
3807 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3809 case TB_SETTOOLTIPS:
3810 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3812 case TB_SETUNICODEFORMAT:
3813 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3815 case CCM_SETVERSION:
3816 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
3819 /* case WM_CHAR: */
3821 case WM_CREATE:
3822 return TOOLBAR_Create (hwnd, wParam, lParam);
3824 case WM_ERASEBKGND:
3825 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
3827 case WM_GETFONT:
3828 return TOOLBAR_GetFont (hwnd, wParam, lParam);
3830 /* case WM_KEYDOWN: */
3831 /* case WM_KILLFOCUS: */
3833 case WM_LBUTTONDBLCLK:
3834 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
3836 case WM_LBUTTONDOWN:
3837 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
3839 case WM_LBUTTONUP:
3840 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
3842 case WM_MOUSEMOVE:
3843 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
3845 case WM_MOUSELEAVE:
3846 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
3848 case WM_NCACTIVATE:
3849 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
3851 case WM_NCCALCSIZE:
3852 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
3854 case WM_NCPAINT:
3855 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
3857 case WM_NOTIFY:
3858 return TOOLBAR_Notify (hwnd, wParam, lParam);
3860 /* case WM_NOTIFYFORMAT: */
3862 case WM_PAINT:
3863 return TOOLBAR_Paint (hwnd, wParam);
3865 case WM_SIZE:
3866 return TOOLBAR_Size (hwnd, wParam, lParam);
3868 case WM_STYLECHANGED:
3869 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
3871 /* case WM_SYSCOLORCHANGE: */
3873 /* case WM_WININICHANGE: */
3875 case WM_CHARTOITEM:
3876 case WM_COMMAND:
3877 case WM_DRAWITEM:
3878 case WM_MEASUREITEM:
3879 case WM_VKEYTOITEM:
3880 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
3882 default:
3883 if (uMsg >= WM_USER)
3884 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
3885 uMsg, wParam, lParam);
3886 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3888 return 0;
3892 VOID
3893 TOOLBAR_Register (void)
3895 WNDCLASSA wndClass;
3897 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
3898 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
3899 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
3900 wndClass.cbClsExtra = 0;
3901 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
3902 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
3903 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
3904 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
3906 RegisterClassA (&wndClass);
3910 VOID
3911 TOOLBAR_Unregister (void)
3913 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);