Fixed some visual toolbar bugs.
[wine.git] / dlls / comctl32 / toolbar.c
blob3bccd30bccdaf0cab75b6a9cea8761c75eec6031
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 "winuser.h"
31 #include "wingdi.h"
32 #include "commctrl.h"
33 #include "cache.h"
34 #include "comctl32.h"
35 #include "toolbar.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(toolbar)
40 #define SEPARATOR_WIDTH 8
41 #define TOP_BORDER 2
42 #define BOTTOM_BORDER 2
44 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
47 static void
48 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
50 INT x = (lpRect->left + lpRect->right) / 2 - 1;
51 INT yBottom = lpRect->bottom - 3;
52 INT yTop = lpRect->top + 1;
54 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
55 MoveToEx (hdc, x, yBottom, NULL);
56 LineTo (hdc, x, yTop);
57 x++;
58 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
59 MoveToEx (hdc, x, yBottom, NULL);
60 LineTo (hdc, x, yTop);
64 static void
65 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
66 HDC hdc, INT nState, DWORD dwStyle)
68 RECT rcText = btnPtr->rect;
69 HFONT hOldFont;
70 INT nOldBkMode;
71 COLORREF clrOld;
73 /* draw text */
74 if ((btnPtr->iString > -1) && (btnPtr->iString < infoPtr->nNumStrings)) {
75 InflateRect (&rcText, -3, -3);
76 if (dwStyle & TBSTYLE_LIST) {
77 rcText.left += infoPtr->nBitmapWidth;
79 else {
80 rcText.top += infoPtr->nBitmapHeight;
82 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
83 OffsetRect (&rcText, 1, 1);
85 hOldFont = SelectObject (hdc, infoPtr->hFont);
86 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
87 if (!(nState & TBSTATE_ENABLED)) {
88 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
89 OffsetRect (&rcText, 1, 1);
90 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
91 &rcText, infoPtr->dwDTFlags);
92 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
93 OffsetRect (&rcText, -1, -1);
94 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
95 &rcText, infoPtr->dwDTFlags);
97 else if (nState & TBSTATE_INDETERMINATE) {
98 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
99 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
100 &rcText, infoPtr->dwDTFlags);
102 else {
103 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
104 DrawTextW (hdc, infoPtr->strings[btnPtr->iString], -1,
105 &rcText, infoPtr->dwDTFlags);
108 SetTextColor (hdc, clrOld);
109 SelectObject (hdc, hOldFont);
110 if (nOldBkMode != TRANSPARENT)
111 SetBkMode (hdc, nOldBkMode);
116 static void
117 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
119 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
120 INT cx = lpRect->right - lpRect->left;
121 INT cy = lpRect->bottom - lpRect->top;
122 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
123 SelectObject (hdc, hbr);
127 static void
128 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
129 HDC hdc, INT x, INT y)
131 /* FIXME: this function is a hack since it uses image list
132 internals directly */
134 HIMAGELIST himl = infoPtr->himlDef;
135 HBITMAP hbmMask;
136 HDC hdcImageList;
137 HDC hdcMask;
139 if (!himl)
140 return;
142 /* create new dc's */
143 hdcImageList = CreateCompatibleDC (0);
144 hdcMask = CreateCompatibleDC (0);
146 /* create new bitmap */
147 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
148 SelectObject (hdcMask, hbmMask);
150 /* copy the mask bitmap */
151 SelectObject (hdcImageList, himl->hbmMask);
152 SetBkColor (hdcImageList, RGB(255, 255, 255));
153 SetTextColor (hdcImageList, RGB(0, 0, 0));
154 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
155 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
157 #if 0
158 /* add white mask from image */
159 SelectObject (hdcImageList, himl->hbmImage);
160 SetBkColor (hdcImageList, RGB(0, 0, 0));
161 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
162 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
163 #endif
165 /* draw the new mask */
166 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
167 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
168 hdcMask, 0, 0, 0xB8074A);
170 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
171 BitBlt (hdc, x, y, himl->cx, himl->cy,
172 hdcMask, 0, 0, 0xB8074A);
174 DeleteObject (hbmMask);
175 DeleteDC (hdcMask);
176 DeleteDC (hdcImageList);
180 static void
181 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
183 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
184 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
185 RECT rc;
187 if (btnPtr->fsState & TBSTATE_HIDDEN)
188 return;
190 rc = btnPtr->rect;
192 /* separator */
193 if (btnPtr->fsStyle & TBSTYLE_SEP) {
194 if ((dwStyle & TBSTYLE_FLAT) && (btnPtr->iBitmap == 0))
195 TOOLBAR_DrawFlatSeparator (&rc, hdc);
196 return;
199 /* disabled */
200 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
201 if (!(dwStyle & TBSTYLE_FLAT))
202 DrawEdge (hdc, &rc, EDGE_RAISED,
203 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
205 if (infoPtr->himlDis)
206 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
207 rc.left+1, rc.top+1, ILD_NORMAL);
208 else
209 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
211 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
212 return;
215 /* pressed TBSTYLE_BUTTON */
216 if (btnPtr->fsState & TBSTATE_PRESSED) {
217 if (dwStyle & TBSTYLE_FLAT)
218 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
219 else
220 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
221 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
222 rc.left+2, rc.top+2, ILD_NORMAL);
223 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
224 return;
227 /* checked TBSTYLE_CHECK */
228 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
229 (btnPtr->fsState & TBSTATE_CHECKED)) {
230 if (dwStyle & TBSTYLE_FLAT)
231 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
232 BF_RECT | BF_MIDDLE | BF_ADJUST);
233 else
234 DrawEdge (hdc, &rc, EDGE_SUNKEN,
235 BF_RECT | BF_MIDDLE | BF_ADJUST);
237 TOOLBAR_DrawPattern (hdc, &rc);
239 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
240 rc.left+2, rc.top+2, ILD_NORMAL);
242 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
243 return;
246 /* indeterminate */
247 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
248 DrawEdge (hdc, &rc, EDGE_RAISED,
249 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
251 TOOLBAR_DrawPattern (hdc, &rc);
252 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
253 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
254 return;
257 /* normal state */
258 if (dwStyle & TBSTYLE_FLAT)
260 if (btnPtr->bHot)
261 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
262 if (btnPtr->bHot && infoPtr->himlHot)
263 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
264 rc.left +2, rc.top +2, ILD_NORMAL);
265 else
266 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
267 rc.left +2, rc.top +2, ILD_NORMAL);
269 else
271 DrawEdge (hdc, &rc, EDGE_RAISED,
272 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
274 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
275 rc.left+1, rc.top+1, ILD_NORMAL);
278 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
282 static void
283 TOOLBAR_Refresh (HWND hwnd, HDC hdc)
285 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
286 TBUTTON_INFO *btnPtr;
287 INT i;
289 /* draw buttons */
290 btnPtr = infoPtr->buttons;
291 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
292 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
296 static void
297 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
299 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
300 TBUTTON_INFO *btnPtr;
301 INT i;
302 HDC hdc;
303 HFONT hOldFont;
304 SIZE sz;
306 lpSize->cx = 0;
307 lpSize->cy = 0;
308 hdc = GetDC (0);
309 hOldFont = SelectObject (hdc, infoPtr->hFont);
311 btnPtr = infoPtr->buttons;
312 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
313 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
314 (btnPtr->iString > -1) &&
315 (btnPtr->iString < infoPtr->nNumStrings)) {
316 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
317 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), &sz);
318 if (sz.cx > lpSize->cx)
319 lpSize->cx = sz.cx;
320 if (sz.cy > lpSize->cy)
321 lpSize->cy = sz.cy;
325 SelectObject (hdc, hOldFont);
326 ReleaseDC (0, hdc);
328 TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
331 /***********************************************************************
332 * TOOLBAR_WrapToolbar
334 * This function walks through the buttons and seperators in the
335 * toolbar, and sets the TBSTATE_WRAP flag only on those items where
336 * wrapping should occur based on the width of the toolbar window.
337 * It does *not* calculate button placement itself. That task
338 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage
339 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
340 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
343 static void
344 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
346 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
347 TBUTTON_INFO *btnPtr;
348 INT x, cx, i, j;
349 RECT rc;
350 BOOL bWrap, bButtonWrap;
352 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
353 /* no layout is necessary. Applications may use this style */
354 /* to perform their own layout on the toolbar. */
355 if( !(dwStyle & TBSTYLE_WRAPABLE) )
356 return;
358 btnPtr = infoPtr->buttons;
359 x = infoPtr->nIndent;
361 GetClientRect( GetParent(hwnd), &rc );
362 infoPtr->nWidth = rc.right - rc.left;
363 bButtonWrap = FALSE;
365 for (i = 0; i < infoPtr->nNumButtons; i++ )
367 bWrap = FALSE;
368 btnPtr[i].fsState &= ~TBSTATE_WRAP;
370 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
371 continue;
373 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
374 /* it is the actual width of the separator. This is used for */
375 /* custom controls in toolbars. */
376 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
377 cx = (btnPtr[i].iBitmap > 0) ?
378 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
379 else
380 cx = infoPtr->nButtonWidth;
382 /* Two or more adjacent separators form a separator group. */
383 /* The first separator in a group should be wrapped to the */
384 /* next row if the previous wrapping is on a button. */
385 if( bButtonWrap &&
386 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
387 (i + 1 < infoPtr->nNumButtons ) &&
388 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
390 btnPtr[i].fsState |= TBSTATE_WRAP;
391 x = infoPtr->nIndent;
392 i++;
393 bButtonWrap = FALSE;
394 continue;
397 /* The layout makes sure the bitmap is visible, but not the button. */
398 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
399 > infoPtr->nWidth )
401 BOOL bFound = FALSE;
403 /* If the current button is a separator and not hidden, */
404 /* go to the next until it reaches a non separator. */
405 /* Wrap the last separator if it is before a button. */
406 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
407 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
408 i < infoPtr->nNumButtons )
410 i++;
411 bFound = TRUE;
414 if( bFound && i < infoPtr->nNumButtons )
416 i--;
417 btnPtr[i].fsState |= TBSTATE_WRAP;
418 x = infoPtr->nIndent;
419 bButtonWrap = FALSE;
420 continue;
422 else if ( i >= infoPtr->nNumButtons)
423 break;
425 /* If the current button is not a separator, find the last */
426 /* separator and wrap it. */
427 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
429 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
430 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
432 bFound = TRUE;
433 i = j;
434 x = infoPtr->nIndent;
435 btnPtr[j].fsState |= TBSTATE_WRAP;
436 bButtonWrap = FALSE;
437 break;
441 /* If no separator available for wrapping, wrap one of */
442 /* non-hidden previous button. */
443 if (!bFound)
445 for ( j = i - 1;
446 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
448 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
449 continue;
451 bFound = TRUE;
452 i = j;
453 x = infoPtr->nIndent;
454 btnPtr[j].fsState |= TBSTATE_WRAP;
455 bButtonWrap = TRUE;
456 break;
460 /* If all above failed, wrap the current button. */
461 if (!bFound)
463 btnPtr[i].fsState |= TBSTATE_WRAP;
464 bFound = TRUE;
465 x = infoPtr->nIndent;
466 if (btnPtr[i].fsState & TBSTYLE_SEP )
467 bButtonWrap = FALSE;
468 else
469 bButtonWrap = TRUE;
472 else
473 x += cx;
477 /***********************************************************************
478 * TOOLBAR_CalcToolbar
480 * This function calculates button and separator placement. It first
481 * calculates the button sizes, gets the toolbar window width and then
482 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
483 * on. It assigns a new location to each item and sends this location to
484 * the tooltip window if appropriate. Finally, it updates the rcBound
485 * rect and calculates the new required toolbar window height.
488 static void
489 TOOLBAR_CalcToolbar (HWND hwnd)
491 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
492 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
493 TBUTTON_INFO *btnPtr;
494 INT i, nRows, nSepRows;
495 INT x, y, cx, cy;
496 SIZE sizeString;
497 RECT rc;
498 BOOL bWrap;
500 TOOLBAR_CalcStrings (hwnd, &sizeString);
502 if (dwStyle & TBSTYLE_LIST) {
503 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
504 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
506 else {
507 if (sizeString.cy > 0)
508 infoPtr->nButtonHeight = sizeString.cy + infoPtr->nBitmapHeight + 6;
509 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
510 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
512 if (sizeString.cx > infoPtr->nBitmapWidth)
513 infoPtr->nButtonWidth = sizeString.cx + 6;
514 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
515 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
518 TOOLBAR_WrapToolbar( hwnd, dwStyle );
520 x = infoPtr->nIndent;
521 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
522 cx = infoPtr->nButtonWidth;
523 cy = infoPtr->nButtonHeight;
524 nRows = nSepRows = 0;
526 infoPtr->rcBound.top = y;
527 infoPtr->rcBound.left = x;
528 infoPtr->rcBound.bottom = y + cy;
529 infoPtr->rcBound.right = x;
531 btnPtr = infoPtr->buttons;
532 GetClientRect( GetParent(hwnd), &rc );
533 infoPtr->nWidth = rc.right - rc.left;
535 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
537 bWrap = FALSE;
538 if (btnPtr->fsState & TBSTATE_HIDDEN)
540 SetRectEmpty (&btnPtr->rect);
541 continue;
544 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
545 /* it is the actual width of the separator. This is used for */
546 /* custom controls in toolbars. */
547 if (btnPtr->fsStyle & TBSTYLE_SEP)
548 cx = (btnPtr->iBitmap > 0) ?
549 btnPtr->iBitmap : SEPARATOR_WIDTH;
550 else
551 cx = infoPtr->nButtonWidth;
553 if (btnPtr->fsState & TBSTATE_WRAP )
554 bWrap = TRUE;
556 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
558 if (infoPtr->rcBound.left > x)
559 infoPtr->rcBound.left = x;
560 if (infoPtr->rcBound.right < x + cx)
561 infoPtr->rcBound.right = x + cx;
562 if (infoPtr->rcBound.bottom < y + cy)
563 infoPtr->rcBound.bottom = y + cy;
565 /* Set the toolTip only for non-hidden, non-separator button */
566 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
568 TTTOOLINFOA ti;
570 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
571 ti.cbSize = sizeof(TTTOOLINFOA);
572 ti.hwnd = hwnd;
573 ti.uId = btnPtr->idCommand;
574 ti.rect = btnPtr->rect;
575 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
576 0, (LPARAM)&ti);
579 /* btnPtr->nRow is zero based. The space between the rows is */
580 /* also considered as a row. */
581 btnPtr->nRow = nRows + nSepRows;
582 if( bWrap )
584 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
585 y += cy;
586 else
588 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
589 /* it is the actual width of the separator. This is used for */
590 /* custom controls in toolbars. */
591 y += cy + ( (btnPtr->iBitmap > 0 ) ?
592 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
594 /* nSepRows is used to calculate the extra height follwoing */
595 /* the last row. */
596 nSepRows++;
598 x = infoPtr->nIndent;
599 nRows++;
601 else
602 x += cx;
605 /* infoPtr->nRows is the number of rows on the toolbar */
606 infoPtr->nRows = nRows + nSepRows + 1;
608 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
609 /* the last row. */
610 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
611 nSepRows * SEPARATOR_WIDTH * 2 / 3 +
612 nSepRows * (infoPtr->nBitmapHeight + 1) +
613 BOTTOM_BORDER;
614 TRACE("toolbar height %d\n", infoPtr->nHeight);
618 static INT
619 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
621 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
622 TBUTTON_INFO *btnPtr;
623 INT i;
625 btnPtr = infoPtr->buttons;
626 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
627 if (btnPtr->fsState & TBSTATE_HIDDEN)
628 continue;
630 if (btnPtr->fsStyle & TBSTYLE_SEP) {
631 if (PtInRect (&btnPtr->rect, *lpPt)) {
632 TRACE(" ON SEPARATOR %d!\n", i);
633 return -i;
636 else {
637 if (PtInRect (&btnPtr->rect, *lpPt)) {
638 TRACE(" ON BUTTON %d!\n", i);
639 return i;
644 TRACE(" NOWHERE!\n");
645 return -1;
649 static INT
650 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
652 TBUTTON_INFO *btnPtr;
653 INT i;
655 btnPtr = infoPtr->buttons;
656 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
657 if (btnPtr->idCommand == idCommand) {
658 TRACE("command=%d index=%d\n", idCommand, i);
659 return i;
662 TRACE("no index found for command=%d\n", idCommand);
663 return -1;
667 static INT
668 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
670 TBUTTON_INFO *btnPtr;
671 INT nRunIndex;
673 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
674 return -1;
676 /* check index button */
677 btnPtr = &infoPtr->buttons[nIndex];
678 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
679 if (btnPtr->fsState & TBSTATE_CHECKED)
680 return nIndex;
683 /* check previous buttons */
684 nRunIndex = nIndex - 1;
685 while (nRunIndex >= 0) {
686 btnPtr = &infoPtr->buttons[nRunIndex];
687 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
688 if (btnPtr->fsState & TBSTATE_CHECKED)
689 return nRunIndex;
691 else
692 break;
693 nRunIndex--;
696 /* check next buttons */
697 nRunIndex = nIndex + 1;
698 while (nRunIndex < infoPtr->nNumButtons) {
699 btnPtr = &infoPtr->buttons[nRunIndex];
700 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
701 if (btnPtr->fsState & TBSTATE_CHECKED)
702 return nRunIndex;
704 else
705 break;
706 nRunIndex++;
709 return -1;
713 static VOID
714 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
715 WPARAM wParam, LPARAM lParam)
717 MSG msg;
719 msg.hwnd = hwndMsg;
720 msg.message = uMsg;
721 msg.wParam = wParam;
722 msg.lParam = lParam;
723 msg.time = GetMessageTime ();
724 msg.pt.x = LOWORD(GetMessagePos ());
725 msg.pt.y = HIWORD(GetMessagePos ());
727 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
731 /***********************************************************************
732 * TOOLBAR_CustomizeDialogProc
733 * This function implements the toolbar customization dialog.
735 static BOOL WINAPI
736 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
738 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
739 static HDSA hDsa = NULL;
741 switch (uMsg)
743 case WM_INITDIALOG:
744 infoPtr = (TOOLBAR_INFO *)lParam;
745 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
747 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
749 if (infoPtr)
751 TBUTTON_INFO *btnPtr;
752 INT i;
754 /* insert 'virtual' separator button into 'available buttons' list */
755 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
757 /* copy all buttons and append them to the right listbox */
758 btnPtr = infoPtr->buttons;
759 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
761 DSA_InsertItem (hDsa, i, btnPtr);
763 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
764 if (btnPtr->fsState & TBSTATE_HIDDEN)
766 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
768 else
770 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
774 /* append 'virtual' separator button to the 'toolbar buttons' list */
775 /* TODO */
777 return TRUE;
779 case WM_CLOSE:
780 EndDialog(hwnd, FALSE);
781 return TRUE;
783 case WM_COMMAND:
784 switch (LOWORD(wParam))
786 case IDCANCEL:
787 EndDialog(hwnd, FALSE);
788 break;
790 return TRUE;
792 case WM_DESTROY:
793 if (hDsa)
794 DSA_Destroy (hDsa);
795 return TRUE;
797 case WM_DRAWITEM:
798 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
800 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
801 TBUTTON_INFO btnPtr;
802 RECT rcButton;
803 RECT rcText;
804 HPEN hOldPen;
805 HBRUSH hOldBrush;
806 COLORREF oldText = 0;
807 COLORREF oldBk = 0;
809 FIXME("action: %x itemState: %x\n",
810 lpdis->itemAction, lpdis->itemState);
812 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
814 if (lpdis->itemState & ODS_FOCUS)
816 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
817 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
820 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
821 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
823 /* fill background rectangle */
824 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
825 lpdis->rcItem.right, lpdis->rcItem.bottom);
827 /* calculate button and text rectangles */
828 CopyRect (&rcButton, &lpdis->rcItem);
829 InflateRect (&rcButton, -1, -1);
830 CopyRect (&rcText, &rcButton);
831 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
832 rcText.left = rcButton.right + 2;
834 /* draw focus rectangle */
835 if (lpdis->itemState & ODS_FOCUS)
836 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
838 /* draw button */
839 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
841 /* draw image and text */
842 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
844 /* virtual separator in the 'available' list */
845 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
846 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
848 else
850 /* real button */
852 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
853 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
855 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
856 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
860 if (lpdis->itemState & ODS_FOCUS)
862 SetBkColor (lpdis->hDC, oldBk);
863 SetTextColor (lpdis->hDC, oldText);
866 SelectObject (lpdis->hDC, hOldBrush);
867 SelectObject (lpdis->hDC, hOldPen);
869 return TRUE;
871 return FALSE;
873 case WM_MEASUREITEM:
874 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
876 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
878 if (infoPtr)
879 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
880 else
881 lpmis->itemHeight = 16 + 8; /* default height */
883 return TRUE;
885 return FALSE;
887 default:
888 return FALSE;
893 /***********************************************************************
894 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
897 static LRESULT
898 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
900 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
901 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
902 INT nIndex = 0, nButtons;
903 HBITMAP hbmLoad;
905 if (!lpAddBmp)
906 return -1;
908 if (lpAddBmp->hInst == HINST_COMMCTRL)
910 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
911 nButtons = 15;
912 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
913 nButtons = 13;
914 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
915 nButtons = 5;
916 else
917 return -1;
919 TRACE ("adding %d internal bitmaps!\n", nButtons);
921 /* Windows resize all the buttons to the size of a newly added standard image */
922 if (lpAddBmp->nID & 1)
924 /* large icons */
925 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
926 MAKELPARAM((WORD)26, (WORD)26));
927 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
928 MAKELPARAM((WORD)33, (WORD)33));
930 else
932 /* small icons */
933 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
934 MAKELPARAM((WORD)16, (WORD)16));
935 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
936 MAKELPARAM((WORD)22, (WORD)22));
939 TOOLBAR_CalcToolbar (hwnd);
941 else
943 nButtons = (INT)wParam;
944 if (nButtons <= 0)
945 return -1;
947 TRACE ("adding %d bitmaps!\n", nButtons);
950 if (!(infoPtr->himlDef)) {
951 /* create new default image list */
952 TRACE ("creating default image list!\n");
954 infoPtr->himlDef =
955 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
956 ILC_COLOR | ILC_MASK, nButtons, 2);
957 infoPtr->himlInt = infoPtr->himlDef;
960 /* Add bitmaps to the default image list */
961 if (lpAddBmp->hInst == (HINSTANCE)0)
963 nIndex =
964 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
965 CLR_DEFAULT);
967 else if (lpAddBmp->hInst == HINST_COMMCTRL)
969 /* Add system bitmaps */
970 switch (lpAddBmp->nID)
972 case IDB_STD_SMALL_COLOR:
973 hbmLoad = LoadBitmapA (COMCTL32_hModule,
974 MAKEINTRESOURCEA(IDB_STD_SMALL));
975 nIndex = ImageList_AddMasked (infoPtr->himlDef,
976 hbmLoad, CLR_DEFAULT);
977 DeleteObject (hbmLoad);
978 break;
980 case IDB_STD_LARGE_COLOR:
981 hbmLoad = LoadBitmapA (COMCTL32_hModule,
982 MAKEINTRESOURCEA(IDB_STD_LARGE));
983 nIndex = ImageList_AddMasked (infoPtr->himlDef,
984 hbmLoad, CLR_DEFAULT);
985 DeleteObject (hbmLoad);
986 break;
988 case IDB_VIEW_SMALL_COLOR:
989 hbmLoad = LoadBitmapA (COMCTL32_hModule,
990 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
991 nIndex = ImageList_AddMasked (infoPtr->himlDef,
992 hbmLoad, CLR_DEFAULT);
993 DeleteObject (hbmLoad);
994 break;
996 case IDB_VIEW_LARGE_COLOR:
997 hbmLoad = LoadBitmapA (COMCTL32_hModule,
998 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
999 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1000 hbmLoad, CLR_DEFAULT);
1001 DeleteObject (hbmLoad);
1002 break;
1004 case IDB_HIST_SMALL_COLOR:
1005 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1006 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1007 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1008 hbmLoad, CLR_DEFAULT);
1009 DeleteObject (hbmLoad);
1010 break;
1012 case IDB_HIST_LARGE_COLOR:
1013 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1014 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1015 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1016 hbmLoad, CLR_DEFAULT);
1017 DeleteObject (hbmLoad);
1018 break;
1020 default:
1021 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1022 ERR ("invalid imagelist!\n");
1023 break;
1026 else
1028 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1029 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1030 DeleteObject (hbmLoad);
1033 infoPtr->nNumBitmaps += nButtons;
1035 return nIndex;
1039 static LRESULT
1040 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1042 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1043 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1044 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1046 TRACE("adding %d buttons!\n", wParam);
1048 nAddButtons = (UINT)wParam;
1049 nOldButtons = infoPtr->nNumButtons;
1050 nNewButtons = nOldButtons + nAddButtons;
1052 if (infoPtr->nNumButtons == 0) {
1053 infoPtr->buttons =
1054 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1056 else {
1057 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1058 infoPtr->buttons =
1059 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1060 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1061 nOldButtons * sizeof(TBUTTON_INFO));
1062 COMCTL32_Free (oldButtons);
1065 infoPtr->nNumButtons = nNewButtons;
1067 /* insert new button data */
1068 for (nCount = 0; nCount < nAddButtons; nCount++) {
1069 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1070 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1071 btnPtr->idCommand = lpTbb[nCount].idCommand;
1072 btnPtr->fsState = lpTbb[nCount].fsState;
1073 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1074 btnPtr->dwData = lpTbb[nCount].dwData;
1075 btnPtr->iString = lpTbb[nCount].iString;
1076 btnPtr->bHot = FALSE;
1078 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1079 TTTOOLINFOA ti;
1081 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1082 ti.cbSize = sizeof (TTTOOLINFOA);
1083 ti.hwnd = hwnd;
1084 ti.uId = btnPtr->idCommand;
1085 ti.hinst = 0;
1086 ti.lpszText = LPSTR_TEXTCALLBACKA;
1088 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1089 0, (LPARAM)&ti);
1093 TOOLBAR_CalcToolbar (hwnd);
1095 InvalidateRect(hwnd, NULL, FALSE);
1097 return TRUE;
1101 static LRESULT
1102 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1104 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1105 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1106 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1108 TRACE("adding %d buttons!\n", wParam);
1110 nAddButtons = (UINT)wParam;
1111 nOldButtons = infoPtr->nNumButtons;
1112 nNewButtons = nOldButtons + nAddButtons;
1114 if (infoPtr->nNumButtons == 0) {
1115 infoPtr->buttons =
1116 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1118 else {
1119 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1120 infoPtr->buttons =
1121 COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1122 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1123 nOldButtons * sizeof(TBUTTON_INFO));
1124 COMCTL32_Free (oldButtons);
1127 infoPtr->nNumButtons = nNewButtons;
1129 /* insert new button data */
1130 for (nCount = 0; nCount < nAddButtons; nCount++) {
1131 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1132 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1133 btnPtr->idCommand = lpTbb[nCount].idCommand;
1134 btnPtr->fsState = lpTbb[nCount].fsState;
1135 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1136 btnPtr->dwData = lpTbb[nCount].dwData;
1137 btnPtr->iString = lpTbb[nCount].iString;
1138 btnPtr->bHot = FALSE;
1140 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1141 TTTOOLINFOW ti;
1143 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1144 ti.cbSize = sizeof (TTTOOLINFOW);
1145 ti.hwnd = hwnd;
1146 ti.uId = btnPtr->idCommand;
1147 ti.hinst = 0;
1148 ti.lpszText = LPSTR_TEXTCALLBACKW;
1150 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1151 0, (LPARAM)&ti);
1155 TOOLBAR_CalcToolbar (hwnd);
1157 InvalidateRect(hwnd, NULL, FALSE);
1159 return TRUE;
1163 static LRESULT
1164 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1166 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1167 INT nIndex;
1169 if ((wParam) && (HIWORD(lParam) == 0)) {
1170 char szString[256];
1171 INT len;
1172 TRACE("adding string from resource!\n");
1174 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1175 szString, 256);
1177 TRACE("len=%d \"%s\"\n", len, szString);
1178 nIndex = infoPtr->nNumStrings;
1179 if (infoPtr->nNumStrings == 0) {
1180 infoPtr->strings =
1181 COMCTL32_Alloc (sizeof(LPWSTR));
1183 else {
1184 LPWSTR *oldStrings = infoPtr->strings;
1185 infoPtr->strings =
1186 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1187 memcpy (&infoPtr->strings[0], &oldStrings[0],
1188 sizeof(LPWSTR) * infoPtr->nNumStrings);
1189 COMCTL32_Free (oldStrings);
1192 infoPtr->strings[infoPtr->nNumStrings] =
1193 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1194 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1195 infoPtr->nNumStrings++;
1197 else {
1198 LPSTR p = (LPSTR)lParam;
1199 INT len;
1201 if (p == NULL)
1202 return -1;
1203 TRACE("adding string(s) from array!\n");
1204 nIndex = infoPtr->nNumStrings;
1205 while (*p) {
1206 len = lstrlenA (p);
1207 TRACE("len=%d \"%s\"\n", len, p);
1209 if (infoPtr->nNumStrings == 0) {
1210 infoPtr->strings =
1211 COMCTL32_Alloc (sizeof(LPWSTR));
1213 else {
1214 LPWSTR *oldStrings = infoPtr->strings;
1215 infoPtr->strings =
1216 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1217 memcpy (&infoPtr->strings[0], &oldStrings[0],
1218 sizeof(LPWSTR) * infoPtr->nNumStrings);
1219 COMCTL32_Free (oldStrings);
1222 infoPtr->strings[infoPtr->nNumStrings] =
1223 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1224 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1225 infoPtr->nNumStrings++;
1227 p += (len+1);
1231 return nIndex;
1235 static LRESULT
1236 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1238 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1239 INT nIndex;
1241 if ((wParam) && (HIWORD(lParam) == 0)) {
1242 WCHAR szString[256];
1243 INT len;
1244 TRACE("adding string from resource!\n");
1246 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1247 szString, 256);
1249 TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1250 nIndex = infoPtr->nNumStrings;
1251 if (infoPtr->nNumStrings == 0) {
1252 infoPtr->strings =
1253 COMCTL32_Alloc (sizeof(LPWSTR));
1255 else {
1256 LPWSTR *oldStrings = infoPtr->strings;
1257 infoPtr->strings =
1258 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1259 memcpy (&infoPtr->strings[0], &oldStrings[0],
1260 sizeof(LPWSTR) * infoPtr->nNumStrings);
1261 COMCTL32_Free (oldStrings);
1264 infoPtr->strings[infoPtr->nNumStrings] =
1265 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1266 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1267 infoPtr->nNumStrings++;
1269 else {
1270 LPWSTR p = (LPWSTR)lParam;
1271 INT len;
1273 if (p == NULL)
1274 return -1;
1275 TRACE("adding string(s) from array!\n");
1276 nIndex = infoPtr->nNumStrings;
1277 while (*p) {
1278 len = lstrlenW (p);
1279 TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1281 if (infoPtr->nNumStrings == 0) {
1282 infoPtr->strings =
1283 COMCTL32_Alloc (sizeof(LPWSTR));
1285 else {
1286 LPWSTR *oldStrings = infoPtr->strings;
1287 infoPtr->strings =
1288 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1289 memcpy (&infoPtr->strings[0], &oldStrings[0],
1290 sizeof(LPWSTR) * infoPtr->nNumStrings);
1291 COMCTL32_Free (oldStrings);
1294 infoPtr->strings[infoPtr->nNumStrings] =
1295 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1296 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1297 infoPtr->nNumStrings++;
1299 p += (len+1);
1303 return nIndex;
1307 static LRESULT
1308 TOOLBAR_AutoSize (HWND hwnd)
1310 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1311 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1312 RECT parent_rect;
1313 HWND parent;
1314 /* INT32 x, y; */
1315 INT cx, cy;
1316 UINT uPosFlags = 0;
1318 TRACE("resize forced!\n");
1320 parent = GetParent (hwnd);
1321 GetClientRect(parent, &parent_rect);
1323 if (dwStyle & CCS_NORESIZE) {
1324 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1325 cx = 0;
1326 cy = 0;
1328 else {
1329 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1330 TOOLBAR_CalcToolbar (hwnd);
1331 InvalidateRect( hwnd, NULL, TRUE );
1332 cy = infoPtr->nHeight;
1333 cx = infoPtr->nWidth;
1336 if (dwStyle & CCS_NOPARENTALIGN)
1337 uPosFlags |= SWP_NOMOVE;
1339 if (!(dwStyle & CCS_NODIVIDER))
1340 cy += GetSystemMetrics(SM_CYEDGE);
1342 infoPtr->bAutoSize = TRUE;
1343 SetWindowPos (hwnd, HWND_TOP, parent_rect.left, parent_rect.top,
1344 cx, cy, uPosFlags);
1346 return 0;
1350 static LRESULT
1351 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1353 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1355 return infoPtr->nNumButtons;
1359 static LRESULT
1360 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1362 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1364 if (infoPtr == NULL) {
1365 ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1366 ERR("infoPtr == NULL!\n");
1367 return 0;
1370 infoPtr->dwStructSize = (DWORD)wParam;
1372 return 0;
1376 static LRESULT
1377 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1379 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1380 TBUTTON_INFO *btnPtr;
1381 HDC hdc;
1382 INT nIndex;
1384 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1385 if (nIndex == -1)
1386 return FALSE;
1388 btnPtr = &infoPtr->buttons[nIndex];
1389 btnPtr->iBitmap = LOWORD(lParam);
1391 hdc = GetDC (hwnd);
1392 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
1393 ReleaseDC (hwnd, hdc);
1395 return TRUE;
1399 static LRESULT
1400 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1402 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1403 TBUTTON_INFO *btnPtr;
1404 HDC hdc;
1405 INT nIndex;
1406 INT nOldIndex = -1;
1408 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1409 if (nIndex == -1)
1410 return FALSE;
1412 btnPtr = &infoPtr->buttons[nIndex];
1414 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1415 return FALSE;
1417 if (LOWORD(lParam) == FALSE)
1418 btnPtr->fsState &= ~TBSTATE_CHECKED;
1419 else {
1420 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1421 nOldIndex =
1422 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1423 if (nOldIndex == nIndex)
1424 return 0;
1425 if (nOldIndex != -1)
1426 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1428 btnPtr->fsState |= TBSTATE_CHECKED;
1431 hdc = GetDC (hwnd);
1432 if (nOldIndex != -1)
1433 TOOLBAR_DrawButton (hwnd, &infoPtr->buttons[nOldIndex], hdc);
1434 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
1435 ReleaseDC (hwnd, hdc);
1437 /* FIXME: Send a WM_NOTIFY?? */
1439 return TRUE;
1443 static LRESULT
1444 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1446 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1448 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1452 static LRESULT
1453 TOOLBAR_Customize (HWND hwnd)
1455 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1456 LRESULT ret;
1457 LPCVOID template;
1458 HRSRC hRes;
1459 NMHDR nmhdr;
1461 /* send TBN_BEGINADJUST notification */
1462 nmhdr.hwndFrom = hwnd;
1463 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1464 nmhdr.code = TBN_BEGINADJUST;
1466 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1467 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1469 if (!(hRes = FindResourceA (COMCTL32_hModule,
1470 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1471 RT_DIALOGA)))
1472 return FALSE;
1474 if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1475 return FALSE;
1477 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1478 (LPDLGTEMPLATEA)template,
1479 hwnd,
1480 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1481 (LPARAM)infoPtr);
1483 /* send TBN_ENDADJUST notification */
1484 nmhdr.code = TBN_ENDADJUST;
1486 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1487 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1489 return ret;
1493 static LRESULT
1494 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1496 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1497 INT nIndex = (INT)wParam;
1499 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1500 return FALSE;
1502 if ((infoPtr->hwndToolTip) &&
1503 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1504 TTTOOLINFOA ti;
1506 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1507 ti.cbSize = sizeof (TTTOOLINFOA);
1508 ti.hwnd = hwnd;
1509 ti.uId = infoPtr->buttons[nIndex].idCommand;
1511 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1514 if (infoPtr->nNumButtons == 1) {
1515 TRACE(" simple delete!\n");
1516 COMCTL32_Free (infoPtr->buttons);
1517 infoPtr->buttons = NULL;
1518 infoPtr->nNumButtons = 0;
1520 else {
1521 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1522 TRACE("complex delete! [nIndex=%d]\n", nIndex);
1524 infoPtr->nNumButtons--;
1525 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1526 if (nIndex > 0) {
1527 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1528 nIndex * sizeof(TBUTTON_INFO));
1531 if (nIndex < infoPtr->nNumButtons) {
1532 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1533 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1536 COMCTL32_Free (oldButtons);
1539 TOOLBAR_CalcToolbar (hwnd);
1541 InvalidateRect (hwnd, NULL, TRUE);
1543 return TRUE;
1547 static LRESULT
1548 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1550 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1551 TBUTTON_INFO *btnPtr;
1552 HDC hdc;
1553 INT nIndex;
1555 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1556 if (nIndex == -1)
1557 return FALSE;
1559 btnPtr = &infoPtr->buttons[nIndex];
1560 if (LOWORD(lParam) == FALSE)
1561 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1562 else
1563 btnPtr->fsState |= TBSTATE_ENABLED;
1565 hdc = GetDC (hwnd);
1566 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
1567 ReleaseDC (hwnd, hdc);
1569 return TRUE;
1573 static inline LRESULT
1574 TOOLBAR_GetAnchorHighlight (HWND hwnd)
1576 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1578 return infoPtr->bAnchor;
1582 static LRESULT
1583 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1585 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1586 INT nIndex;
1588 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1589 if (nIndex == -1)
1590 return -1;
1592 return infoPtr->buttons[nIndex].iBitmap;
1596 static inline LRESULT
1597 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1599 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1603 static LRESULT
1604 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1606 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1607 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1608 INT nIndex = (INT)wParam;
1609 TBUTTON_INFO *btnPtr;
1611 if (infoPtr == NULL)
1612 return FALSE;
1614 if (lpTbb == NULL)
1615 return FALSE;
1617 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1618 return FALSE;
1620 btnPtr = &infoPtr->buttons[nIndex];
1621 lpTbb->iBitmap = btnPtr->iBitmap;
1622 lpTbb->idCommand = btnPtr->idCommand;
1623 lpTbb->fsState = btnPtr->fsState;
1624 lpTbb->fsStyle = btnPtr->fsStyle;
1625 lpTbb->dwData = btnPtr->dwData;
1626 lpTbb->iString = btnPtr->iString;
1628 return TRUE;
1632 static LRESULT
1633 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1635 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1636 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1637 TBUTTON_INFO *btnPtr;
1638 INT nIndex;
1640 if (infoPtr == NULL)
1641 return -1;
1642 if (lpTbInfo == NULL)
1643 return -1;
1644 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1645 return -1;
1647 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1648 if (nIndex == -1)
1649 return -1;
1651 btnPtr = &infoPtr->buttons[nIndex];
1653 if (lpTbInfo->dwMask & TBIF_COMMAND)
1654 lpTbInfo->idCommand = btnPtr->idCommand;
1655 if (lpTbInfo->dwMask & TBIF_IMAGE)
1656 lpTbInfo->iImage = btnPtr->iBitmap;
1657 if (lpTbInfo->dwMask & TBIF_LPARAM)
1658 lpTbInfo->lParam = btnPtr->dwData;
1659 if (lpTbInfo->dwMask & TBIF_SIZE)
1660 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1661 if (lpTbInfo->dwMask & TBIF_STATE)
1662 lpTbInfo->fsState = btnPtr->fsState;
1663 if (lpTbInfo->dwMask & TBIF_STYLE)
1664 lpTbInfo->fsStyle = btnPtr->fsStyle;
1665 if (lpTbInfo->dwMask & TBIF_TEXT) {
1666 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1667 lstrcpynWtoA (lpTbInfo->pszText,
1668 (LPWSTR)infoPtr->strings[btnPtr->iString],
1669 lpTbInfo->cchText);
1672 return nIndex;
1676 static LRESULT
1677 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1679 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1680 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
1681 TBUTTON_INFO *btnPtr;
1682 INT nIndex;
1684 if (infoPtr == NULL)
1685 return -1;
1686 if (lpTbInfo == NULL)
1687 return -1;
1688 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
1689 return -1;
1691 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1692 if (nIndex == -1)
1693 return -1;
1695 btnPtr = &infoPtr->buttons[nIndex];
1697 if (lpTbInfo->dwMask & TBIF_COMMAND)
1698 lpTbInfo->idCommand = btnPtr->idCommand;
1699 if (lpTbInfo->dwMask & TBIF_IMAGE)
1700 lpTbInfo->iImage = btnPtr->iBitmap;
1701 if (lpTbInfo->dwMask & TBIF_LPARAM)
1702 lpTbInfo->lParam = btnPtr->dwData;
1703 if (lpTbInfo->dwMask & TBIF_SIZE)
1704 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1705 if (lpTbInfo->dwMask & TBIF_STATE)
1706 lpTbInfo->fsState = btnPtr->fsState;
1707 if (lpTbInfo->dwMask & TBIF_STYLE)
1708 lpTbInfo->fsStyle = btnPtr->fsStyle;
1709 if (lpTbInfo->dwMask & TBIF_TEXT) {
1710 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1711 lstrcpynW (lpTbInfo->pszText,
1712 (LPWSTR)infoPtr->strings[btnPtr->iString],
1713 lpTbInfo->cchText);
1716 return nIndex;
1720 static LRESULT
1721 TOOLBAR_GetButtonSize (HWND hwnd)
1723 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1725 return MAKELONG((WORD)infoPtr->nButtonWidth,
1726 (WORD)infoPtr->nButtonHeight);
1730 static LRESULT
1731 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1733 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1734 INT nIndex, nStringIndex;
1736 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1737 if (nIndex == -1)
1738 return -1;
1740 nStringIndex = infoPtr->buttons[nIndex].iString;
1742 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1744 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1745 return -1;
1747 if (lParam == 0)
1748 return -1;
1750 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1752 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1756 static LRESULT
1757 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1759 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1760 INT nIndex, nStringIndex;
1762 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1763 if (nIndex == -1)
1764 return -1;
1766 nStringIndex = infoPtr->buttons[nIndex].iString;
1768 TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1770 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1771 return -1;
1773 if (lParam == 0)
1774 return -1;
1776 lstrcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1778 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1782 /* << TOOLBAR_GetColorScheme >> */
1785 static LRESULT
1786 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1788 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1790 return (LRESULT)infoPtr->himlDis;
1794 inline static LRESULT
1795 TOOLBAR_GetExtendedStyle (HWND hwnd)
1797 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1799 return infoPtr->dwExStyle;
1803 static LRESULT
1804 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1806 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1808 return (LRESULT)infoPtr->himlHot;
1812 static LRESULT
1813 TOOLBAR_GetHotItem (HWND hwnd)
1815 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1817 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
1818 return -1;
1820 if (infoPtr->nHotItem < 0)
1821 return -1;
1823 return (LRESULT)infoPtr->nHotItem;
1827 static LRESULT
1828 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1830 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1832 return (LRESULT)infoPtr->himlDef;
1836 /* << TOOLBAR_GetInsertMark >> */
1837 /* << TOOLBAR_GetInsertMarkColor >> */
1840 static LRESULT
1841 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1843 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1844 TBUTTON_INFO *btnPtr;
1845 LPRECT lpRect;
1846 INT nIndex;
1848 if (infoPtr == NULL)
1849 return FALSE;
1850 nIndex = (INT)wParam;
1851 btnPtr = &infoPtr->buttons[nIndex];
1852 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1853 return FALSE;
1854 lpRect = (LPRECT)lParam;
1855 if (lpRect == NULL)
1856 return FALSE;
1857 if (btnPtr->fsState & TBSTATE_HIDDEN)
1858 return FALSE;
1860 TOOLBAR_CalcToolbar( hwnd );
1862 lpRect->left = btnPtr->rect.left;
1863 lpRect->right = btnPtr->rect.right;
1864 lpRect->bottom = btnPtr->rect.bottom;
1865 lpRect->top = btnPtr->rect.top;
1867 return TRUE;
1871 static LRESULT
1872 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1874 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1875 LPSIZE lpSize = (LPSIZE)lParam;
1877 if (lpSize == NULL)
1878 return FALSE;
1880 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
1881 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
1883 TRACE("maximum size %d x %d\n",
1884 infoPtr->rcBound.right - infoPtr->rcBound.left,
1885 infoPtr->rcBound.bottom - infoPtr->rcBound.top);
1887 return TRUE;
1891 /* << TOOLBAR_GetObject >> */
1892 /* << TOOLBAR_GetPadding >> */
1895 static LRESULT
1896 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1898 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1899 TBUTTON_INFO *btnPtr;
1900 LPRECT lpRect;
1901 INT nIndex;
1903 if (infoPtr == NULL)
1904 return FALSE;
1905 nIndex = (INT)wParam;
1906 btnPtr = &infoPtr->buttons[nIndex];
1907 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1908 return FALSE;
1909 lpRect = (LPRECT)lParam;
1910 if (lpRect == NULL)
1911 return FALSE;
1913 lpRect->left = btnPtr->rect.left;
1914 lpRect->right = btnPtr->rect.right;
1915 lpRect->bottom = btnPtr->rect.bottom;
1916 lpRect->top = btnPtr->rect.top;
1918 return TRUE;
1922 static LRESULT
1923 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
1925 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1927 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
1928 return infoPtr->nRows;
1929 else
1930 return 1;
1934 static LRESULT
1935 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
1937 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1938 INT nIndex;
1940 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1941 if (nIndex == -1)
1942 return -1;
1944 return infoPtr->buttons[nIndex].fsState;
1948 static LRESULT
1949 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
1951 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1952 INT nIndex;
1954 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1955 if (nIndex == -1)
1956 return -1;
1958 return infoPtr->buttons[nIndex].fsStyle;
1962 static LRESULT
1963 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
1965 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1967 if (infoPtr == NULL)
1968 return 0;
1970 return infoPtr->nMaxTextRows;
1974 static LRESULT
1975 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
1977 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1979 if (infoPtr == NULL)
1980 return 0;
1981 return infoPtr->hwndToolTip;
1985 static LRESULT
1986 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
1988 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1990 TRACE("%s hwnd=0x%x stub!\n",
1991 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
1993 return infoPtr->bUnicode;
1997 inline static LRESULT
1998 TOOLBAR_GetVersion (HWND hwnd)
2000 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2001 return infoPtr->iVersion;
2005 static LRESULT
2006 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2008 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2009 TBUTTON_INFO *btnPtr;
2010 INT nIndex;
2012 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2013 if (nIndex == -1)
2014 return FALSE;
2016 btnPtr = &infoPtr->buttons[nIndex];
2017 if (LOWORD(lParam) == FALSE)
2018 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2019 else
2020 btnPtr->fsState |= TBSTATE_HIDDEN;
2022 TOOLBAR_CalcToolbar (hwnd);
2024 InvalidateRect (hwnd, NULL, TRUE);
2026 return TRUE;
2030 inline static LRESULT
2031 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2033 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2037 static LRESULT
2038 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2040 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2041 TBUTTON_INFO *btnPtr;
2042 HDC hdc;
2043 INT nIndex;
2045 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2046 if (nIndex == -1)
2047 return FALSE;
2049 btnPtr = &infoPtr->buttons[nIndex];
2050 if (LOWORD(lParam) == FALSE)
2051 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2052 else
2053 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2055 hdc = GetDC (hwnd);
2056 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2057 ReleaseDC (hwnd, hdc);
2059 return TRUE;
2063 static LRESULT
2064 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2066 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2067 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2068 INT nIndex = (INT)wParam;
2069 TBUTTON_INFO *oldButtons;
2071 if (lpTbb == NULL)
2072 return FALSE;
2074 if (nIndex == -1) {
2075 /* EPP: this seems to be an undocumented call (from my IE4)
2076 * I assume in that case that:
2077 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2078 * - index of insertion is at the end of existing buttons
2079 * I only see this happen with nIndex == -1, but it could have a special
2080 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2082 int len = lstrlenA((char*)lpTbb->iString) + 2;
2083 LPSTR ptr = COMCTL32_Alloc(len);
2085 nIndex = infoPtr->nNumButtons;
2086 strcpy(ptr, (char*)lpTbb->iString);
2087 ptr[len - 1] = 0; /* ended by two '\0' */
2088 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2089 COMCTL32_Free(ptr);
2091 } else if (nIndex < 0)
2092 return FALSE;
2094 TRACE("inserting button index=%d\n", nIndex);
2095 if (nIndex > infoPtr->nNumButtons) {
2096 nIndex = infoPtr->nNumButtons;
2097 TRACE("adjust index=%d\n", nIndex);
2100 oldButtons = infoPtr->buttons;
2101 infoPtr->nNumButtons++;
2102 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2103 /* pre insert copy */
2104 if (nIndex > 0) {
2105 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2106 nIndex * sizeof(TBUTTON_INFO));
2109 /* insert new button */
2110 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2111 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2112 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2113 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2114 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2115 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2117 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2118 TTTOOLINFOA ti;
2120 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2121 ti.cbSize = sizeof (TTTOOLINFOA);
2122 ti.hwnd = hwnd;
2123 ti.uId = lpTbb->idCommand;
2124 ti.hinst = 0;
2125 ti.lpszText = LPSTR_TEXTCALLBACKA;
2127 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2128 0, (LPARAM)&ti);
2131 /* post insert copy */
2132 if (nIndex < infoPtr->nNumButtons - 1) {
2133 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2134 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2137 COMCTL32_Free (oldButtons);
2139 TOOLBAR_CalcToolbar (hwnd);
2141 InvalidateRect (hwnd, NULL, FALSE);
2143 return TRUE;
2147 static LRESULT
2148 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2150 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2151 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2152 INT nIndex = (INT)wParam;
2153 TBUTTON_INFO *oldButtons;
2155 if (lpTbb == NULL)
2156 return FALSE;
2157 if (nIndex < 0)
2158 return FALSE;
2160 TRACE("inserting button index=%d\n", nIndex);
2161 if (nIndex > infoPtr->nNumButtons) {
2162 nIndex = infoPtr->nNumButtons;
2163 TRACE("adjust index=%d\n", nIndex);
2166 oldButtons = infoPtr->buttons;
2167 infoPtr->nNumButtons++;
2168 infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2169 /* pre insert copy */
2170 if (nIndex > 0) {
2171 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2172 nIndex * sizeof(TBUTTON_INFO));
2175 /* insert new button */
2176 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2177 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2178 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2179 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2180 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2181 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2183 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2184 TTTOOLINFOW ti;
2186 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2187 ti.cbSize = sizeof (TTTOOLINFOW);
2188 ti.hwnd = hwnd;
2189 ti.uId = lpTbb->idCommand;
2190 ti.hinst = 0;
2191 ti.lpszText = LPSTR_TEXTCALLBACKW;
2193 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2194 0, (LPARAM)&ti);
2197 /* post insert copy */
2198 if (nIndex < infoPtr->nNumButtons - 1) {
2199 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2200 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2203 COMCTL32_Free (oldButtons);
2205 TOOLBAR_CalcToolbar (hwnd);
2207 InvalidateRect (hwnd, NULL, FALSE);
2209 return TRUE;
2213 /* << TOOLBAR_InsertMarkHitTest >> */
2216 static LRESULT
2217 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2219 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2220 INT nIndex;
2222 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2223 if (nIndex == -1)
2224 return FALSE;
2226 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2230 static LRESULT
2231 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2233 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2234 INT nIndex;
2236 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2237 if (nIndex == -1)
2238 return FALSE;
2240 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2244 static LRESULT
2245 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2247 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2248 INT nIndex;
2250 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2251 if (nIndex == -1)
2252 return FALSE;
2254 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2258 static LRESULT
2259 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2261 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2262 INT nIndex;
2264 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2265 if (nIndex == -1)
2266 return FALSE;
2268 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2272 static LRESULT
2273 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2275 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2276 INT nIndex;
2278 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2279 if (nIndex == -1)
2280 return FALSE;
2282 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2286 static LRESULT
2287 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2289 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2290 INT nIndex;
2292 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2293 if (nIndex == -1)
2294 return FALSE;
2296 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2300 /* << TOOLBAR_LoadImages >> */
2301 /* << TOOLBAR_MapAccelerator >> */
2302 /* << TOOLBAR_MarkButton >> */
2303 /* << TOOLBAR_MoveButton >> */
2306 static LRESULT
2307 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2309 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2310 TBUTTON_INFO *btnPtr;
2311 HDC hdc;
2312 INT nIndex;
2314 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2315 if (nIndex == -1)
2316 return FALSE;
2318 btnPtr = &infoPtr->buttons[nIndex];
2319 if (LOWORD(lParam) == FALSE)
2320 btnPtr->fsState &= ~TBSTATE_PRESSED;
2321 else
2322 btnPtr->fsState |= TBSTATE_PRESSED;
2324 hdc = GetDC (hwnd);
2325 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2326 ReleaseDC (hwnd, hdc);
2328 return TRUE;
2332 /* << TOOLBAR_ReplaceBitmap >> */
2335 static LRESULT
2336 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2338 #if 0
2339 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2340 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2342 if (lpSave == NULL) return 0;
2344 if ((BOOL)wParam) {
2345 /* save toolbar information */
2346 FIXME("save to \"%s\" \"%s\"\n",
2347 lpSave->pszSubKey, lpSave->pszValueName);
2351 else {
2352 /* restore toolbar information */
2354 FIXME("restore from \"%s\" \"%s\"\n",
2355 lpSave->pszSubKey, lpSave->pszValueName);
2359 #endif
2361 return 0;
2365 static LRESULT
2366 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2368 #if 0
2369 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2370 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2372 if (lpSave == NULL)
2373 return 0;
2375 if ((BOOL)wParam) {
2376 /* save toolbar information */
2377 FIXME("save to \"%s\" \"%s\"\n",
2378 lpSave->pszSubKey, lpSave->pszValueName);
2382 else {
2383 /* restore toolbar information */
2385 FIXME("restore from \"%s\" \"%s\"\n",
2386 lpSave->pszSubKey, lpSave->pszValueName);
2390 #endif
2392 return 0;
2396 static LRESULT
2397 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2399 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2400 BOOL bOldAnchor = infoPtr->bAnchor;
2402 infoPtr->bAnchor = (BOOL)wParam;
2404 return (LRESULT)bOldAnchor;
2408 static LRESULT
2409 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2411 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2413 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2414 return FALSE;
2416 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2417 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2419 return TRUE;
2423 static LRESULT
2424 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2426 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2427 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2428 TBUTTON_INFO *btnPtr;
2429 INT nIndex;
2431 if (lptbbi == NULL)
2432 return FALSE;
2433 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2434 return FALSE;
2436 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2437 if (nIndex == -1)
2438 return FALSE;
2440 btnPtr = &infoPtr->buttons[nIndex];
2441 if (lptbbi->dwMask & TBIF_COMMAND)
2442 btnPtr->idCommand = lptbbi->idCommand;
2443 if (lptbbi->dwMask & TBIF_IMAGE)
2444 btnPtr->iBitmap = lptbbi->iImage;
2445 if (lptbbi->dwMask & TBIF_LPARAM)
2446 btnPtr->dwData = lptbbi->lParam;
2447 /* if (lptbbi->dwMask & TBIF_SIZE) */
2448 /* btnPtr->cx = lptbbi->cx; */
2449 if (lptbbi->dwMask & TBIF_STATE)
2450 btnPtr->fsState = lptbbi->fsState;
2451 if (lptbbi->dwMask & TBIF_STYLE)
2452 btnPtr->fsStyle = lptbbi->fsStyle;
2454 if (lptbbi->dwMask & TBIF_TEXT) {
2455 if ((btnPtr->iString >= 0) ||
2456 (btnPtr->iString < infoPtr->nNumStrings)) {
2457 TRACE("Ooooooch\n");
2458 #if 0
2459 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2460 INT len = lstrlenA (lptbbi->pszText);
2461 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2462 #endif
2464 /* this is the ultimate sollution */
2465 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2469 return TRUE;
2473 static LRESULT
2474 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2476 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2477 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2478 TBUTTON_INFO *btnPtr;
2479 INT nIndex;
2481 if (lptbbi == NULL)
2482 return FALSE;
2483 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2484 return FALSE;
2486 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2487 if (nIndex == -1)
2488 return FALSE;
2490 btnPtr = &infoPtr->buttons[nIndex];
2491 if (lptbbi->dwMask & TBIF_COMMAND)
2492 btnPtr->idCommand = lptbbi->idCommand;
2493 if (lptbbi->dwMask & TBIF_IMAGE)
2494 btnPtr->iBitmap = lptbbi->iImage;
2495 if (lptbbi->dwMask & TBIF_LPARAM)
2496 btnPtr->dwData = lptbbi->lParam;
2497 /* if (lptbbi->dwMask & TBIF_SIZE) */
2498 /* btnPtr->cx = lptbbi->cx; */
2499 if (lptbbi->dwMask & TBIF_STATE)
2500 btnPtr->fsState = lptbbi->fsState;
2501 if (lptbbi->dwMask & TBIF_STYLE)
2502 btnPtr->fsStyle = lptbbi->fsStyle;
2504 if (lptbbi->dwMask & TBIF_TEXT) {
2505 if ((btnPtr->iString >= 0) ||
2506 (btnPtr->iString < infoPtr->nNumStrings)) {
2507 #if 0
2508 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2509 INT len = lstrlenW (lptbbi->pszText);
2510 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2511 #endif
2513 /* this is the ultimate sollution */
2514 /* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2518 return TRUE;
2522 static LRESULT
2523 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2525 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2527 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2528 return FALSE;
2530 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2531 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2533 return TRUE;
2537 static LRESULT
2538 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2540 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2542 if (infoPtr == NULL)
2543 return FALSE;
2545 infoPtr->cxMin = (INT)LOWORD(lParam);
2546 infoPtr->cxMax = (INT)HIWORD(lParam);
2548 return TRUE;
2552 static LRESULT
2553 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2555 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2556 INT nIndex = (INT)wParam;
2558 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2559 return FALSE;
2561 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2563 if (infoPtr->hwndToolTip) {
2565 FIXME("change tool tip!\n");
2569 return TRUE;
2573 /* << TOOLBAR_SetColorScheme >> */
2576 static LRESULT
2577 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2579 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2580 HIMAGELIST himlTemp;
2582 himlTemp = infoPtr->himlDis;
2583 infoPtr->himlDis = (HIMAGELIST)lParam;
2585 /* FIXME: redraw ? */
2587 return (LRESULT)himlTemp;
2591 static LRESULT
2592 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2594 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2595 DWORD dwTemp;
2597 dwTemp = infoPtr->dwDTFlags;
2598 infoPtr->dwDTFlags =
2599 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2601 return (LRESULT)dwTemp;
2605 static LRESULT
2606 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2608 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2609 DWORD dwTemp;
2611 dwTemp = infoPtr->dwExStyle;
2612 infoPtr->dwExStyle = (DWORD)lParam;
2614 return (LRESULT)dwTemp;
2618 static LRESULT
2619 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2621 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2622 HIMAGELIST himlTemp;
2624 himlTemp = infoPtr->himlHot;
2625 infoPtr->himlHot = (HIMAGELIST)lParam;
2627 /* FIXME: redraw ? */
2629 return (LRESULT)himlTemp;
2633 static LRESULT
2634 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
2636 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2637 INT nOldHotItem = infoPtr->nHotItem;
2639 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
2641 infoPtr->nHotItem = (INT)wParam;
2643 /* FIXME: What else must be done ??? */
2647 if (nOldHotItem < 0)
2648 return -1;
2650 return (LRESULT)nOldHotItem;
2654 static LRESULT
2655 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2657 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2658 HIMAGELIST himlTemp;
2660 himlTemp = infoPtr->himlDef;
2661 infoPtr->himlDef = (HIMAGELIST)lParam;
2663 /* FIXME: redraw ? */
2665 return (LRESULT)himlTemp;
2669 static LRESULT
2670 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2674 infoPtr->nIndent = (INT)wParam;
2676 TOOLBAR_CalcToolbar (hwnd);
2678 InvalidateRect(hwnd, NULL, FALSE);
2680 return TRUE;
2684 /* << TOOLBAR_SetInsertMark >> */
2687 static LRESULT
2688 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2690 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2692 infoPtr->clrInsertMark = (COLORREF)lParam;
2694 /* FIXME : redraw ??*/
2696 return 0;
2700 static LRESULT
2701 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2703 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2705 if (infoPtr == NULL)
2706 return FALSE;
2708 infoPtr->nMaxTextRows = (INT)wParam;
2710 return TRUE;
2714 /* << TOOLBAR_SetPadding >> */
2717 static LRESULT
2718 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2720 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2721 HWND hwndOldNotify;
2723 if (infoPtr == NULL)
2724 return 0;
2725 hwndOldNotify = infoPtr->hwndNotify;
2726 infoPtr->hwndNotify = (HWND)wParam;
2728 return hwndOldNotify;
2732 static LRESULT
2733 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2735 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2736 LPRECT lprc = (LPRECT)lParam;
2738 if (LOWORD(wParam) > 1) {
2740 FIXME("multiple rows not supported!\n");
2744 /* recalculate toolbar */
2745 TOOLBAR_CalcToolbar (hwnd);
2747 /* return bounding rectangle */
2748 if (lprc) {
2749 lprc->left = infoPtr->rcBound.left;
2750 lprc->right = infoPtr->rcBound.right;
2751 lprc->top = infoPtr->rcBound.top;
2752 lprc->bottom = infoPtr->rcBound.bottom;
2755 /* repaint toolbar */
2756 InvalidateRect(hwnd, NULL, FALSE);
2758 return 0;
2762 static LRESULT
2763 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2765 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2766 TBUTTON_INFO *btnPtr;
2767 HDC hdc;
2768 INT nIndex;
2770 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2771 if (nIndex == -1)
2772 return FALSE;
2774 btnPtr = &infoPtr->buttons[nIndex];
2775 btnPtr->fsState = LOWORD(lParam);
2777 hdc = GetDC (hwnd);
2778 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2779 ReleaseDC (hwnd, hdc);
2781 return TRUE;
2785 static LRESULT
2786 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2788 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2789 TBUTTON_INFO *btnPtr;
2790 HDC hdc;
2791 INT nIndex;
2793 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2794 if (nIndex == -1)
2795 return FALSE;
2797 btnPtr = &infoPtr->buttons[nIndex];
2798 btnPtr->fsStyle = LOWORD(lParam);
2800 hdc = GetDC (hwnd);
2801 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2802 ReleaseDC (hwnd, hdc);
2804 if (infoPtr->hwndToolTip) {
2806 FIXME("change tool tip!\n");
2810 return TRUE;
2814 inline static LRESULT
2815 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2817 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2819 if (infoPtr == NULL)
2820 return 0;
2821 infoPtr->hwndToolTip = (HWND)wParam;
2822 return 0;
2826 static LRESULT
2827 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2829 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2830 BOOL bTemp;
2832 TRACE("%s hwnd=0x%04x stub!\n",
2833 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
2835 bTemp = infoPtr->bUnicode;
2836 infoPtr->bUnicode = (BOOL)wParam;
2838 return bTemp;
2842 static LRESULT
2843 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
2845 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2846 INT iOldVersion = infoPtr->iVersion;
2848 infoPtr->iVersion = iVersion;
2850 return iOldVersion;
2854 static LRESULT
2855 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
2857 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2858 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2859 LOGFONTA logFont;
2861 /* initialize info structure */
2862 infoPtr->nButtonHeight = 22;
2863 infoPtr->nButtonWidth = 23;
2864 infoPtr->nBitmapHeight = 15;
2865 infoPtr->nBitmapWidth = 16;
2867 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
2868 infoPtr->nRows = 1;
2869 infoPtr->nMaxTextRows = 1;
2870 infoPtr->cxMin = -1;
2871 infoPtr->cxMax = -1;
2873 infoPtr->bCaptured = FALSE;
2874 infoPtr->bUnicode = IsWindowUnicode (hwnd);
2875 infoPtr->nButtonDown = -1;
2876 infoPtr->nOldHit = -1;
2877 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
2878 infoPtr->hwndNotify = GetParent (hwnd);
2879 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
2880 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
2881 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
2882 infoPtr->iVersion = 0;
2884 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
2885 infoPtr->hFont = CreateFontIndirectA (&logFont);
2887 if (dwStyle & TBSTYLE_TOOLTIPS) {
2888 /* Create tooltip control */
2889 infoPtr->hwndToolTip =
2890 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
2891 CW_USEDEFAULT, CW_USEDEFAULT,
2892 CW_USEDEFAULT, CW_USEDEFAULT,
2893 hwnd, 0, 0, 0);
2895 /* Send NM_TOOLTIPSCREATED notification */
2896 if (infoPtr->hwndToolTip) {
2897 NMTOOLTIPSCREATED nmttc;
2899 nmttc.hdr.hwndFrom = hwnd;
2900 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
2901 nmttc.hdr.code = NM_TOOLTIPSCREATED;
2902 nmttc.hwndToolTips = infoPtr->hwndToolTip;
2904 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
2905 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
2909 return 0;
2913 static LRESULT
2914 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
2916 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2918 /* delete tooltip control */
2919 if (infoPtr->hwndToolTip)
2920 DestroyWindow (infoPtr->hwndToolTip);
2922 /* delete button data */
2923 if (infoPtr->buttons)
2924 COMCTL32_Free (infoPtr->buttons);
2926 /* delete strings */
2927 if (infoPtr->strings) {
2928 INT i;
2929 for (i = 0; i < infoPtr->nNumStrings; i++)
2930 if (infoPtr->strings[i])
2931 COMCTL32_Free (infoPtr->strings[i]);
2933 COMCTL32_Free (infoPtr->strings);
2936 /* destroy internal image list */
2937 if (infoPtr->himlInt)
2938 ImageList_Destroy (infoPtr->himlInt);
2940 /* delete default font */
2941 if (infoPtr->hFont)
2942 DeleteObject (infoPtr->hFont);
2944 /* free toolbar info data */
2945 COMCTL32_Free (infoPtr);
2947 return 0;
2951 static LRESULT
2952 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
2954 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2956 if (infoPtr->bTransparent)
2957 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
2959 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
2963 static LRESULT
2964 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2966 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2968 return infoPtr->hFont;
2972 static LRESULT
2973 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
2975 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2976 TBUTTON_INFO *btnPtr;
2977 POINT pt;
2978 INT nHit;
2979 HDC hdc;
2981 pt.x = (INT)LOWORD(lParam);
2982 pt.y = (INT)HIWORD(lParam);
2983 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
2985 if (nHit >= 0) {
2986 btnPtr = &infoPtr->buttons[nHit];
2987 if (!(btnPtr->fsState & TBSTATE_ENABLED))
2988 return 0;
2989 SetCapture (hwnd);
2990 infoPtr->bCaptured = TRUE;
2991 infoPtr->nButtonDown = nHit;
2993 btnPtr->fsState |= TBSTATE_PRESSED;
2995 hdc = GetDC (hwnd);
2996 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2997 ReleaseDC (hwnd, hdc);
2999 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3000 TOOLBAR_Customize (hwnd);
3002 return 0;
3006 static LRESULT
3007 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3009 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3010 TBUTTON_INFO *btnPtr;
3011 POINT pt;
3012 INT nHit;
3013 HDC hdc;
3015 if (infoPtr->hwndToolTip)
3016 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3017 WM_LBUTTONDOWN, wParam, lParam);
3019 pt.x = (INT)LOWORD(lParam);
3020 pt.y = (INT)HIWORD(lParam);
3021 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3023 if (nHit >= 0) {
3024 btnPtr = &infoPtr->buttons[nHit];
3025 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3026 return 0;
3028 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
3030 NMTOOLBARA nmtb;
3032 nmtb.hdr.hwndFrom = hwnd;
3033 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3034 nmtb.hdr.code = TBN_DROPDOWN;
3035 nmtb.iItem = btnPtr->idCommand;
3037 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3038 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3041 SetCapture (hwnd);
3042 infoPtr->bCaptured = TRUE;
3043 infoPtr->nButtonDown = nHit;
3044 infoPtr->nOldHit = nHit;
3046 btnPtr->fsState |= TBSTATE_PRESSED;
3048 hdc = GetDC (hwnd);
3049 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
3050 ReleaseDC (hwnd, hdc);
3053 return 0;
3056 static LRESULT
3057 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3059 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3060 TBUTTON_INFO *btnPtr;
3061 POINT pt;
3062 INT nHit;
3063 INT nOldIndex = -1;
3064 HDC hdc;
3065 BOOL bSendMessage = TRUE;
3067 if (infoPtr->hwndToolTip)
3068 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3069 WM_LBUTTONUP, wParam, lParam);
3071 pt.x = (INT)LOWORD(lParam);
3072 pt.y = (INT)HIWORD(lParam);
3073 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3075 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3076 infoPtr->bCaptured = FALSE;
3077 ReleaseCapture ();
3078 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3079 btnPtr->fsState &= ~TBSTATE_PRESSED;
3081 if (nHit == infoPtr->nButtonDown) {
3082 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3083 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3084 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3085 infoPtr->nButtonDown);
3086 if (nOldIndex == infoPtr->nButtonDown)
3087 bSendMessage = FALSE;
3088 if ((nOldIndex != infoPtr->nButtonDown) &&
3089 (nOldIndex != -1))
3090 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3091 btnPtr->fsState |= TBSTATE_CHECKED;
3093 else {
3094 if (btnPtr->fsState & TBSTATE_CHECKED)
3095 btnPtr->fsState &= ~TBSTATE_CHECKED;
3096 else
3097 btnPtr->fsState |= TBSTATE_CHECKED;
3101 else
3102 bSendMessage = FALSE;
3104 hdc = GetDC (hwnd);
3105 if (nOldIndex != -1)
3106 TOOLBAR_DrawButton (hwnd, &infoPtr->buttons[nOldIndex], hdc);
3107 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
3108 ReleaseDC (hwnd, hdc);
3110 if (bSendMessage) {
3111 SendMessageA (GetParent(hwnd), WM_COMMAND,
3112 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3114 if ((GetWindowLongA(hwnd, GWL_STYLE) & TBSTYLE_DROPDOWN) ||
3115 (btnPtr->fsStyle & 0x08/* BTNS_DROPDOWN */)) {
3116 NMTOOLBARW nmtb;
3118 nmtb.hdr.hwndFrom = hwnd;
3119 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3120 nmtb.hdr.code = TBN_DROPDOWN;
3121 nmtb.iItem = nHit;
3122 /* nmtb.tbButton not used with TBN_DROPDOWN */
3123 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) {
3124 nmtb.pszText = infoPtr->strings[btnPtr->iString];
3125 nmtb.cchText = lstrlenW(nmtb.pszText);
3126 } else {
3127 nmtb.pszText = NULL;
3128 nmtb.cchText = 0;
3130 nmtb.rcButton = btnPtr->rect;
3132 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
3133 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3136 infoPtr->nButtonDown = -1;
3137 infoPtr->nOldHit = -1;
3140 return 0;
3144 static LRESULT
3145 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3147 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3148 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3149 POINT pt;
3150 INT nHit;
3151 HDC hdc;
3153 if (infoPtr->hwndToolTip)
3154 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3155 WM_MOUSEMOVE, wParam, lParam);
3157 pt.x = (INT)LOWORD(lParam);
3158 pt.y = (INT)HIWORD(lParam);
3160 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3162 if (infoPtr->nOldHit != nHit)
3164 /* Remove the effect of an old hot button */
3165 if(infoPtr->nOldHit == infoPtr->nHotItem)
3167 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3168 oldBtnPtr->bHot = FALSE;
3170 InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
3173 /* It's not a separator or in nowhere. It's a hot button. */
3174 if (nHit >= 0)
3176 btnPtr = &infoPtr->buttons[nHit];
3177 btnPtr->bHot = TRUE;
3179 hdc = GetDC (hwnd);
3180 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
3181 ReleaseDC (hwnd, hdc);
3183 infoPtr->nHotItem = nHit;
3186 if (infoPtr->bCaptured) {
3187 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3188 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3189 btnPtr->fsState &= ~TBSTATE_PRESSED;
3190 hdc = GetDC (hwnd);
3191 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
3192 ReleaseDC (hwnd, hdc);
3194 else if (nHit == infoPtr->nButtonDown) {
3195 btnPtr->fsState |= TBSTATE_PRESSED;
3196 hdc = GetDC (hwnd);
3197 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
3198 ReleaseDC (hwnd, hdc);
3201 infoPtr->nOldHit = nHit;
3203 return 0;
3207 inline static LRESULT
3208 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3210 /* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3211 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3212 /* else */
3213 /* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3217 inline static LRESULT
3218 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3220 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3221 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3223 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3227 static LRESULT
3228 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3230 TOOLBAR_INFO *infoPtr;
3232 /* allocate memory for info structure */
3233 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3234 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3236 /* paranoid!! */
3237 infoPtr->dwStructSize = sizeof(TBBUTTON);
3239 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3240 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3241 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3242 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3245 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3249 static LRESULT
3250 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3252 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3253 RECT rcWindow;
3254 HDC hdc;
3256 if (dwStyle & WS_MINIMIZE)
3257 return 0; /* Nothing to do */
3259 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3261 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3262 return 0;
3264 if (!(dwStyle & CCS_NODIVIDER))
3266 GetWindowRect (hwnd, &rcWindow);
3267 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3268 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3271 ReleaseDC( hwnd, hdc );
3273 return 0;
3277 inline static LRESULT
3278 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3280 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3281 LPNMHDR lpnmh = (LPNMHDR)lParam;
3283 TRACE("passing WM_NOTIFY!\n");
3285 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3286 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3288 #if 0
3289 if (lpnmh->code == TTN_GETDISPINFOA) {
3290 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3292 FIXME("retrieving ASCII string\n");
3295 else if (lpnmh->code == TTN_GETDISPINFOW) {
3296 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3298 FIXME("retrieving UNICODE string\n");
3301 #endif
3304 return 0;
3308 static LRESULT
3309 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3311 HDC hdc;
3312 PAINTSTRUCT ps;
3314 TOOLBAR_CalcToolbar( hwnd );
3315 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
3316 TOOLBAR_Refresh (hwnd, hdc);
3317 if (!wParam)
3318 EndPaint (hwnd, &ps);
3319 return 0;
3323 static LRESULT
3324 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3326 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3327 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3328 RECT parent_rect;
3329 HWND parent;
3330 /* INT32 x, y; */
3331 INT cx, cy;
3332 INT flags;
3333 UINT uPosFlags = 0;
3335 /* Resize deadlock check */
3336 if (infoPtr->bAutoSize) {
3337 infoPtr->bAutoSize = FALSE;
3338 return 0;
3341 flags = (INT) wParam;
3343 /* FIXME for flags =
3344 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3347 TRACE("sizing toolbar!\n");
3349 if (flags == SIZE_RESTORED) {
3350 /* width and height don't apply */
3351 parent = GetParent (hwnd);
3352 GetClientRect(parent, &parent_rect);
3354 if (dwStyle & CCS_NORESIZE) {
3355 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3357 /* FIXME */
3358 /* infoPtr->nWidth = parent_rect.right - parent_rect.left; */
3359 cy = infoPtr->nHeight;
3360 cx = infoPtr->nWidth;
3361 TOOLBAR_CalcToolbar (hwnd);
3362 infoPtr->nWidth = cx;
3363 infoPtr->nHeight = cy;
3365 else {
3366 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3367 TOOLBAR_CalcToolbar (hwnd);
3368 cy = infoPtr->nHeight;
3369 cx = infoPtr->nWidth;
3372 if (dwStyle & CCS_NOPARENTALIGN) {
3373 uPosFlags |= SWP_NOMOVE;
3374 cy = infoPtr->nHeight;
3375 cx = infoPtr->nWidth;
3378 if (!(dwStyle & CCS_NODIVIDER))
3379 cy += GetSystemMetrics(SM_CYEDGE);
3381 SetWindowPos (hwnd, 0, parent_rect.left, parent_rect.top,
3382 cx, cy, uPosFlags | SWP_NOZORDER);
3384 return 0;
3388 static LRESULT
3389 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3391 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3393 if (nType == GWL_STYLE) {
3394 if (lpStyle->styleNew & TBSTYLE_LIST) {
3395 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3397 else {
3398 infoPtr->dwDTFlags = DT_CENTER;
3402 TOOLBAR_AutoSize (hwnd);
3404 InvalidateRect(hwnd, NULL, FALSE);
3406 return 0;
3411 static LRESULT WINAPI
3412 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3414 switch (uMsg)
3416 case TB_ADDBITMAP:
3417 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3419 case TB_ADDBUTTONSA:
3420 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3422 case TB_ADDBUTTONSW:
3423 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3425 case TB_ADDSTRINGA:
3426 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3428 case TB_ADDSTRINGW:
3429 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3431 case TB_AUTOSIZE:
3432 return TOOLBAR_AutoSize (hwnd);
3434 case TB_BUTTONCOUNT:
3435 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3437 case TB_BUTTONSTRUCTSIZE:
3438 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3440 case TB_CHANGEBITMAP:
3441 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3443 case TB_CHECKBUTTON:
3444 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3446 case TB_COMMANDTOINDEX:
3447 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3449 case TB_CUSTOMIZE:
3450 return TOOLBAR_Customize (hwnd);
3452 case TB_DELETEBUTTON:
3453 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3455 case TB_ENABLEBUTTON:
3456 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3458 case TB_GETANCHORHIGHLIGHT:
3459 return TOOLBAR_GetAnchorHighlight (hwnd);
3461 case TB_GETBITMAP:
3462 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3464 case TB_GETBITMAPFLAGS:
3465 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3467 case TB_GETBUTTON:
3468 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3470 case TB_GETBUTTONINFOA:
3471 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3473 case TB_GETBUTTONINFOW:
3474 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3476 case TB_GETBUTTONSIZE:
3477 return TOOLBAR_GetButtonSize (hwnd);
3479 case TB_GETBUTTONTEXTA:
3480 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3482 case TB_GETBUTTONTEXTW:
3483 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
3485 /* case TB_GETCOLORSCHEME: */ /* 4.71 */
3487 case TB_GETDISABLEDIMAGELIST:
3488 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3490 case TB_GETEXTENDEDSTYLE:
3491 return TOOLBAR_GetExtendedStyle (hwnd);
3493 case TB_GETHOTIMAGELIST:
3494 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3496 case TB_GETHOTITEM:
3497 return TOOLBAR_GetHotItem (hwnd);
3499 case TB_GETIMAGELIST:
3500 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3502 /* case TB_GETINSERTMARK: */ /* 4.71 */
3503 /* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
3505 case TB_GETITEMRECT:
3506 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3508 case TB_GETMAXSIZE:
3509 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3511 /* case TB_GETOBJECT: */ /* 4.71 */
3512 /* case TB_GETPADDING: */ /* 4.71 */
3514 case TB_GETRECT:
3515 return TOOLBAR_GetRect (hwnd, wParam, lParam);
3517 case TB_GETROWS:
3518 return TOOLBAR_GetRows (hwnd, wParam, lParam);
3520 case TB_GETSTATE:
3521 return TOOLBAR_GetState (hwnd, wParam, lParam);
3523 case TB_GETSTYLE:
3524 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3526 case TB_GETTEXTROWS:
3527 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3529 case TB_GETTOOLTIPS:
3530 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3532 case TB_GETUNICODEFORMAT:
3533 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3535 case CCM_GETVERSION:
3536 return TOOLBAR_GetVersion (hwnd);
3538 case TB_HIDEBUTTON:
3539 return TOOLBAR_HideButton (hwnd, wParam, lParam);
3541 case TB_HITTEST:
3542 return TOOLBAR_HitTest (hwnd, wParam, lParam);
3544 case TB_INDETERMINATE:
3545 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3547 case TB_INSERTBUTTONA:
3548 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3550 case TB_INSERTBUTTONW:
3551 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
3553 /* case TB_INSERTMARKHITTEST: */ /* 4.71 */
3555 case TB_ISBUTTONCHECKED:
3556 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3558 case TB_ISBUTTONENABLED:
3559 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3561 case TB_ISBUTTONHIDDEN:
3562 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3564 case TB_ISBUTTONHIGHLIGHTED:
3565 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3567 case TB_ISBUTTONINDETERMINATE:
3568 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3570 case TB_ISBUTTONPRESSED:
3571 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3573 case TB_LOADIMAGES: /* 4.70 */
3574 FIXME("missing standard imagelists\n");
3575 return 0;
3577 /* case TB_MAPACCELERATORA: */ /* 4.71 */
3578 /* case TB_MAPACCELERATORW: */ /* 4.71 */
3579 /* case TB_MARKBUTTON: */ /* 4.71 */
3580 /* case TB_MOVEBUTTON: */ /* 4.71 */
3582 case TB_PRESSBUTTON:
3583 return TOOLBAR_PressButton (hwnd, wParam, lParam);
3585 /* case TB_REPLACEBITMAP: */
3587 case TB_SAVERESTOREA:
3588 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3590 case TB_SAVERESTOREW:
3591 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
3593 case TB_SETANCHORHIGHLIGHT:
3594 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
3596 case TB_SETBITMAPSIZE:
3597 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3599 case TB_SETBUTTONINFOA:
3600 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3602 case TB_SETBUTTONINFOW:
3603 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
3605 case TB_SETBUTTONSIZE:
3606 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3608 case TB_SETBUTTONWIDTH:
3609 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3611 case TB_SETCMDID:
3612 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3614 /* case TB_SETCOLORSCHEME: */ /* 4.71 */
3616 case TB_SETDISABLEDIMAGELIST:
3617 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3619 case TB_SETDRAWTEXTFLAGS:
3620 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3622 case TB_SETEXTENDEDSTYLE:
3623 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3625 case TB_SETHOTIMAGELIST:
3626 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3628 case TB_SETHOTITEM:
3629 return TOOLBAR_SetHotItem (hwnd, wParam);
3631 case TB_SETIMAGELIST:
3632 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3634 case TB_SETINDENT:
3635 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3637 /* case TB_SETINSERTMARK: */ /* 4.71 */
3639 case TB_SETINSERTMARKCOLOR:
3640 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3642 case TB_SETMAXTEXTROWS:
3643 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3645 /* case TB_SETPADDING: */ /* 4.71 */
3647 case TB_SETPARENT:
3648 return TOOLBAR_SetParent (hwnd, wParam, lParam);
3650 case TB_SETROWS:
3651 return TOOLBAR_SetRows (hwnd, wParam, lParam);
3653 case TB_SETSTATE:
3654 return TOOLBAR_SetState (hwnd, wParam, lParam);
3656 case TB_SETSTYLE:
3657 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3659 case TB_SETTOOLTIPS:
3660 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3662 case TB_SETUNICODEFORMAT:
3663 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3665 case CCM_SETVERSION:
3666 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
3669 /* case WM_CHAR: */
3671 case WM_CREATE:
3672 return TOOLBAR_Create (hwnd, wParam, lParam);
3674 case WM_DESTROY:
3675 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3677 case WM_ERASEBKGND:
3678 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
3680 case WM_GETFONT:
3681 return TOOLBAR_GetFont (hwnd, wParam, lParam);
3683 /* case WM_KEYDOWN: */
3684 /* case WM_KILLFOCUS: */
3686 case WM_LBUTTONDBLCLK:
3687 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
3689 case WM_LBUTTONDOWN:
3690 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
3692 case WM_LBUTTONUP:
3693 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
3695 case WM_MOUSEMOVE:
3696 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
3698 case WM_NCACTIVATE:
3699 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
3701 case WM_NCCALCSIZE:
3702 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
3704 case WM_NCCREATE:
3705 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3707 case WM_NCPAINT:
3708 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
3710 case WM_NOTIFY:
3711 return TOOLBAR_Notify (hwnd, wParam, lParam);
3713 /* case WM_NOTIFYFORMAT: */
3715 case WM_PAINT:
3716 return TOOLBAR_Paint (hwnd, wParam);
3718 case WM_SIZE:
3719 return TOOLBAR_Size (hwnd, wParam, lParam);
3721 case WM_STYLECHANGED:
3722 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
3724 /* case WM_SYSCOLORCHANGE: */
3726 /* case WM_WININICHANGE: */
3728 case WM_CHARTOITEM:
3729 case WM_COMMAND:
3730 case WM_DRAWITEM:
3731 case WM_MEASUREITEM:
3732 case WM_VKEYTOITEM:
3733 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
3735 default:
3736 if (uMsg >= WM_USER)
3737 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
3738 uMsg, wParam, lParam);
3739 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3741 return 0;
3745 VOID
3746 TOOLBAR_Register (void)
3748 WNDCLASSA wndClass;
3750 if (GlobalFindAtomA (TOOLBARCLASSNAMEA)) return;
3752 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
3753 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
3754 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
3755 wndClass.cbClsExtra = 0;
3756 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
3757 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
3758 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
3759 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
3761 RegisterClassA (&wndClass);
3765 VOID
3766 TOOLBAR_Unregister (void)
3768 if (GlobalFindAtomA (TOOLBARCLASSNAMEA))
3769 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);