source: trunk/src/comctl32/toolbar.cpp@ 3956

Last change on this file since 3956 was 3956, checked in by sandervl, 25 years ago

PD: Updated comctl32/toolbar to Wine 20000801

File size: 102.6 KB
Line 
1/*
2 * Toolbar control
3 *
4 * Copyright 1998,1999 Eric Kohl
5 * Copyright 1999 Achim Hasenmueller
6 * Copyright 1999 Christoph Bratschi
7 *
8 * TODO:
9 * - A little bug in TOOLBAR_DrawMasked()
10 * - Button wrapping (under construction).
11 * - Messages.
12 * - Notifications (under construction).
13 * - Fix TB_SETROWS.
14 * - Tooltip support (almost complete).
15 * - Unicode suppport (under construction).
16 * - Fix TOOLBAR_SetButtonInfo32A/W.
17 * - Customize dialog (under construction).
18 * - TBSTYLE_AUTOSIZE for toolbar and buttons.
19 * - I_IMAGECALLBACK support.
20 *
21 * Testing:
22 * - Run tests using Waite Group Windows95 API Bible Volume 2.
23 * The second cdrom contains executables addstr.exe, btncount.exe,
24 * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
25 * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
26 * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
27 * setparnt.exe, setrows.exe, toolwnd.exe.
28 * - Microsofts controlspy examples.
29 */
30
31/*
32 - (WINE 20000608 level)
33*/
34
35
36#include <string.h>
37
38#include "winbase.h"
39#include "commctrl.h"
40#include "cache.h"
41#include "comctl32.h"
42#include "ccbase.h"
43#include "toolbar.h"
44
45#define SEPARATOR_WIDTH 8
46#define TOP_BORDER 2
47#define BOTTOM_BORDER 2
48
49#define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
50
51static BOOL
52TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
53{
54 if ((index>=0) && (index < infoPtr->nNumBitmaps))
55 return TRUE;
56 else
57 return FALSE;
58}
59
60
61static void
62TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
63{
64 INT x = (lpRect->left + lpRect->right) / 2 - 1;
65 INT yBottom = lpRect->bottom - 3;
66 INT yTop = lpRect->top + 1;
67
68 SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
69 MoveToEx (hdc, x, yBottom, NULL);
70 LineTo (hdc, x, yTop);
71 x++;
72 SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
73 MoveToEx (hdc, x, yBottom, NULL);
74 LineTo (hdc, x, yTop);
75}
76
77/*
78 * Draw the text string for this button.
79 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
80 * is non-zero, so we can simply check himlDef to see if we have
81 * an image list
82 */
83static void
84TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
85 HDC hdc, INT nState, DWORD dwStyle)
86{
87 RECT rcText = btnPtr->rect;
88 HFONT hOldFont;
89 INT nOldBkMode;
90 COLORREF clrOld;
91 LPWSTR lpText = NULL;
92 HIMAGELIST himl = infoPtr->himlDef;
93
94 // TRACE ("iString: %x\n", btnPtr->iString);
95
96 /* get a pointer to the text */
97 if (btnPtr->iString == -1)
98 dprintf(("TOOLBAR_DrawString: Undocumented Index -1\n"));
99 else if (HIWORD(btnPtr->iString) != 0)
100 lpText = (LPWSTR)btnPtr->iString;
101 else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
102 lpText = infoPtr->strings[btnPtr->iString];
103
104 // TRACE ("lpText: \"%s\"\n", debugstr_w(lpText));
105
106 /* draw text */
107 if (lpText) {
108
109 InflateRect (&rcText, -3, -3);
110
111 if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
112 if ((dwStyle & TBSTYLE_LIST) &&
113 ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
114 (btnPtr->iBitmap != I_IMAGENONE)) {
115 rcText.left += infoPtr->nBitmapWidth;
116 }
117 else {
118 rcText.top += infoPtr->nBitmapHeight;
119 }
120 }
121
122 if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
123 OffsetRect (&rcText, 1, 1);
124
125 hOldFont = SelectObject (hdc, infoPtr->hFont);
126 nOldBkMode = SetBkMode (hdc, TRANSPARENT);
127 if (!(nState & TBSTATE_ENABLED)) {
128 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
129 OffsetRect (&rcText, 1, 1);
130 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
131 SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
132 OffsetRect (&rcText, -1, -1);
133 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
134 }
135 else if (nState & TBSTATE_INDETERMINATE) {
136 clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
137 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
138 }
139 else {
140 clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
141 DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
142 }
143
144 SetTextColor (hdc, clrOld);
145 SelectObject (hdc, hOldFont);
146 if (nOldBkMode != TRANSPARENT)
147 SetBkMode (hdc, nOldBkMode);
148 }
149}
150
151
152static void
153TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
154{
155 HBRUSH hbr = SelectObject (hdc, GetPattern55AABrush ());
156 INT cx = lpRect->right - lpRect->left;
157 INT cy = lpRect->bottom - lpRect->top;
158 PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
159 SelectObject (hdc, hbr);
160}
161
162
163static void
164TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
165 HDC hdc, INT x, INT y)
166{
167 /* FIXME: this function is a hack since it uses image list
168 internals directly */
169
170 HIMAGELIST himl = infoPtr->himlDef;
171 HBITMAP hbmMask;
172 HDC hdcImageList;
173 HDC hdcMask;
174
175 if (!himl)
176 return;
177
178 /* create new dc's */
179 hdcImageList = CreateCompatibleDC (0);
180 hdcMask = CreateCompatibleDC (0);
181
182 /* create new bitmap */
183 hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
184 SelectObject (hdcMask, hbmMask);
185
186 /* copy the mask bitmap */
187 SelectObject (hdcImageList, himl->hbmMask);
188 SetBkColor (hdcImageList, RGB(255, 255, 255));
189 SetTextColor (hdcImageList, RGB(0, 0, 0));
190 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
191 hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
192
193#if 0
194 /* add white mask from image */
195 SelectObject (hdcImageList, himl->hbmImage);
196 SetBkColor (hdcImageList, RGB(0, 0, 0));
197 BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
198 hdcImageList, himl->cx * btnPtr->iBitmap, 0, MERGEPAINT);
199#endif
200
201 /* draw the new mask */
202 SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
203 BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
204 hdcMask, 0, 0, 0xB8074A);
205
206 SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
207 BitBlt (hdc, x, y, himl->cx, himl->cy,
208 hdcMask, 0, 0, 0xB8074A);
209
210 DeleteObject (hbmMask);
211 DeleteDC (hdcMask);
212 DeleteDC (hdcImageList);
213}
214
215
216static void
217TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
218{
219 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
220 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
221 RECT rc;
222
223 if (btnPtr->fsState & TBSTATE_HIDDEN)
224 return;
225
226 rc = btnPtr->rect;
227
228 // TRACE("iBitmap: %d\n", btnPtr->iBitmap);
229
230 /* separator */
231 if (btnPtr->fsStyle & TBSTYLE_SEP) {
232 /* with the FLAT style, iBitmap is the width and has already */
233 /* been taken into consideration in calculating the width */
234 /* so now we need to draw the vertical separator */
235 /* empirical tests show that iBitmap can/will be non-zero */
236 /* when drawing the vertical bar... */
237 if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
238 TOOLBAR_DrawFlatSeparator (&rc, hdc);
239 return;
240 }
241
242 /* disabled */
243 if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
244 if (!(dwStyle & TBSTYLE_FLAT))
245 DrawEdge (hdc, &rc, EDGE_RAISED,
246 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
247
248 if (infoPtr->himlDis &&
249 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
250 ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
251 rc.left+1, rc.top+1, ILD_NORMAL);
252 else
253 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
254
255 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
256 return;
257 }
258
259 /* pressed TBSTYLE_BUTTON */
260 if (btnPtr->fsState & TBSTATE_PRESSED) {
261 if (dwStyle & TBSTYLE_FLAT)
262 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
263 else
264 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
265 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
266 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
267 rc.left+2, rc.top+2, ILD_NORMAL);
268 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
269 return;
270 }
271
272 /* checked TBSTYLE_CHECK */
273 if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
274 (btnPtr->fsState & TBSTATE_CHECKED)) {
275 if (dwStyle & TBSTYLE_FLAT)
276 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
277 BF_RECT | BF_MIDDLE | BF_ADJUST);
278 else
279 DrawEdge (hdc, &rc, EDGE_SUNKEN,
280 BF_RECT | BF_MIDDLE | BF_ADJUST);
281
282 TOOLBAR_DrawPattern (hdc, &rc);
283
284 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
285 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
286 rc.left+2, rc.top+2, ILD_NORMAL);
287
288 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
289 return;
290 }
291
292 /* indeterminate */
293 if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
294 DrawEdge (hdc, &rc, EDGE_RAISED,
295 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
296
297 TOOLBAR_DrawPattern (hdc, &rc);
298 TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
299 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
300 return;
301 }
302
303 /* normal state */
304 if (dwStyle & TBSTYLE_FLAT)
305 {
306 if (btnPtr->bHot)
307 DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
308 if (btnPtr->bHot && infoPtr->himlHot &&
309 TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
310 ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
311 rc.left +2, rc.top +2, ILD_NORMAL);
312 else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
313 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
314 rc.left +2, rc.top +2, ILD_NORMAL);
315 }
316 else
317 {
318 DrawEdge (hdc, &rc, EDGE_RAISED,
319 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
320
321 if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
322 ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
323 rc.left+1, rc.top+1, ILD_NORMAL);
324 }
325
326 TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
327}
328
329
330static void
331TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
332{
333 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
334 TBUTTON_INFO *btnPtr;
335 INT i;
336 RECT rcTemp;
337
338 /* redraw necessary buttons */
339 btnPtr = infoPtr->buttons;
340 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
341 {
342 if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
343 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
344 }
345}
346
347static void
348TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
349{
350 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
351 TBUTTON_INFO *btnPtr;
352 HDC hdc;
353 HFONT hOldFont;
354
355 lpSize->cx = 0;
356 lpSize->cy = 0;
357 hdc = GetDC (0);
358 hOldFont = SelectObject (hdc, infoPtr->hFont);
359
360 btnPtr = &infoPtr->buttons[index];
361
362 if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
363 (btnPtr->iString > -1) &&
364 (btnPtr->iString < infoPtr->nNumStrings))
365 {
366 LPWSTR lpText = infoPtr->strings[btnPtr->iString];
367 GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
368 }
369
370 SelectObject (hdc, hOldFont);
371 ReleaseDC (0, hdc);
372
373 // TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
374}
375
376static void
377TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
378{
379 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
380 TBUTTON_INFO *btnPtr;
381 INT i;
382 SIZE sz;
383
384
385 lpSize->cx = 0;
386 lpSize->cy = 0;
387
388 btnPtr = infoPtr->buttons;
389 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
390 TOOLBAR_MeasureString(hwnd,i,&sz);
391 if (sz.cx > lpSize->cx)
392 lpSize->cx = sz.cx;
393 if (sz.cy > lpSize->cy)
394 lpSize->cy = sz.cy;
395 }
396
397 // TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
398}
399
400/***********************************************************************
401* TOOLBAR_WrapToolbar
402*
403* This function walks through the buttons and seperators in the
404* toolbar, and sets the TBSTATE_WRAP flag only on those items where
405* wrapping should occur based on the width of the toolbar window.
406* It does *not* calculate button placement itself. That task
407* takes place in TOOLBAR_CalcToolbar. If the program wants to manage
408* the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
409* flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
410*/
411
412static void
413TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
414{
415 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
416 TBUTTON_INFO *btnPtr;
417 INT x, cx, i, j;
418 RECT rc;
419 BOOL bWrap, bButtonWrap;
420
421 /* When the toolbar window style is not TBSTYLE_WRAPABLE, */
422 /* no layout is necessary. Applications may use this style */
423 /* to perform their own layout on the toolbar. */
424 if( !(dwStyle & TBSTYLE_WRAPABLE) )
425 return;
426
427 btnPtr = infoPtr->buttons;
428 x = infoPtr->nIndent;
429
430 /* this can get the parents width, to know how far we can extend
431 * this toolbar. We cannot use its height, as there may be multiple
432 * toolbars in a rebar control
433 */
434 GetClientRect( GetParent(hwnd), &rc );
435 infoPtr->nWidth = rc.right - rc.left;
436 bButtonWrap = FALSE;
437
438 for (i = 0; i < infoPtr->nNumButtons; i++ )
439 {
440 bWrap = FALSE;
441 btnPtr[i].fsState &= ~TBSTATE_WRAP;
442
443 if (btnPtr[i].fsState & TBSTATE_HIDDEN)
444 continue;
445
446 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
447 /* it is the actual width of the separator. This is used for */
448 /* custom controls in toolbars. */
449 if (btnPtr[i].fsStyle & TBSTYLE_SEP)
450 cx = (btnPtr[i].iBitmap > 0) ?
451 btnPtr[i].iBitmap : SEPARATOR_WIDTH;
452 else
453 cx = infoPtr->nButtonWidth;
454
455 /* Two or more adjacent separators form a separator group. */
456 /* The first separator in a group should be wrapped to the */
457 /* next row if the previous wrapping is on a button. */
458 if( bButtonWrap &&
459 (btnPtr[i].fsStyle & TBSTYLE_SEP) &&
460 (i + 1 < infoPtr->nNumButtons ) &&
461 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) )
462 {
463 btnPtr[i].fsState |= TBSTATE_WRAP;
464 x = infoPtr->nIndent;
465 i++;
466 bButtonWrap = FALSE;
467 continue;
468 }
469
470 /* The layout makes sure the bitmap is visible, but not the button. */
471 if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
472 > infoPtr->nWidth )
473 {
474 BOOL bFound = FALSE;
475
476 /* If the current button is a separator and not hidden, */
477 /* go to the next until it reaches a non separator. */
478 /* Wrap the last separator if it is before a button. */
479 while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) ||
480 (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
481 i < infoPtr->nNumButtons )
482 {
483 i++;
484 bFound = TRUE;
485 }
486
487 if( bFound && i < infoPtr->nNumButtons )
488 {
489 i--;
490 btnPtr[i].fsState |= TBSTATE_WRAP;
491 x = infoPtr->nIndent;
492 bButtonWrap = FALSE;
493 continue;
494 }
495 else if ( i >= infoPtr->nNumButtons)
496 break;
497
498 /* If the current button is not a separator, find the last */
499 /* separator and wrap it. */
500 for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
501 {
502 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
503 !(btnPtr[j].fsState & TBSTATE_HIDDEN))
504 {
505 bFound = TRUE;
506 i = j;
507 x = infoPtr->nIndent;
508 btnPtr[j].fsState |= TBSTATE_WRAP;
509 bButtonWrap = FALSE;
510 break;
511 }
512 }
513
514 /* If no separator available for wrapping, wrap one of */
515 /* non-hidden previous button. */
516 if (!bFound)
517 {
518 for ( j = i - 1;
519 j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
520 {
521 if (btnPtr[j].fsState & TBSTATE_HIDDEN)
522 continue;
523
524 bFound = TRUE;
525 i = j;
526 x = infoPtr->nIndent;
527 btnPtr[j].fsState |= TBSTATE_WRAP;
528 bButtonWrap = TRUE;
529 break;
530 }
531 }
532
533 /* If all above failed, wrap the current button. */
534 if (!bFound)
535 {
536 btnPtr[i].fsState |= TBSTATE_WRAP;
537 bFound = TRUE;
538 x = infoPtr->nIndent;
539 if (btnPtr[i].fsState & TBSTYLE_SEP )
540 bButtonWrap = FALSE;
541 else
542 bButtonWrap = TRUE;
543 }
544 }
545 else
546 x += cx;
547 }
548}
549
550/***********************************************************************
551* TOOLBAR_CalcToolbar
552*
553* This function calculates button and separator placement. It first
554* calculates the button sizes, gets the toolbar window width and then
555* calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
556* on. It assigns a new location to each item and sends this location to
557* the tooltip window if appropriate. Finally, it updates the rcBound
558* rect and calculates the new required toolbar window height.
559*/
560
561static void
562TOOLBAR_CalcToolbar (HWND hwnd)
563{
564 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
565 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
566 TBUTTON_INFO *btnPtr;
567 INT i, nRows, nSepRows;
568 INT x, y, cx, cy;
569 SIZE sizeString;
570 BOOL bWrap;
571
572 TOOLBAR_CalcStrings (hwnd, &sizeString);
573
574 if (dwStyle & TBSTYLE_LIST) {
575 infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
576 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
577 }
578 else {
579 BOOL usesBitmaps = FALSE;
580 INT i;
581
582 for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
583 if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
584 usesBitmaps = TRUE;
585
586 if (sizeString.cy > 0) {
587 if (usesBitmaps)
588 infoPtr->nButtonHeight = sizeString.cy + infoPtr->nBitmapHeight + 6;
589 else
590 infoPtr->nButtonHeight = sizeString.cy + 6;
591 }
592 else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
593 infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
594
595 if (sizeString.cx > infoPtr->nBitmapWidth)
596 infoPtr->nButtonWidth = sizeString.cx + 6;
597 else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
598 infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
599 }
600
601 if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
602 infoPtr->nButtonWidth = infoPtr->cxMin;
603 if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
604 infoPtr->nButtonWidth = infoPtr->cxMax;
605
606 TOOLBAR_WrapToolbar( hwnd, dwStyle );
607
608 x = infoPtr->nIndent;
609 y = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
610
611 /*
612 * We wills et the height below, and we set the width on entry
613 * so we do not reset them here..
614 */
615#if 0
616 GetClientRect( hwnd, &rc );
617 /* get initial values for toolbar */
618 infoPtr->nWidth = rc.right - rc.left;
619 infoPtr->nHeight = rc.bottom - rc.top;
620#endif
621
622 /* from above, minimum is a button, and possible text */
623 cx = infoPtr->nButtonWidth;
624 /* cannot use just ButtonHeight, we may have no buttons! */
625 if (infoPtr->nNumButtons > 0)
626 infoPtr->nHeight = infoPtr->nButtonHeight;
627 cy = infoPtr->nHeight;
628
629 nRows = nSepRows = 0;
630
631 infoPtr->rcBound.top = y;
632 infoPtr->rcBound.left = x;
633 infoPtr->rcBound.bottom = y + cy;
634 infoPtr->rcBound.right = x;
635
636 btnPtr = infoPtr->buttons;
637
638 /* do not base height/width on parent, if the parent is a */
639 /* rebar control it could have multiple rows of toolbars */
640/* GetClientRect( GetParent(hwnd), &rc ); */
641/* cx = rc.right - rc.left; */
642/* cy = rc.bottom - rc.top; */
643
644 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
645 {
646 bWrap = FALSE;
647 if (btnPtr->fsState & TBSTATE_HIDDEN)
648 {
649 SetRectEmpty (&btnPtr->rect);
650 continue;
651 }
652
653 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
654 /* it is the actual width of the separator. This is used for */
655 /* custom controls in toolbars. */
656 if (btnPtr->fsStyle & TBSTYLE_SEP)
657 cx = (btnPtr->iBitmap > 0) ?
658 btnPtr->iBitmap : SEPARATOR_WIDTH;
659 else {
660 if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE)
661 {
662 SIZE sz;
663 TOOLBAR_MeasureString(hwnd,i,&sz);
664 cx = sz.cx + 6;
665 }
666 else
667 cx = infoPtr->nButtonWidth;
668 }
669 cy = infoPtr->nHeight;
670
671 if (btnPtr->fsState & TBSTATE_WRAP )
672 bWrap = TRUE;
673
674 SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
675
676 if (infoPtr->rcBound.left > x)
677 infoPtr->rcBound.left = x;
678 if (infoPtr->rcBound.right < x + cx)
679 infoPtr->rcBound.right = x + cx;
680 if (infoPtr->rcBound.bottom < y + cy)
681 infoPtr->rcBound.bottom = y + cy;
682
683 /* Set the toolTip only for non-hidden, non-separator button */
684 if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP ))
685 {
686 TTTOOLINFOA ti;
687
688 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
689 ti.cbSize = sizeof(TTTOOLINFOA);
690 ti.hwnd = hwnd;
691 ti.uId = btnPtr->idCommand;
692 ti.rect = btnPtr->rect;
693 SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
694 0, (LPARAM)&ti);
695 }
696
697 /* btnPtr->nRow is zero based. The space between the rows is */
698 /* also considered as a row. */
699 btnPtr->nRow = nRows + nSepRows;
700 if( bWrap )
701 {
702 if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
703 y += cy;
704 else
705 {
706 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
707 /* it is the actual width of the separator. This is used for */
708 /* custom controls in toolbars. */
709 y += cy + ( (btnPtr->iBitmap > 0 ) ?
710 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3;
711
712 /* nSepRows is used to calculate the extra height follwoing */
713 /* the last row. */
714 nSepRows++;
715 }
716 x = infoPtr->nIndent;
717 nRows++;
718 }
719 else
720 x += cx;
721 }
722
723 /* infoPtr->nRows is the number of rows on the toolbar */
724 infoPtr->nRows = nRows + nSepRows + 1;
725
726 /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
727 /* the last row. */
728 infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
729 nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
730 nSepRows * (infoPtr->nBitmapHeight + 1) +
731 BOTTOM_BORDER;
732 // TRACE("toolbar height %d\n", infoPtr->nHeight);
733}
734
735
736static INT
737TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
738{
739 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
740 TBUTTON_INFO *btnPtr;
741 INT i;
742
743 btnPtr = infoPtr->buttons;
744 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
745 if (btnPtr->fsState & TBSTATE_HIDDEN)
746 continue;
747
748 if (btnPtr->fsStyle & TBSTYLE_SEP) {
749 if (PtInRect (&btnPtr->rect, *lpPt)) {
750 // TRACE(" ON SEPARATOR %d!\n", i);
751 return -i;
752 }
753 }
754 else {
755 if (PtInRect (&btnPtr->rect, *lpPt)) {
756 // TRACE(" ON BUTTON %d!\n", i);
757 return i;
758 }
759 }
760 }
761
762 // TRACE(" NOWHERE!\n");
763 return -1;
764}
765
766
767static INT
768TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
769{
770 TBUTTON_INFO *btnPtr;
771 INT i;
772
773 btnPtr = infoPtr->buttons;
774 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
775 if (btnPtr->idCommand == idCommand) {
776 // TRACE("command=%d index=%d\n", idCommand, i);
777 return i;
778 }
779 }
780 // TRACE("no index found for command=%d\n", idCommand);
781 return -1;
782}
783
784
785static INT
786TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
787{
788 TBUTTON_INFO *btnPtr;
789 INT nRunIndex;
790
791 if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
792 return -1;
793
794 /* check index button */
795 btnPtr = &infoPtr->buttons[nIndex];
796 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
797 if (btnPtr->fsState & TBSTATE_CHECKED)
798 return nIndex;
799 }
800
801 /* check previous buttons */
802 nRunIndex = nIndex - 1;
803 while (nRunIndex >= 0) {
804 btnPtr = &infoPtr->buttons[nRunIndex];
805 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
806 if (btnPtr->fsState & TBSTATE_CHECKED)
807 return nRunIndex;
808 }
809 else
810 break;
811 nRunIndex--;
812 }
813
814 /* check next buttons */
815 nRunIndex = nIndex + 1;
816 while (nRunIndex < infoPtr->nNumButtons) {
817 btnPtr = &infoPtr->buttons[nRunIndex];
818 if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
819 if (btnPtr->fsState & TBSTATE_CHECKED)
820 return nRunIndex;
821 }
822 else
823 break;
824 nRunIndex++;
825 }
826
827 return -1;
828}
829
830
831static VOID
832TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
833 WPARAM wParam, LPARAM lParam)
834{
835 MSG msg;
836
837 msg.hwnd = hwndMsg;
838 msg.message = uMsg;
839 msg.wParam = wParam;
840 msg.lParam = lParam;
841 msg.time = GetMessageTime ();
842 msg.pt.x = LOWORD(GetMessagePos ());
843 msg.pt.y = HIWORD(GetMessagePos ());
844
845 SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
846}
847
848
849/***********************************************************************
850 * TOOLBAR_CustomizeDialogProc
851 * This function implements the toolbar customization dialog.
852 */
853static BOOL WINAPI
854TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
855{
856 TOOLBAR_INFO *infoPtr = (TOOLBAR_INFO *)GetWindowLongA (hwnd, DWL_USER);
857 static HDSA hDsa = NULL;
858
859 switch (uMsg)
860 {
861 case WM_INITDIALOG:
862 infoPtr = (TOOLBAR_INFO *)lParam;
863 SetWindowLongA (hwnd, DWL_USER, (DWORD)infoPtr);
864
865 hDsa = DSA_Create (sizeof(TBUTTON_INFO), 5);
866
867 if (infoPtr)
868 {
869 TBUTTON_INFO *btnPtr;
870 INT i;
871
872 /* insert 'virtual' separator button into 'available buttons' list */
873 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
874
875 /* copy all buttons and append them to the right listbox */
876 btnPtr = infoPtr->buttons;
877 for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
878 {
879 DSA_InsertItem (hDsa, i, btnPtr);
880
881 /* FIXME: hidden buttons appear in the 'toolbar buttons' list too */
882 if (btnPtr->fsState & TBSTATE_HIDDEN)
883 {
884 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
885 }
886 else
887 {
888 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)"");
889 }
890 }
891
892 /* append 'virtual' separator button to the 'toolbar buttons' list */
893 /* TODO */
894 }
895 return TRUE;
896
897 case WM_CLOSE:
898 EndDialog(hwnd, FALSE);
899 return TRUE;
900
901 case WM_COMMAND:
902 switch (LOWORD(wParam))
903 {
904 case IDCANCEL:
905 EndDialog(hwnd, FALSE);
906 break;
907 }
908 return TRUE;
909
910 case WM_DESTROY:
911 if (hDsa)
912 DSA_Destroy (hDsa);
913 return TRUE;
914
915 case WM_DRAWITEM:
916 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
917 {
918 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
919 TBUTTON_INFO btnPtr;
920 RECT rcButton;
921 RECT rcText;
922 HPEN hOldPen;
923 HBRUSH hOldBrush;
924 COLORREF oldText = 0;
925 COLORREF oldBk = 0;
926
927 // FIXME("action: %x itemState: %x\n",
928 // lpdis->itemAction, lpdis->itemState);
929
930 DSA_GetItem (hDsa, 0 /*lpdis->itemID*/, &btnPtr);
931
932 if (lpdis->itemState & ODS_FOCUS)
933 {
934 oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
935 oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
936 }
937
938 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
939 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
940
941 /* fill background rectangle */
942 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
943 lpdis->rcItem.right, lpdis->rcItem.bottom);
944
945 /* calculate button and text rectangles */
946 CopyRect (&rcButton, &lpdis->rcItem);
947 InflateRect (&rcButton, -1, -1);
948 CopyRect (&rcText, &rcButton);
949 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
950 rcText.left = rcButton.right + 2;
951
952 /* draw focus rectangle */
953 if (lpdis->itemState & ODS_FOCUS)
954 DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
955
956 /* draw button */
957 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
958
959 /* draw image and text */
960 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
961 {
962 /* virtual separator in the 'available' list */
963 DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
964 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
965 }
966 else
967 {
968 /* real button */
969
970 ImageList_Draw (infoPtr->himlDef, btnPtr.iBitmap, lpdis->hDC,
971 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
972
973 DrawTextW (lpdis->hDC, infoPtr->strings[btnPtr.iString], -1, &rcText,
974 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
975
976 }
977
978 if (lpdis->itemState & ODS_FOCUS)
979 {
980 SetBkColor (lpdis->hDC, oldBk);
981 SetTextColor (lpdis->hDC, oldText);
982 }
983
984 SelectObject (lpdis->hDC, hOldBrush);
985 SelectObject (lpdis->hDC, hOldPen);
986
987 return TRUE;
988 }
989 return FALSE;
990
991 case WM_MEASUREITEM:
992 if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
993 {
994 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
995
996 if (infoPtr)
997 lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
998 else
999 lpmis->itemHeight = 15 + 8; /* default height */
1000
1001 return TRUE;
1002 }
1003 return FALSE;
1004
1005 default:
1006 return FALSE;
1007 }
1008}
1009
1010
1011/***********************************************************************
1012 * TOOLBAR_AddBitmap: Add the bitmaps to the default image list.
1013 *
1014 */
1015static LRESULT
1016TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1017{
1018 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1019 LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1020 INT nIndex = 0, nButtons, nCount;
1021 HBITMAP hbmLoad;
1022
1023 // TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1024 if (!lpAddBmp)
1025 return -1;
1026
1027 if (lpAddBmp->hInst == HINST_COMMCTRL)
1028 {
1029 if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1030 nButtons = 15;
1031 else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1032 nButtons = 13;
1033 else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1034 nButtons = 5;
1035 else
1036 return -1;
1037
1038 // TRACE ("adding %d internal bitmaps!\n", nButtons);
1039
1040 /* Windows resize all the buttons to the size of a newly added standard image */
1041 if (lpAddBmp->nID & 1)
1042 {
1043 /* large icons */
1044 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1045 MAKELPARAM((WORD)26, (WORD)26));
1046 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1047 MAKELPARAM((WORD)33, (WORD)33));
1048 }
1049 else
1050 {
1051 /* small icons */
1052 SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1053 MAKELPARAM((WORD)16, (WORD)16));
1054 SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1055 MAKELPARAM((WORD)22, (WORD)22));
1056 }
1057
1058 TOOLBAR_CalcToolbar (hwnd);
1059 }
1060 else
1061 {
1062 nButtons = (INT)wParam;
1063 if (nButtons <= 0)
1064 return -1;
1065
1066 // TRACE ("adding %d bitmaps!\n", nButtons);
1067 }
1068
1069 if (!(infoPtr->himlDef)) {
1070 /* create new default image list */
1071 // TRACE ("creating default image list!\n");
1072
1073 infoPtr->himlDef =
1074 ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1075 ILC_COLOR | ILC_MASK, nButtons, 2);
1076 infoPtr->himlInt = infoPtr->himlDef;
1077 }
1078
1079 nCount = ImageList_GetImageCount(infoPtr->himlDef);
1080
1081 /* Add bitmaps to the default image list */
1082 if (lpAddBmp->hInst == (HINSTANCE)0)
1083 {
1084 nIndex =
1085 ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1086 CLR_DEFAULT);
1087 }
1088 else if (lpAddBmp->hInst == HINST_COMMCTRL)
1089 {
1090 /* Add system bitmaps */
1091 switch (lpAddBmp->nID)
1092 {
1093 case IDB_STD_SMALL_COLOR:
1094 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1095 MAKEINTRESOURCEA(IDB_STD_SMALL));
1096 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1097 hbmLoad, CLR_DEFAULT);
1098 DeleteObject (hbmLoad);
1099 break;
1100
1101 case IDB_STD_LARGE_COLOR:
1102 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1103 MAKEINTRESOURCEA(IDB_STD_LARGE));
1104 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1105 hbmLoad, CLR_DEFAULT);
1106 DeleteObject (hbmLoad);
1107 break;
1108
1109 case IDB_VIEW_SMALL_COLOR:
1110 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1111 MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1112 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1113 hbmLoad, CLR_DEFAULT);
1114 DeleteObject (hbmLoad);
1115 break;
1116
1117 case IDB_VIEW_LARGE_COLOR:
1118 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1119 MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1120 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1121 hbmLoad, CLR_DEFAULT);
1122 DeleteObject (hbmLoad);
1123 break;
1124
1125 case IDB_HIST_SMALL_COLOR:
1126 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1127 MAKEINTRESOURCEA(IDB_HIST_SMALL));
1128 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1129 hbmLoad, CLR_DEFAULT);
1130 DeleteObject (hbmLoad);
1131 break;
1132
1133 case IDB_HIST_LARGE_COLOR:
1134 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1135 MAKEINTRESOURCEA(IDB_HIST_LARGE));
1136 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1137 hbmLoad, CLR_DEFAULT);
1138 DeleteObject (hbmLoad);
1139 break;
1140
1141 default:
1142 nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1143 // ERR ("invalid imagelist!\n");
1144 break;
1145 }
1146 }
1147 else
1148 {
1149 hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1150 nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1151 DeleteObject (hbmLoad);
1152 }
1153
1154 if (nIndex != -1)
1155 {
1156 INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1157
1158 if (infoPtr->nNumBitmaps + nButtons != imagecount)
1159 {
1160 dprintf(("TOOLBAR_AddBitmap: Desired images do not match recieved images : Previous image number %i Previous images in list %i added %i expecting total %i, Images in list %i\n",
1161 infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1162 infoPtr->nNumBitmaps+nButtons,imagecount));
1163
1164 infoPtr->nNumBitmaps = imagecount;
1165 }
1166 else
1167 infoPtr->nNumBitmaps += nButtons;
1168 }
1169
1170 return nIndex;
1171}
1172
1173
1174static LRESULT
1175TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1176{
1177 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1178 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1179 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1180
1181 // TRACE("adding %d buttons!\n", wParam);
1182
1183 nAddButtons = (UINT)wParam;
1184 nOldButtons = infoPtr->nNumButtons;
1185 nNewButtons = nOldButtons + nAddButtons;
1186
1187 if (infoPtr->nNumButtons == 0) {
1188 infoPtr->buttons =
1189 (TBUTTON_INFO*) COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1190 }
1191 else {
1192 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1193 infoPtr->buttons =
1194 (TBUTTON_INFO*) COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1195 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1196 nOldButtons * sizeof(TBUTTON_INFO));
1197 COMCTL32_Free (oldButtons);
1198 }
1199
1200 infoPtr->nNumButtons = nNewButtons;
1201
1202 /* insert new button data */
1203 for (nCount = 0; nCount < nAddButtons; nCount++) {
1204 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1205 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1206 btnPtr->idCommand = lpTbb[nCount].idCommand;
1207 btnPtr->fsState = lpTbb[nCount].fsState;
1208 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1209 btnPtr->dwData = lpTbb[nCount].dwData;
1210 btnPtr->iString = lpTbb[nCount].iString;
1211 btnPtr->bHot = FALSE;
1212
1213 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1214 TTTOOLINFOA ti;
1215
1216 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1217 ti.cbSize = sizeof (TTTOOLINFOA);
1218 ti.hwnd = hwnd;
1219 ti.uId = btnPtr->idCommand;
1220 ti.hinst = 0;
1221 ti.lpszText = LPSTR_TEXTCALLBACKA;
1222
1223 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1224 0, (LPARAM)&ti);
1225 }
1226 }
1227
1228 TOOLBAR_CalcToolbar (hwnd);
1229
1230 InvalidateRect(hwnd, NULL, FALSE);
1231
1232 return TRUE;
1233}
1234
1235
1236static LRESULT
1237TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1238{
1239 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1240 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1241 INT nOldButtons, nNewButtons, nAddButtons, nCount;
1242
1243 // TRACE("adding %d buttons!\n", wParam);
1244
1245 nAddButtons = (UINT)wParam;
1246 nOldButtons = infoPtr->nNumButtons;
1247 nNewButtons = nOldButtons + nAddButtons;
1248
1249 if (infoPtr->nNumButtons == 0) {
1250 infoPtr->buttons =
1251 (TBUTTON_INFO*)COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1252 }
1253 else {
1254 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1255 infoPtr->buttons =
1256 (TBUTTON_INFO*)COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1257 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1258 nOldButtons * sizeof(TBUTTON_INFO));
1259 COMCTL32_Free (oldButtons);
1260 }
1261
1262 infoPtr->nNumButtons = nNewButtons;
1263
1264 /* insert new button data */
1265 for (nCount = 0; nCount < nAddButtons; nCount++) {
1266 TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1267 btnPtr->iBitmap = lpTbb[nCount].iBitmap;
1268 btnPtr->idCommand = lpTbb[nCount].idCommand;
1269 btnPtr->fsState = lpTbb[nCount].fsState;
1270 btnPtr->fsStyle = lpTbb[nCount].fsStyle;
1271 btnPtr->dwData = lpTbb[nCount].dwData;
1272 btnPtr->iString = lpTbb[nCount].iString;
1273 btnPtr->bHot = FALSE;
1274
1275 if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1276 TTTOOLINFOW ti;
1277
1278 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1279 ti.cbSize = sizeof (TTTOOLINFOW);
1280 ti.hwnd = hwnd;
1281 ti.uId = btnPtr->idCommand;
1282 ti.hinst = 0;
1283 ti.lpszText = LPSTR_TEXTCALLBACKW;
1284
1285 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1286 0, (LPARAM)&ti);
1287 }
1288 }
1289
1290 TOOLBAR_CalcToolbar (hwnd);
1291
1292 InvalidateRect(hwnd, NULL, FALSE);
1293
1294 return TRUE;
1295}
1296
1297
1298static LRESULT
1299TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1300{
1301 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1302 INT nIndex;
1303
1304 if ((wParam) && (HIWORD(lParam) == 0)) {
1305 char szString[256];
1306 INT len;
1307 // TRACE("adding string from resource!\n");
1308
1309 len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1310 szString, 256);
1311
1312 // TRACE("len=%d \"%s\"\n", len, szString);
1313 nIndex = infoPtr->nNumStrings;
1314 if (infoPtr->nNumStrings == 0) {
1315 infoPtr->strings =
1316 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR));
1317 }
1318 else {
1319 LPWSTR *oldStrings = infoPtr->strings;
1320 infoPtr->strings =
1321 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1322 memcpy (&infoPtr->strings[0], &oldStrings[0],
1323 sizeof(LPWSTR) * infoPtr->nNumStrings);
1324 COMCTL32_Free (oldStrings);
1325 }
1326
1327 infoPtr->strings[infoPtr->nNumStrings] =
1328 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1329 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1330 infoPtr->nNumStrings++;
1331 }
1332 else {
1333 LPSTR p = (LPSTR)lParam;
1334 INT len;
1335
1336 if (p == NULL)
1337 return -1;
1338 // TRACE("adding string(s) from array!\n");
1339
1340 nIndex = infoPtr->nNumStrings;
1341 while (*p) {
1342 len = lstrlenA (p);
1343 // TRACE("len=%d \"%s\"\n", len, p);
1344
1345 if (infoPtr->nNumStrings == 0) {
1346 infoPtr->strings =
1347 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR));
1348 }
1349 else {
1350 LPWSTR *oldStrings = infoPtr->strings;
1351 infoPtr->strings =
1352 (LPWSTR*) COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1353 memcpy (&infoPtr->strings[0], &oldStrings[0],
1354 sizeof(LPWSTR) * infoPtr->nNumStrings);
1355 COMCTL32_Free (oldStrings);
1356 }
1357
1358 infoPtr->strings[infoPtr->nNumStrings] =
1359 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1360 lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1361 infoPtr->nNumStrings++;
1362
1363 p += (len+1);
1364 }
1365 }
1366
1367 return nIndex;
1368}
1369
1370
1371static LRESULT
1372TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1373{
1374#define MAX_RESOURCE_STRING_LENGTH 512
1375 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1376 INT nIndex;
1377
1378 if ((wParam) && (HIWORD(lParam) == 0)) {
1379 WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1380 INT len;
1381 // TRACE("adding string from resource!\n");
1382
1383 len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1384 szString, MAX_RESOURCE_STRING_LENGTH);
1385
1386 // TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1387 // TRACE("First char: 0x%x\n", *szString);
1388 if (szString[0] == L'|')
1389 {
1390 PWSTR p = szString + 1;
1391
1392 nIndex = infoPtr->nNumStrings;
1393 while (*p != L'|') {
1394
1395 if (infoPtr->nNumStrings == 0) {
1396 infoPtr->strings =
1397 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR));
1398 }
1399 else {
1400 LPWSTR *oldStrings = infoPtr->strings;
1401 infoPtr->strings =
1402 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1403 memcpy (&infoPtr->strings[0], &oldStrings[0],
1404 sizeof(LPWSTR) * infoPtr->nNumStrings);
1405 COMCTL32_Free (oldStrings);
1406 }
1407
1408 len = COMCTL32_StrChrW (p, L'|') - p;
1409 // TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1410 infoPtr->strings[infoPtr->nNumStrings] =
1411 (WCHAR *)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1412 lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1413 infoPtr->nNumStrings++;
1414
1415 p += (len+1);
1416 }
1417 }
1418 else
1419 {
1420 nIndex = infoPtr->nNumStrings;
1421 if (infoPtr->nNumStrings == 0) {
1422 infoPtr->strings =
1423 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR));
1424 }
1425 else {
1426 LPWSTR *oldStrings = infoPtr->strings;
1427 infoPtr->strings =
1428 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1429 memcpy (&infoPtr->strings[0], &oldStrings[0],
1430 sizeof(LPWSTR) * infoPtr->nNumStrings);
1431 COMCTL32_Free (oldStrings);
1432 }
1433
1434 infoPtr->strings[infoPtr->nNumStrings] =
1435 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1436 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1437 infoPtr->nNumStrings++;
1438 }
1439 }
1440 else {
1441 LPWSTR p = (LPWSTR)lParam;
1442 INT len;
1443
1444 if (p == NULL)
1445 return -1;
1446 // TRACE("adding string(s) from array!\n");
1447 nIndex = infoPtr->nNumStrings;
1448 while (*p) {
1449 len = lstrlenW (p);
1450
1451 // TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1452 if (infoPtr->nNumStrings == 0) {
1453 infoPtr->strings =
1454 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR));
1455 }
1456 else {
1457 LPWSTR *oldStrings = infoPtr->strings;
1458 infoPtr->strings =
1459 (LPWSTR*)COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1460 memcpy (&infoPtr->strings[0], &oldStrings[0],
1461 sizeof(LPWSTR) * infoPtr->nNumStrings);
1462 COMCTL32_Free (oldStrings);
1463 }
1464
1465 infoPtr->strings[infoPtr->nNumStrings] =
1466 (WCHAR*)COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1467 lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1468 infoPtr->nNumStrings++;
1469
1470 p += (len+1);
1471 }
1472 }
1473
1474 return nIndex;
1475}
1476
1477
1478static LRESULT
1479TOOLBAR_AutoSize (HWND hwnd)
1480{
1481 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1482 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1483 RECT parent_rect;
1484 RECT window_rect;
1485 HWND parent;
1486 INT x, y;
1487 INT cx, cy;
1488 UINT uPosFlags = SWP_NOZORDER;
1489
1490 // TRACE("resize forced, style=%lx!\n", dwStyle);
1491
1492 parent = GetParent (hwnd);
1493 GetClientRect(parent, &parent_rect);
1494
1495 x = parent_rect.left;
1496 y = parent_rect.top;
1497
1498 if (dwStyle & CCS_NORESIZE) {
1499 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1500 cx = 0;
1501 cy = 0;
1502 }
1503 else {
1504 infoPtr->nWidth = parent_rect.right - parent_rect.left;
1505 TOOLBAR_CalcToolbar (hwnd);
1506 InvalidateRect( hwnd, NULL, TRUE );
1507 cy = infoPtr->nHeight;
1508 cx = infoPtr->nWidth;
1509
1510 if (dwStyle & CCS_NOMOVEY) {
1511 GetWindowRect(hwnd, &window_rect);
1512 ScreenToClient(parent, (LPPOINT)&window_rect.left);
1513 y = window_rect.top;
1514 }
1515 }
1516
1517 if (dwStyle & CCS_NOPARENTALIGN)
1518 uPosFlags |= SWP_NOMOVE;
1519
1520 if (!(dwStyle & CCS_NODIVIDER))
1521 cy += GetSystemMetrics(SM_CYEDGE);
1522
1523 if (dwStyle & WS_BORDER)
1524 {
1525 x = y = 1;
1526 cy += GetSystemMetrics(SM_CYEDGE);
1527 cx += GetSystemMetrics(SM_CYEDGE);
1528 }
1529
1530 infoPtr->bAutoSize = TRUE;
1531 SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
1532 cx, cy, uPosFlags);
1533 /* The following line makes sure that the infoPtr->bAutoSize is turned off after
1534 * the setwindowpos calls */
1535 infoPtr->bAutoSize = FALSE;
1536
1537 return 0;
1538}
1539
1540
1541static LRESULT
1542TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1543{
1544 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1545
1546 return infoPtr->nNumButtons;
1547}
1548
1549
1550static LRESULT
1551TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1552{
1553 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1554
1555 if (infoPtr == NULL) {
1556// ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1557// ERR("infoPtr == NULL!\n");
1558 return 0;
1559 }
1560
1561 infoPtr->dwStructSize = (DWORD)wParam;
1562
1563 return 0;
1564}
1565
1566
1567static LRESULT
1568TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1569{
1570 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1571 TBUTTON_INFO *btnPtr;
1572 INT nIndex;
1573
1574 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1575 if (nIndex == -1)
1576 return FALSE;
1577
1578 btnPtr = &infoPtr->buttons[nIndex];
1579 btnPtr->iBitmap = LOWORD(lParam);
1580
1581 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1582
1583 return TRUE;
1584}
1585
1586
1587static LRESULT
1588TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1589{
1590 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1591 TBUTTON_INFO *btnPtr;
1592 INT nIndex;
1593 INT nOldIndex = -1;
1594 BOOL bChecked = FALSE;
1595
1596 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1597 if (nIndex == -1)
1598 return FALSE;
1599
1600 btnPtr = &infoPtr->buttons[nIndex];
1601
1602 if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1603 return FALSE;
1604
1605 bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
1606
1607 if (LOWORD(lParam) == FALSE)
1608 btnPtr->fsState &= ~TBSTATE_CHECKED;
1609 else {
1610 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1611 nOldIndex =
1612 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1613 if (nOldIndex == nIndex)
1614 return 0;
1615 if (nOldIndex != -1)
1616 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1617 }
1618 btnPtr->fsState |= TBSTATE_CHECKED;
1619 }
1620
1621 if( bChecked != LOWORD(lParam) )
1622 {
1623 if (nOldIndex != -1)
1624 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect, TRUE);
1625 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1626 }
1627
1628 /* FIXME: Send a WM_NOTIFY?? */
1629
1630 return TRUE;
1631}
1632
1633
1634static LRESULT
1635TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1636{
1637 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1638
1639 return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1640}
1641
1642
1643static LRESULT
1644TOOLBAR_Customize (HWND hwnd)
1645{
1646 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1647 LRESULT ret;
1648 LPCVOID temp;
1649 HRSRC hRes;
1650 NMHDR nmhdr;
1651
1652 /* send TBN_BEGINADJUST notification */
1653 nmhdr.hwndFrom = hwnd;
1654 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1655 nmhdr.code = TBN_BEGINADJUST;
1656
1657 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1658 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1659
1660 if (!(hRes = FindResourceA (COMCTL32_hModule,
1661 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1662 RT_DIALOGA)))
1663 return FALSE;
1664
1665 if(!(temp = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1666 return FALSE;
1667
1668 ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1669 (LPDLGTEMPLATEA)temp,
1670 hwnd,
1671 (DLGPROC)TOOLBAR_CustomizeDialogProc,
1672 (LPARAM)infoPtr);
1673
1674 /* send TBN_ENDADJUST notification */
1675 nmhdr.code = TBN_ENDADJUST;
1676
1677 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1678 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1679
1680 return ret;
1681}
1682
1683
1684static LRESULT
1685TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1686{
1687 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1688 INT nIndex = (INT)wParam;
1689
1690 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1691 return FALSE;
1692
1693 if ((infoPtr->hwndToolTip) &&
1694 !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1695 TTTOOLINFOA ti;
1696
1697 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1698 ti.cbSize = sizeof (TTTOOLINFOA);
1699 ti.hwnd = hwnd;
1700 ti.uId = infoPtr->buttons[nIndex].idCommand;
1701
1702 SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1703 }
1704
1705 if (infoPtr->nNumButtons == 1) {
1706 // TRACE(" simple delete!\n");
1707 COMCTL32_Free (infoPtr->buttons);
1708 infoPtr->buttons = NULL;
1709 infoPtr->nNumButtons = 0;
1710 }
1711 else {
1712 TBUTTON_INFO *oldButtons = infoPtr->buttons;
1713 // TRACE("complex delete! [nIndex=%d]\n", nIndex);
1714
1715 infoPtr->nNumButtons--;
1716 infoPtr->buttons = (TBUTTON_INFO*)COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1717 if (nIndex > 0) {
1718 memcpy (&infoPtr->buttons[0], &oldButtons[0],
1719 nIndex * sizeof(TBUTTON_INFO));
1720 }
1721
1722 if (nIndex < infoPtr->nNumButtons) {
1723 memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1724 (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1725 }
1726
1727 COMCTL32_Free (oldButtons);
1728 }
1729
1730 TOOLBAR_CalcToolbar (hwnd);
1731
1732 InvalidateRect (hwnd, NULL, TRUE);
1733
1734 return TRUE;
1735}
1736
1737
1738static LRESULT
1739TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1740{
1741 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1742 TBUTTON_INFO *btnPtr;
1743 INT nIndex;
1744 DWORD bState;
1745
1746 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1747 if (nIndex == -1)
1748 return FALSE;
1749
1750 btnPtr = &infoPtr->buttons[nIndex];
1751
1752 bState = btnPtr->fsState & TBSTATE_ENABLED;
1753
1754 /* update the toolbar button state */
1755 if(LOWORD(lParam) == FALSE) {
1756 btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1757 } else {
1758 btnPtr->fsState |= TBSTATE_ENABLED;
1759 }
1760
1761 /* redraw the button only if the state of the button changed */
1762 if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
1763 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
1764
1765 return TRUE;
1766}
1767
1768
1769static inline LRESULT
1770TOOLBAR_GetAnchorHighlight (HWND hwnd)
1771{
1772 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1773
1774 return infoPtr->bAnchor;
1775}
1776
1777
1778static LRESULT
1779TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1780{
1781 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1782 INT nIndex;
1783
1784 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1785 if (nIndex == -1)
1786 return -1;
1787
1788 return infoPtr->buttons[nIndex].iBitmap;
1789}
1790
1791
1792static inline LRESULT
1793TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1794{
1795 return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1796}
1797
1798
1799static LRESULT
1800TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1801{
1802 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1803 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1804 INT nIndex = (INT)wParam;
1805 TBUTTON_INFO *btnPtr;
1806
1807 if (infoPtr == NULL)
1808 return FALSE;
1809
1810 if (lpTbb == NULL)
1811 return FALSE;
1812
1813 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1814 return FALSE;
1815
1816 btnPtr = &infoPtr->buttons[nIndex];
1817 lpTbb->iBitmap = btnPtr->iBitmap;
1818 lpTbb->idCommand = btnPtr->idCommand;
1819 lpTbb->fsState = btnPtr->fsState;
1820 lpTbb->fsStyle = btnPtr->fsStyle;
1821 lpTbb->dwData = btnPtr->dwData;
1822 lpTbb->iString = btnPtr->iString;
1823
1824 return TRUE;
1825}
1826
1827
1828static LRESULT
1829TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1830{
1831 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1832 LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1833 TBUTTON_INFO *btnPtr;
1834 INT nIndex;
1835
1836 if (infoPtr == NULL)
1837 return -1;
1838 if (lpTbInfo == NULL)
1839 return -1;
1840 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1841 return -1;
1842
1843 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1844 if (nIndex == -1)
1845 return -1;
1846
1847 btnPtr = &infoPtr->buttons[nIndex];
1848
1849 if (lpTbInfo->dwMask & TBIF_COMMAND)
1850 lpTbInfo->idCommand = btnPtr->idCommand;
1851 if (lpTbInfo->dwMask & TBIF_IMAGE)
1852 lpTbInfo->iImage = btnPtr->iBitmap;
1853 if (lpTbInfo->dwMask & TBIF_LPARAM)
1854 lpTbInfo->lParam = btnPtr->dwData;
1855 if (lpTbInfo->dwMask & TBIF_SIZE)
1856 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1857 if (lpTbInfo->dwMask & TBIF_STATE)
1858 lpTbInfo->fsState = btnPtr->fsState;
1859 if (lpTbInfo->dwMask & TBIF_STYLE)
1860 lpTbInfo->fsStyle = btnPtr->fsStyle;
1861 if (lpTbInfo->dwMask & TBIF_TEXT) {
1862 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
1863 {
1864 lstrcpynWtoA (lpTbInfo->pszText,
1865 (LPWSTR)infoPtr->strings[btnPtr->iString],
1866 lpTbInfo->cchText);
1867 }
1868 else lpTbInfo->pszText[0]=0;
1869 }
1870 return nIndex;
1871}
1872
1873
1874static LRESULT
1875TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1876{
1877 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1878 LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
1879 TBUTTON_INFO *btnPtr;
1880 INT nIndex;
1881
1882 if (infoPtr == NULL)
1883 return -1;
1884 if (lpTbInfo == NULL)
1885 return -1;
1886 if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
1887 return -1;
1888
1889 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1890 if (nIndex == -1)
1891 return -1;
1892
1893 btnPtr = &infoPtr->buttons[nIndex];
1894
1895 if (lpTbInfo->dwMask & TBIF_COMMAND)
1896 lpTbInfo->idCommand = btnPtr->idCommand;
1897 if (lpTbInfo->dwMask & TBIF_IMAGE)
1898 lpTbInfo->iImage = btnPtr->iBitmap;
1899 if (lpTbInfo->dwMask & TBIF_LPARAM)
1900 lpTbInfo->lParam = btnPtr->dwData;
1901 if (lpTbInfo->dwMask & TBIF_SIZE)
1902 lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1903 if (lpTbInfo->dwMask & TBIF_STATE)
1904 lpTbInfo->fsState = btnPtr->fsState;
1905 if (lpTbInfo->dwMask & TBIF_STYLE)
1906 lpTbInfo->fsStyle = btnPtr->fsStyle;
1907 if (lpTbInfo->dwMask & TBIF_TEXT) {
1908 if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1909 lstrcpynW (lpTbInfo->pszText,
1910 (LPWSTR)infoPtr->strings[btnPtr->iString],
1911 lpTbInfo->cchText);
1912 }
1913
1914 return nIndex;
1915}
1916
1917
1918static LRESULT
1919TOOLBAR_GetButtonSize (HWND hwnd)
1920{
1921 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1922
1923 return MAKELONG((WORD)infoPtr->nButtonWidth,
1924 (WORD)infoPtr->nButtonHeight);
1925}
1926
1927
1928static LRESULT
1929TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1930{
1931 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1932 INT nIndex, nStringIndex;
1933
1934 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1935 if (nIndex == -1)
1936 return -1;
1937
1938 nStringIndex = infoPtr->buttons[nIndex].iString;
1939
1940 // TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1941
1942 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1943 return -1;
1944
1945 if (lParam == 0)
1946 return -1;
1947
1948 lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1949
1950 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1951}
1952
1953
1954static LRESULT
1955TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1956{
1957 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1958 INT nIndex, nStringIndex;
1959
1960 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1961 if (nIndex == -1)
1962 return -1;
1963
1964 nStringIndex = infoPtr->buttons[nIndex].iString;
1965
1966 // TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1967
1968 if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1969 return -1;
1970
1971 if (lParam == 0)
1972 return -1;
1973
1974 lstrcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
1975
1976 return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
1977}
1978
1979
1980/* << TOOLBAR_GetColorScheme >> */
1981
1982
1983static LRESULT
1984TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1985{
1986 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1987
1988 return (LRESULT)infoPtr->himlDis;
1989}
1990
1991
1992inline static LRESULT
1993TOOLBAR_GetExtendedStyle (HWND hwnd)
1994{
1995 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1996
1997 return infoPtr->dwExStyle;
1998}
1999
2000
2001static LRESULT
2002TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2003{
2004 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2005
2006 return (LRESULT)infoPtr->himlHot;
2007}
2008
2009
2010static LRESULT
2011TOOLBAR_GetHotItem (HWND hwnd)
2012{
2013 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2014
2015 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2016 return -1;
2017
2018 if (infoPtr->nHotItem < 0)
2019 return -1;
2020
2021 return (LRESULT)infoPtr->nHotItem;
2022}
2023
2024
2025static LRESULT
2026TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2027{
2028 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2029
2030 return (LRESULT)infoPtr->himlDef;
2031}
2032
2033
2034/* << TOOLBAR_GetInsertMark >> */
2035/* << TOOLBAR_GetInsertMarkColor >> */
2036
2037
2038static LRESULT
2039TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2040{
2041 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2042 TBUTTON_INFO *btnPtr;
2043 LPRECT lpRect;
2044 INT nIndex;
2045
2046 if (infoPtr == NULL)
2047 return FALSE;
2048 nIndex = (INT)wParam;
2049 btnPtr = &infoPtr->buttons[nIndex];
2050 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2051 return FALSE;
2052 lpRect = (LPRECT)lParam;
2053 if (lpRect == NULL)
2054 return FALSE;
2055 if (btnPtr->fsState & TBSTATE_HIDDEN)
2056 return FALSE;
2057
2058 TOOLBAR_CalcToolbar( hwnd );
2059
2060 lpRect->left = btnPtr->rect.left;
2061 lpRect->right = btnPtr->rect.right;
2062 lpRect->bottom = btnPtr->rect.bottom;
2063 lpRect->top = btnPtr->rect.top;
2064
2065 return TRUE;
2066}
2067
2068
2069static LRESULT
2070TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2071{
2072 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2073 LPSIZE lpSize = (LPSIZE)lParam;
2074
2075 if (lpSize == NULL)
2076 return FALSE;
2077
2078 lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2079 lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2080
2081 // TRACE("maximum size %d x %d\n",
2082 // infoPtr->rcBound.right - infoPtr->rcBound.left,
2083 // infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2084
2085 return TRUE;
2086}
2087
2088
2089/* << TOOLBAR_GetObject >> */
2090/* << TOOLBAR_GetPadding >> */
2091
2092
2093static LRESULT
2094TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2095{
2096 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2097 TBUTTON_INFO *btnPtr;
2098 LPRECT lpRect;
2099 INT nIndex;
2100
2101 if (infoPtr == NULL)
2102 return FALSE;
2103 nIndex = (INT)wParam;
2104 btnPtr = &infoPtr->buttons[nIndex];
2105 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2106 return FALSE;
2107 lpRect = (LPRECT)lParam;
2108 if (lpRect == NULL)
2109 return FALSE;
2110
2111 lpRect->left = btnPtr->rect.left;
2112 lpRect->right = btnPtr->rect.right;
2113 lpRect->bottom = btnPtr->rect.bottom;
2114 lpRect->top = btnPtr->rect.top;
2115
2116 return TRUE;
2117}
2118
2119
2120static LRESULT
2121TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2122{
2123 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2124
2125 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2126 return infoPtr->nRows;
2127 else
2128 return 1;
2129}
2130
2131
2132static LRESULT
2133TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2134{
2135 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2136 INT nIndex;
2137
2138 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2139 if (nIndex == -1)
2140 return -1;
2141
2142 return infoPtr->buttons[nIndex].fsState;
2143}
2144
2145
2146static LRESULT
2147TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2148{
2149 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2150 INT nIndex;
2151
2152 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2153 if (nIndex == -1)
2154 return -1;
2155
2156 return infoPtr->buttons[nIndex].fsStyle;
2157}
2158
2159
2160static LRESULT
2161TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2162{
2163 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2164
2165 if (infoPtr == NULL)
2166 return 0;
2167
2168 return infoPtr->nMaxTextRows;
2169}
2170
2171
2172static LRESULT
2173TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2174{
2175 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2176
2177 if (infoPtr == NULL)
2178 return 0;
2179 return infoPtr->hwndToolTip;
2180}
2181
2182
2183static LRESULT
2184TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2185{
2186 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2187
2188 // TRACE("%s hwnd=0x%x stub!\n",
2189// infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2190
2191 return infoPtr->bUnicode;
2192}
2193
2194
2195inline static LRESULT
2196TOOLBAR_GetVersion (HWND hwnd)
2197{
2198 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2199 return infoPtr->iVersion;
2200}
2201
2202
2203static LRESULT
2204TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2205{
2206 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2207 TBUTTON_INFO *btnPtr;
2208 INT nIndex;
2209
2210 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2211 if (nIndex == -1)
2212 return FALSE;
2213
2214 btnPtr = &infoPtr->buttons[nIndex];
2215 if (LOWORD(lParam) == FALSE)
2216 btnPtr->fsState &= ~TBSTATE_HIDDEN;
2217 else
2218 btnPtr->fsState |= TBSTATE_HIDDEN;
2219
2220 TOOLBAR_CalcToolbar (hwnd);
2221
2222 InvalidateRect (hwnd, NULL, TRUE);
2223
2224 return TRUE;
2225}
2226
2227
2228inline static LRESULT
2229TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2230{
2231 return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2232}
2233
2234
2235static LRESULT
2236TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2237{
2238 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2239 TBUTTON_INFO *btnPtr;
2240 INT nIndex;
2241
2242 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2243 if (nIndex == -1)
2244 return FALSE;
2245
2246 btnPtr = &infoPtr->buttons[nIndex];
2247 if (LOWORD(lParam) == FALSE)
2248 btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2249 else
2250 btnPtr->fsState |= TBSTATE_INDETERMINATE;
2251
2252 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2253
2254 return TRUE;
2255}
2256
2257
2258static LRESULT
2259TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2260{
2261 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2262 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2263 INT nIndex = (INT)wParam;
2264 TBUTTON_INFO *oldButtons;
2265
2266 if (lpTbb == NULL)
2267 return FALSE;
2268
2269 if (nIndex == -1) {
2270 /* EPP: this seems to be an undocumented call (from my IE4)
2271 * I assume in that case that:
2272 * - lpTbb->iString is a string pointer (not a string index in strings[] table
2273 * - index of insertion is at the end of existing buttons
2274 * I only see this happen with nIndex == -1, but it could have a special
2275 * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2276 */
2277 int len;
2278 LPSTR ptr;
2279
2280 if(lpTbb->iString) {
2281 len = lstrlenA((char*)lpTbb->iString) + 2;
2282 ptr = (CHAR*)COMCTL32_Alloc(len);
2283 nIndex = infoPtr->nNumButtons;
2284 strcpy(ptr, (char*)lpTbb->iString);
2285 ptr[len - 1] = 0; /* ended by two '\0' */
2286 lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2287 COMCTL32_Free(ptr);
2288 }
2289 else {
2290 // ERR("lpTbb->iString is NULL\n");
2291 return FALSE;
2292 }
2293
2294 } else if (nIndex < 0)
2295 return FALSE;
2296
2297 // TRACE("inserting button index=%d\n", nIndex);
2298 if (nIndex > infoPtr->nNumButtons) {
2299 nIndex = infoPtr->nNumButtons;
2300 // TRACE("adjust index=%d\n", nIndex);
2301 }
2302
2303 oldButtons = infoPtr->buttons;
2304 infoPtr->nNumButtons++;
2305 infoPtr->buttons = (TBUTTON_INFO*)COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2306 /* pre insert copy */
2307 if (nIndex > 0) {
2308 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2309 nIndex * sizeof(TBUTTON_INFO));
2310 }
2311
2312 /* insert new button */
2313 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2314 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2315 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2316 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2317 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2318 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2319
2320 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2321 TTTOOLINFOA ti;
2322
2323 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2324 ti.cbSize = sizeof (TTTOOLINFOA);
2325 ti.hwnd = hwnd;
2326 ti.uId = lpTbb->idCommand;
2327 ti.hinst = 0;
2328 ti.lpszText = LPSTR_TEXTCALLBACKA;
2329
2330 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2331 0, (LPARAM)&ti);
2332 }
2333
2334 /* post insert copy */
2335 if (nIndex < infoPtr->nNumButtons - 1) {
2336 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2337 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2338 }
2339
2340 COMCTL32_Free (oldButtons);
2341
2342 TOOLBAR_CalcToolbar (hwnd);
2343
2344 InvalidateRect (hwnd, NULL, FALSE);
2345
2346 return TRUE;
2347}
2348
2349
2350static LRESULT
2351TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2352{
2353 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2354 LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2355 INT nIndex = (INT)wParam;
2356 TBUTTON_INFO *oldButtons;
2357
2358 if (lpTbb == NULL)
2359 return FALSE;
2360 if (nIndex < 0)
2361 return FALSE;
2362
2363 // TRACE("inserting button index=%d\n", nIndex);
2364 if (nIndex > infoPtr->nNumButtons) {
2365 nIndex = infoPtr->nNumButtons;
2366 // TRACE("adjust index=%d\n", nIndex);
2367 }
2368
2369 oldButtons = infoPtr->buttons;
2370 infoPtr->nNumButtons++;
2371 infoPtr->buttons = (TBUTTON_INFO*)COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2372 /* pre insert copy */
2373 if (nIndex > 0) {
2374 memcpy (&infoPtr->buttons[0], &oldButtons[0],
2375 nIndex * sizeof(TBUTTON_INFO));
2376 }
2377
2378 /* insert new button */
2379 infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap;
2380 infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2381 infoPtr->buttons[nIndex].fsState = lpTbb->fsState;
2382 infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle;
2383 infoPtr->buttons[nIndex].dwData = lpTbb->dwData;
2384 infoPtr->buttons[nIndex].iString = lpTbb->iString;
2385
2386 if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2387 TTTOOLINFOW ti;
2388
2389 ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2390 ti.cbSize = sizeof (TTTOOLINFOW);
2391 ti.hwnd = hwnd;
2392 ti.uId = lpTbb->idCommand;
2393 ti.hinst = 0;
2394 ti.lpszText = LPSTR_TEXTCALLBACKW;
2395
2396 SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2397 0, (LPARAM)&ti);
2398 }
2399
2400 /* post insert copy */
2401 if (nIndex < infoPtr->nNumButtons - 1) {
2402 memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2403 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2404 }
2405
2406 COMCTL32_Free (oldButtons);
2407
2408 TOOLBAR_CalcToolbar (hwnd);
2409
2410 InvalidateRect (hwnd, NULL, FALSE);
2411
2412 return TRUE;
2413}
2414
2415
2416/* << TOOLBAR_InsertMarkHitTest >> */
2417
2418
2419static LRESULT
2420TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2421{
2422 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2423 INT nIndex;
2424
2425 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2426 if (nIndex == -1)
2427 return FALSE;
2428
2429 return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2430}
2431
2432
2433static LRESULT
2434TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2435{
2436 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2437 INT nIndex;
2438
2439 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2440 if (nIndex == -1)
2441 return FALSE;
2442
2443 return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2444}
2445
2446
2447static LRESULT
2448TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2449{
2450 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2451 INT nIndex;
2452
2453 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2454 if (nIndex == -1)
2455 return FALSE;
2456
2457 return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2458}
2459
2460
2461static LRESULT
2462TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2463{
2464 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2465 INT nIndex;
2466
2467 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2468 if (nIndex == -1)
2469 return FALSE;
2470
2471 return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2472}
2473
2474
2475static LRESULT
2476TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2477{
2478 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2479 INT nIndex;
2480
2481 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2482 if (nIndex == -1)
2483 return FALSE;
2484
2485 return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2486}
2487
2488
2489static LRESULT
2490TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2491{
2492 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2493 INT nIndex;
2494
2495 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2496 if (nIndex == -1)
2497 return FALSE;
2498
2499 return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2500}
2501
2502
2503/* << TOOLBAR_LoadImages >> */
2504/* << TOOLBAR_MapAccelerator >> */
2505/* << TOOLBAR_MarkButton >> */
2506/* << TOOLBAR_MoveButton >> */
2507
2508
2509static LRESULT
2510TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2511{
2512 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2513 TBUTTON_INFO *btnPtr;
2514 INT nIndex;
2515
2516 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2517 if (nIndex == -1)
2518 return FALSE;
2519
2520 btnPtr = &infoPtr->buttons[nIndex];
2521 if (LOWORD(lParam) == FALSE)
2522 btnPtr->fsState &= ~TBSTATE_PRESSED;
2523 else
2524 btnPtr->fsState |= TBSTATE_PRESSED;
2525
2526 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2527
2528 return TRUE;
2529}
2530
2531
2532/* << TOOLBAR_ReplaceBitmap >> */
2533
2534
2535static LRESULT
2536TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2537{
2538#if 0
2539 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2540 LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2541
2542 if (lpSave == NULL) return 0;
2543
2544 if ((BOOL)wParam) {
2545 /* save toolbar information */
2546 // FIXME("save to \"%s\" \"%s\"\n",
2547 lpSave->pszSubKey, lpSave->pszValueName);
2548
2549
2550 }
2551 else {
2552 /* restore toolbar information */
2553
2554 // FIXME("restore from \"%s\" \"%s\"\n",
2555 lpSave->pszSubKey, lpSave->pszValueName);
2556
2557
2558 }
2559#endif
2560
2561 return 0;
2562}
2563
2564
2565static LRESULT
2566TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2567{
2568#if 0
2569 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2570 LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
2571
2572 if (lpSave == NULL)
2573 return 0;
2574
2575 if ((BOOL)wParam) {
2576 /* save toolbar information */
2577 // FIXME("save to \"%s\" \"%s\"\n",
2578 lpSave->pszSubKey, lpSave->pszValueName);
2579
2580
2581 }
2582 else {
2583 /* restore toolbar information */
2584
2585 // FIXME("restore from \"%s\" \"%s\"\n",
2586 lpSave->pszSubKey, lpSave->pszValueName);
2587
2588
2589 }
2590#endif
2591
2592 return 0;
2593}
2594
2595
2596static LRESULT
2597TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
2598{
2599 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2600 BOOL bOldAnchor = infoPtr->bAnchor;
2601
2602 infoPtr->bAnchor = (BOOL)wParam;
2603
2604 return (LRESULT)bOldAnchor;
2605}
2606
2607
2608static LRESULT
2609TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2610{
2611 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2612
2613 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2614 return FALSE;
2615
2616// if (infoPtr->nNumButtons > 0)
2617// WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
2618// infoPtr->nNumButtons,
2619// infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
2620// LOWORD(lParam), HIWORD(lParam));
2621
2622 infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2623 infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2624
2625 /* uses image list internals directly */
2626 if (infoPtr->himlDef) {
2627 infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
2628 infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
2629 }
2630
2631 return TRUE;
2632}
2633
2634
2635static LRESULT
2636TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2637{
2638 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2639 LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2640 TBUTTON_INFO *btnPtr;
2641 INT nIndex;
2642
2643 if (lptbbi == NULL)
2644 return FALSE;
2645 if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2646 return FALSE;
2647
2648 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2649 if (nIndex == -1)
2650 return FALSE;
2651
2652 btnPtr = &infoPtr->buttons[nIndex];
2653 if (lptbbi->dwMask & TBIF_COMMAND)
2654 btnPtr->idCommand = lptbbi->idCommand;
2655 if (lptbbi->dwMask & TBIF_IMAGE)
2656 btnPtr->iBitmap = lptbbi->iImage;
2657 if (lptbbi->dwMask & TBIF_LPARAM)
2658 btnPtr->dwData = lptbbi->lParam;
2659/* if (lptbbi->dwMask & TBIF_SIZE) */
2660/* btnPtr->cx = lptbbi->cx; */
2661 if (lptbbi->dwMask & TBIF_STATE)
2662 btnPtr->fsState = lptbbi->fsState;
2663 if (lptbbi->dwMask & TBIF_STYLE)
2664 btnPtr->fsStyle = lptbbi->fsStyle;
2665
2666 if (lptbbi->dwMask & TBIF_TEXT) {
2667 if ((btnPtr->iString >= 0) ||
2668 (btnPtr->iString < infoPtr->nNumStrings)) {
2669 // TRACE("Ooooooch\n");
2670#if 0
2671 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2672 INT len = lstrlenA (lptbbi->pszText);
2673 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2674#endif
2675
2676 /* this is the ultimate sollution */
2677/* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2678 }
2679 }
2680
2681 return TRUE;
2682}
2683
2684
2685static LRESULT
2686TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2687{
2688 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2689 LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
2690 TBUTTON_INFO *btnPtr;
2691 INT nIndex;
2692
2693 if (lptbbi == NULL)
2694 return FALSE;
2695 if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
2696 return FALSE;
2697
2698 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2699 if (nIndex == -1)
2700 return FALSE;
2701
2702 btnPtr = &infoPtr->buttons[nIndex];
2703 if (lptbbi->dwMask & TBIF_COMMAND)
2704 btnPtr->idCommand = lptbbi->idCommand;
2705 if (lptbbi->dwMask & TBIF_IMAGE)
2706 btnPtr->iBitmap = lptbbi->iImage;
2707 if (lptbbi->dwMask & TBIF_LPARAM)
2708 btnPtr->dwData = lptbbi->lParam;
2709/* if (lptbbi->dwMask & TBIF_SIZE) */
2710/* btnPtr->cx = lptbbi->cx; */
2711 if (lptbbi->dwMask & TBIF_STATE)
2712 btnPtr->fsState = lptbbi->fsState;
2713 if (lptbbi->dwMask & TBIF_STYLE)
2714 btnPtr->fsStyle = lptbbi->fsStyle;
2715
2716 if (lptbbi->dwMask & TBIF_TEXT) {
2717 if ((btnPtr->iString >= 0) ||
2718 (btnPtr->iString < infoPtr->nNumStrings)) {
2719#if 0
2720 WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
2721 INT len = lstrlenW (lptbbi->pszText);
2722 *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
2723#endif
2724
2725 /* this is the ultimate sollution */
2726/* Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2727 }
2728 }
2729
2730 return TRUE;
2731}
2732
2733
2734static LRESULT
2735TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2736{
2737 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2738
2739 if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2740 {
2741// ERR("invalid parameter\n");
2742 return FALSE;
2743 }
2744
2745 /* Button size can only be set before adding any button to the toolbar
2746 according to the documentation. */
2747 /* this appears to be wrong. WINZIP32.EXE (ver 8) calls this on
2748 one of its buttons after adding it to the toolbar, and it
2749 checks that the return value is nonzero - mjm */
2750 if( infoPtr->nNumButtons != 0 )
2751 {
2752 // FIXME("Button size set after button in toolbar\n");
2753 return TRUE;
2754 }
2755
2756 infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2757 infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2758 return TRUE;
2759}
2760
2761
2762static LRESULT
2763TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2764{
2765 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2766
2767 if (infoPtr == NULL)
2768 return FALSE;
2769
2770 infoPtr->cxMin = (INT)LOWORD(lParam);
2771 infoPtr->cxMax = (INT)HIWORD(lParam);
2772
2773 return TRUE;
2774}
2775
2776
2777static LRESULT
2778TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2779{
2780 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2781 INT nIndex = (INT)wParam;
2782
2783 if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2784 return FALSE;
2785
2786 infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2787
2788 if (infoPtr->hwndToolTip) {
2789
2790 // FIXME("change tool tip!\n");
2791
2792 }
2793
2794 return TRUE;
2795}
2796
2797
2798/* << TOOLBAR_SetColorScheme >> */
2799
2800
2801static LRESULT
2802TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2803{
2804 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2805 HIMAGELIST himlTemp;
2806
2807
2808 himlTemp = infoPtr->himlDis;
2809 infoPtr->himlDis = (HIMAGELIST)lParam;
2810
2811 /* FIXME: redraw ? */
2812
2813 return (LRESULT)himlTemp;
2814}
2815
2816
2817static LRESULT
2818TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2819{
2820 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2821 DWORD dwTemp;
2822
2823 dwTemp = infoPtr->dwDTFlags;
2824 infoPtr->dwDTFlags =
2825 (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2826
2827 return (LRESULT)dwTemp;
2828}
2829
2830
2831static LRESULT
2832TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2833{
2834 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2835 DWORD dwTemp;
2836
2837 dwTemp = infoPtr->dwExStyle;
2838 infoPtr->dwExStyle = (DWORD)lParam;
2839
2840 return (LRESULT)dwTemp;
2841}
2842
2843
2844static LRESULT
2845TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2846{
2847 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2848 HIMAGELIST himlTemp;
2849
2850 himlTemp = infoPtr->himlHot;
2851 infoPtr->himlHot = (HIMAGELIST)lParam;
2852
2853 /* FIXME: redraw ? */
2854
2855 return (LRESULT)himlTemp;
2856}
2857
2858
2859static LRESULT
2860TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
2861{
2862 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2863 INT nOldHotItem = infoPtr->nHotItem;
2864
2865 if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
2866 {
2867 infoPtr->nHotItem = (INT)wParam;
2868
2869 /* FIXME: What else must be done ??? */
2870
2871 }
2872
2873 if (nOldHotItem < 0)
2874 return -1;
2875
2876 return (LRESULT)nOldHotItem;
2877}
2878
2879
2880static LRESULT
2881TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2882{
2883 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2884 HIMAGELIST himlTemp;
2885
2886 himlTemp = infoPtr->himlDef;
2887 infoPtr->himlDef = (HIMAGELIST)lParam;
2888
2889 infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
2890 /* FIXME: redraw ? */
2891
2892 return (LRESULT)himlTemp;
2893}
2894
2895
2896static LRESULT
2897TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2898{
2899 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2900
2901 infoPtr->nIndent = (INT)wParam;
2902
2903 TOOLBAR_CalcToolbar (hwnd);
2904
2905 InvalidateRect(hwnd, NULL, FALSE);
2906
2907 return TRUE;
2908}
2909
2910
2911/* << TOOLBAR_SetInsertMark >> */
2912
2913
2914static LRESULT
2915TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2916{
2917 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2918
2919 infoPtr->clrInsertMark = (COLORREF)lParam;
2920
2921 /* FIXME : redraw ??*/
2922
2923 return 0;
2924}
2925
2926
2927static LRESULT
2928TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2929{
2930 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2931
2932 if (infoPtr == NULL)
2933 return FALSE;
2934
2935 infoPtr->nMaxTextRows = (INT)wParam;
2936
2937 return TRUE;
2938}
2939
2940
2941/* << TOOLBAR_SetPadding >> */
2942
2943
2944static LRESULT
2945TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2946{
2947 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2948 HWND hwndOldNotify;
2949
2950 if (infoPtr == NULL)
2951 return 0;
2952 hwndOldNotify = infoPtr->hwndNotify;
2953 infoPtr->hwndNotify = (HWND)wParam;
2954
2955 return hwndOldNotify;
2956}
2957
2958
2959static LRESULT
2960TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2961{
2962 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2963 LPRECT lprc = (LPRECT)lParam;
2964
2965 if (LOWORD(wParam) > 1) {
2966
2967 // FIXME("multiple rows not supported!\n");
2968
2969 }
2970
2971 /* recalculate toolbar */
2972 TOOLBAR_CalcToolbar (hwnd);
2973
2974 /* return bounding rectangle */
2975 if (lprc) {
2976 lprc->left = infoPtr->rcBound.left;
2977 lprc->right = infoPtr->rcBound.right;
2978 lprc->top = infoPtr->rcBound.top;
2979 lprc->bottom = infoPtr->rcBound.bottom;
2980 }
2981
2982 /* repaint toolbar */
2983 InvalidateRect(hwnd, NULL, FALSE);
2984
2985 return 0;
2986}
2987
2988
2989static LRESULT
2990TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2991{
2992 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2993 TBUTTON_INFO *btnPtr;
2994 INT nIndex;
2995
2996 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2997 if (nIndex == -1)
2998 return FALSE;
2999
3000 btnPtr = &infoPtr->buttons[nIndex];
3001 btnPtr->fsState = LOWORD(lParam);
3002
3003 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3004
3005 return TRUE;
3006}
3007
3008
3009static LRESULT
3010TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3011{
3012 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3013 TBUTTON_INFO *btnPtr;
3014 INT nIndex;
3015
3016 nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3017 if (nIndex == -1)
3018 return FALSE;
3019
3020 btnPtr = &infoPtr->buttons[nIndex];
3021 btnPtr->fsStyle = LOWORD(lParam);
3022
3023 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3024
3025 if (infoPtr->hwndToolTip) {
3026 // FIXME("change tool tip!\n");
3027 }
3028
3029 return TRUE;
3030}
3031
3032
3033inline static LRESULT
3034TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3035{
3036 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3037
3038 if (infoPtr == NULL)
3039 return 0;
3040 infoPtr->hwndToolTip = (HWND)wParam;
3041 return 0;
3042}
3043
3044
3045static LRESULT
3046TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3047{
3048 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3049 BOOL bTemp;
3050
3051 // TRACE("%s hwnd=0x%04x stub!\n",
3052// ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3053
3054 bTemp = infoPtr->bUnicode;
3055 infoPtr->bUnicode = (BOOL)wParam;
3056
3057 return bTemp;
3058}
3059
3060
3061static LRESULT
3062TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3063{
3064 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3065 INT iOldVersion = infoPtr->iVersion;
3066
3067 infoPtr->iVersion = iVersion;
3068
3069 return iOldVersion;
3070}
3071
3072
3073static LRESULT
3074TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3075{
3076 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3077 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3078 LOGFONTA logFont;
3079
3080 /* initialize info structure */
3081 infoPtr->nButtonHeight = 22;
3082 infoPtr->nButtonWidth = 24;
3083 infoPtr->nBitmapHeight = 15;
3084 infoPtr->nBitmapWidth = 16;
3085
3086 infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3087 infoPtr->nRows = 1;
3088 infoPtr->nMaxTextRows = 1;
3089 infoPtr->cxMin = -1;
3090 infoPtr->cxMax = -1;
3091 infoPtr->nNumBitmaps = 0;
3092 infoPtr->nNumStrings = 0;
3093
3094 infoPtr->bCaptured = FALSE;
3095 infoPtr->bUnicode = IsWindowUnicode (hwnd);
3096 infoPtr->nButtonDown = -1;
3097 infoPtr->nOldHit = -1;
3098 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3099 infoPtr->hwndNotify = GetParent (hwnd);
3100 infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3101 infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3102 infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3103 infoPtr->iVersion = 0;
3104
3105 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3106 infoPtr->hFont = CreateFontIndirectA (&logFont);
3107
3108 if (dwStyle & TBSTYLE_TOOLTIPS) {
3109 /* Create tooltip control */
3110 infoPtr->hwndToolTip =
3111 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3112 CW_USEDEFAULT, CW_USEDEFAULT,
3113 CW_USEDEFAULT, CW_USEDEFAULT,
3114 hwnd, 0, 0, 0);
3115
3116 /* Send NM_TOOLTIPSCREATED notification */
3117 if (infoPtr->hwndToolTip) {
3118 NMTOOLTIPSCREATED nmttc;
3119
3120 nmttc.hdr.hwndFrom = hwnd;
3121 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3122 nmttc.hdr.code = NM_TOOLTIPSCREATED;
3123 nmttc.hwndToolTips = infoPtr->hwndToolTip;
3124
3125 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3126 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3127 }
3128 }
3129
3130 return 0;
3131}
3132
3133
3134static LRESULT
3135TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3136{
3137 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3138
3139 /* delete tooltip control */
3140 if (infoPtr->hwndToolTip)
3141 DestroyWindow (infoPtr->hwndToolTip);
3142
3143 /* delete button data */
3144 if (infoPtr->buttons)
3145 COMCTL32_Free (infoPtr->buttons);
3146
3147 /* delete strings */
3148 if (infoPtr->strings) {
3149 INT i;
3150 for (i = 0; i < infoPtr->nNumStrings; i++)
3151 if (infoPtr->strings[i])
3152 COMCTL32_Free (infoPtr->strings[i]);
3153
3154 COMCTL32_Free (infoPtr->strings);
3155 }
3156
3157 /* destroy internal image list */
3158 if (infoPtr->himlInt)
3159 ImageList_Destroy (infoPtr->himlInt);
3160
3161 /* delete default font */
3162 if (infoPtr->hFont)
3163 DeleteObject (infoPtr->hFont);
3164
3165 /* free toolbar info data */
3166 COMCTL32_Free (infoPtr);
3167 SetWindowLongA (hwnd, 0, 0);
3168
3169 return 0;
3170}
3171
3172
3173static LRESULT
3174TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3175{
3176 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3177
3178 if (infoPtr->bTransparent)
3179 return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3180
3181 return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3182}
3183
3184
3185static LRESULT
3186TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3187{
3188 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3189
3190 return infoPtr->hFont;
3191}
3192
3193
3194static LRESULT
3195TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3196{
3197 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3198 TBUTTON_INFO *btnPtr;
3199 POINT pt;
3200 INT nHit;
3201
3202 pt.x = (INT)LOWORD(lParam);
3203 pt.y = (INT)HIWORD(lParam);
3204 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3205
3206 if (nHit >= 0) {
3207 btnPtr = &infoPtr->buttons[nHit];
3208 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3209 return 0;
3210 SetCapture (hwnd);
3211 infoPtr->bCaptured = TRUE;
3212 infoPtr->nButtonDown = nHit;
3213
3214 btnPtr->fsState |= TBSTATE_PRESSED;
3215
3216 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3217 }
3218 else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3219 TOOLBAR_Customize (hwnd);
3220
3221 return 0;
3222}
3223
3224
3225static LRESULT
3226TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3227{
3228 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3229 TBUTTON_INFO *btnPtr;
3230 POINT pt;
3231 INT nHit;
3232
3233 if (infoPtr->hwndToolTip)
3234 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3235 WM_LBUTTONDOWN, wParam, lParam);
3236
3237 pt.x = (INT)LOWORD(lParam);
3238 pt.y = (INT)HIWORD(lParam);
3239 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3240
3241 if (nHit >= 0) {
3242 btnPtr = &infoPtr->buttons[nHit];
3243 if (!(btnPtr->fsState & TBSTATE_ENABLED))
3244 return 0;
3245
3246 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
3247 {
3248 NMTOOLBARA nmtb;
3249
3250 nmtb.hdr.hwndFrom = hwnd;
3251 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3252 nmtb.hdr.code = TBN_DROPDOWN;
3253 nmtb.iItem = btnPtr->idCommand;
3254
3255 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3256 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3257 }
3258
3259 SetCapture (hwnd);
3260 infoPtr->bCaptured = TRUE;
3261 infoPtr->nButtonDown = nHit;
3262 infoPtr->nOldHit = nHit;
3263
3264 btnPtr->fsState |= TBSTATE_PRESSED;
3265 btnPtr->bHot = FALSE;
3266
3267 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3268 }
3269
3270 return 0;
3271}
3272
3273static LRESULT
3274TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3275{
3276 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3277 TBUTTON_INFO *btnPtr;
3278 POINT pt;
3279 INT nHit;
3280 INT nOldIndex = -1;
3281 BOOL bSendMessage = TRUE;
3282
3283 if (infoPtr->hwndToolTip)
3284 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3285 WM_LBUTTONUP, wParam, lParam);
3286
3287 pt.x = (INT)LOWORD(lParam);
3288 pt.y = (INT)HIWORD(lParam);
3289 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3290
3291 /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3292 if(infoPtr->nHotItem >= 0)
3293 infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3294
3295 if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3296 infoPtr->bCaptured = FALSE;
3297 ReleaseCapture ();
3298 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3299 btnPtr->fsState &= ~TBSTATE_PRESSED;
3300
3301 if (nHit == infoPtr->nButtonDown) {
3302 if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3303 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3304 nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3305 infoPtr->nButtonDown);
3306 if (nOldIndex == infoPtr->nButtonDown)
3307 bSendMessage = FALSE;
3308 if ((nOldIndex != infoPtr->nButtonDown) &&
3309 (nOldIndex != -1))
3310 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3311 btnPtr->fsState |= TBSTATE_CHECKED;
3312 }
3313 else {
3314 if (btnPtr->fsState & TBSTATE_CHECKED)
3315 btnPtr->fsState &= ~TBSTATE_CHECKED;
3316 else
3317 btnPtr->fsState |= TBSTATE_CHECKED;
3318 }
3319 }
3320 }
3321 else
3322 bSendMessage = FALSE;
3323
3324 if (nOldIndex != -1)
3325 InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect, TRUE);
3326
3327 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3328
3329 if (bSendMessage) {
3330 SendMessageA (GetParent(hwnd), WM_COMMAND,
3331 MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3332
3333// if ((GetWindowLongA(hwnd, GWL_STYLE) & TBSTYLE_DROPDOWN) ||
3334// (btnPtr->fsStyle & 0x08/* BTNS_DROPDOWN */)) {
3335 /*
3336 * This appears to be an error. Instead of checking the style of the
3337 * button in question wine was checking the style of the toolbar
3338 * itself. This caused a number of strange behaviors. In my
3339 * invistigation i think the whole dropdown thing is still fairly
3340 * broken. but this helps fix some of the problems.
3341 */
3342
3343 if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
3344 NMTOOLBARW nmtb;
3345
3346 nmtb.hdr.hwndFrom = hwnd;
3347 nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3348 nmtb.hdr.code = TBN_DROPDOWN;
3349 nmtb.iItem = nHit;
3350 /* nmtb.tbButton not used with TBN_DROPDOWN */
3351 if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) {
3352 nmtb.pszText = infoPtr->strings[btnPtr->iString];
3353 nmtb.cchText = lstrlenW(nmtb.pszText);
3354 } else {
3355 nmtb.pszText = NULL;
3356 nmtb.cchText = 0;
3357 }
3358 nmtb.rcButton = btnPtr->rect;
3359
3360 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
3361 (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3362 }
3363 }
3364 infoPtr->nButtonDown = -1;
3365 infoPtr->nOldHit = -1;
3366 }
3367
3368 return 0;
3369}
3370
3371static LRESULT
3372TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3373{
3374 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3375 TBUTTON_INFO *hotBtnPtr;
3376
3377 if (infoPtr->nOldHit < 0)
3378 return TRUE;
3379
3380 hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3381
3382 /* Redraw the button if the last button we were over is the hot button and it
3383 is enabled */
3384 if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3385 {
3386 hotBtnPtr->bHot = FALSE;
3387
3388 InvalidateRect (hwnd, &hotBtnPtr->rect, TRUE);
3389 }
3390
3391 infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3392 infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3393
3394 return TRUE;
3395}
3396
3397static LRESULT
3398TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3399{
3400 TBUTTON_INFO *btnPtr, *oldBtnPtr;
3401 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3402 POINT pt;
3403 INT nHit;
3404 TRACKMOUSEEVENT trackinfo;
3405
3406 /* fill in the TRACKMOUSEEVENT struct */
3407 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3408 trackinfo.dwFlags = TME_QUERY;
3409 trackinfo.hwndTrack = hwnd;
3410 trackinfo.dwHoverTime = HOVER_DEFAULT;
3411
3412 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3413 _TrackMouseEvent(&trackinfo);
3414
3415 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3416 if(!(trackinfo.dwFlags & TME_LEAVE)) {
3417 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3418
3419 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3420 /* and can properly deactivate the hot toolbar button */
3421 _TrackMouseEvent(&trackinfo);
3422 }
3423
3424 if (infoPtr->hwndToolTip)
3425 TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3426 WM_MOUSEMOVE, wParam, lParam);
3427
3428 pt.x = (INT)LOWORD(lParam);
3429 pt.y = (INT)HIWORD(lParam);
3430
3431 nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3432
3433 if (infoPtr->nOldHit != nHit)
3434 {
3435 /* Remove the effect of an old hot button if the button was enabled and was
3436 drawn with the hot button effect */
3437 if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem &&
3438 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3439 {
3440 oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3441 oldBtnPtr->bHot = FALSE;
3442
3443 InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
3444 }
3445
3446 /* It's not a separator or in nowhere. It's a hot button. */
3447 if (nHit >= 0)
3448 {
3449 btnPtr = &infoPtr->buttons[nHit];
3450 btnPtr->bHot = TRUE;
3451
3452 infoPtr->nHotItem = nHit;
3453
3454 /* only enabled buttons show hot effect */
3455 if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3456 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3457 }
3458
3459 if (infoPtr->bCaptured) {
3460 btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3461 if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3462 btnPtr->fsState &= ~TBSTATE_PRESSED;
3463 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3464 }
3465 else if (nHit == infoPtr->nButtonDown) {
3466 btnPtr->fsState |= TBSTATE_PRESSED;
3467 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
3468 }
3469 }
3470 infoPtr->nOldHit = nHit;
3471 }
3472 return 0;
3473}
3474
3475
3476inline static LRESULT
3477TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3478{
3479/* if (wndPtr->dwStyle & CCS_NODIVIDER) */
3480 return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
3481/* else */
3482/* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
3483}
3484
3485
3486inline static LRESULT
3487TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3488{
3489 if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
3490 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3491
3492 return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
3493}
3494
3495
3496static LRESULT
3497TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3498{
3499 TOOLBAR_INFO *infoPtr;
3500
3501 /* allocate memory for info structure */
3502 infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
3503 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
3504
3505 /* paranoid!! */
3506 infoPtr->dwStructSize = sizeof(TBBUTTON);
3507
3508 /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
3509 if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
3510 HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
3511 SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
3512 }
3513
3514 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
3515}
3516
3517
3518static LRESULT
3519TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3520{
3521 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3522 RECT rcWindow;
3523 HDC hdc;
3524
3525 if (dwStyle & WS_MINIMIZE)
3526 return 0; /* Nothing to do */
3527
3528 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3529
3530 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
3531 return 0;
3532
3533 if (!(dwStyle & CCS_NODIVIDER))
3534 {
3535 GetWindowRect (hwnd, &rcWindow);
3536 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3537 if( dwStyle & WS_BORDER )
3538 OffsetRect (&rcWindow, 1, 1);
3539 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
3540 }
3541
3542 ReleaseDC( hwnd, hdc );
3543
3544 return 0;
3545}
3546
3547
3548inline static LRESULT
3549TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
3550{
3551 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3552 LPNMHDR lpnmh = (LPNMHDR)lParam;
3553
3554 // TRACE("passing WM_NOTIFY!\n");
3555
3556 if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
3557 SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
3558
3559#if 0
3560 if (lpnmh->code == TTN_GETDISPINFOA) {
3561 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
3562
3563 // FIXME("retrieving ASCII string\n");
3564
3565 }
3566 else if (lpnmh->code == TTN_GETDISPINFOW) {
3567 LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
3568
3569 // FIXME("retrieving UNICODE string\n");
3570
3571 }
3572#endif
3573 }
3574
3575 return 0;
3576}
3577
3578
3579static LRESULT
3580TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
3581{
3582 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3583 HDC hdc;
3584 PAINTSTRUCT ps;
3585
3586 /* fill ps.rcPaint with a default rect */
3587 memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound));
3588
3589 TOOLBAR_CalcToolbar( hwnd );
3590 hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
3591 TOOLBAR_Refresh (hwnd, hdc, &ps);
3592 if (!wParam) EndPaint (hwnd, &ps);
3593
3594 return 0;
3595}
3596
3597
3598static LRESULT
3599TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3600{
3601 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3602 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3603 RECT parent_rect;
3604 RECT window_rect;
3605 HWND parent;
3606 INT x, y;
3607 INT cx, cy;
3608 INT flags;
3609 UINT uPosFlags = 0;
3610
3611 /* Resize deadlock check */
3612 if (infoPtr->bAutoSize) {
3613 infoPtr->bAutoSize = FALSE;
3614 return 0;
3615 }
3616
3617 flags = (INT) wParam;
3618
3619 /* FIXME for flags =
3620 * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
3621 */
3622
3623 // TRACE("sizing toolbar!\n");
3624
3625 if (flags == SIZE_RESTORED) {
3626 /* width and height don't apply */
3627 parent = GetParent (hwnd);
3628 GetClientRect(parent, &parent_rect);
3629 x = parent_rect.left;
3630 y = parent_rect.top;
3631
3632 if (dwStyle & CCS_NORESIZE) {
3633 uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
3634
3635 /*
3636 * this sets the working width of the toolbar, and
3637 * Calc Toolbar will not adjust it, only the height
3638 */
3639 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3640 cy = infoPtr->nHeight;
3641 cx = infoPtr->nWidth;
3642 TOOLBAR_CalcToolbar (hwnd);
3643 infoPtr->nWidth = cx;
3644 infoPtr->nHeight = cy;
3645 }
3646 else {
3647 infoPtr->nWidth = parent_rect.right - parent_rect.left;
3648 TOOLBAR_CalcToolbar (hwnd);
3649 cy = infoPtr->nHeight;
3650 cx = infoPtr->nWidth;
3651
3652 if (dwStyle & CCS_NOMOVEY) {
3653 GetWindowRect(hwnd, &window_rect);
3654 ScreenToClient(parent, (LPPOINT)&window_rect.left);
3655 y = window_rect.top;
3656 }
3657 }
3658
3659 if (dwStyle & CCS_NOPARENTALIGN) {
3660 uPosFlags |= SWP_NOMOVE;
3661 cy = infoPtr->nHeight;
3662 cx = infoPtr->nWidth;
3663 }
3664
3665 if (!(dwStyle & CCS_NODIVIDER))
3666 cy += GetSystemMetrics(SM_CYEDGE);
3667
3668 if (dwStyle & WS_BORDER)
3669 {
3670 x = y = 1;
3671 cy += GetSystemMetrics(SM_CYEDGE);
3672 cx += GetSystemMetrics(SM_CYEDGE);
3673 }
3674
3675 SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
3676 cx, cy, uPosFlags | SWP_NOZORDER);
3677 }
3678 return 0;
3679}
3680
3681
3682static LRESULT
3683TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
3684{
3685 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3686
3687 if (nType == GWL_STYLE) {
3688 if (lpStyle->styleNew & TBSTYLE_LIST) {
3689 infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
3690 }
3691 else {
3692 infoPtr->dwDTFlags = DT_CENTER;
3693 }
3694 }
3695
3696 TOOLBAR_AutoSize (hwnd);
3697
3698 InvalidateRect(hwnd, NULL, FALSE);
3699
3700 return 0;
3701}
3702
3703
3704
3705static LRESULT WINAPI
3706ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3707{
3708
3709 switch (uMsg)
3710 {
3711 case WM_DESTROY:
3712 return TOOLBAR_Destroy (hwnd, wParam, lParam);
3713
3714 case WM_NCCREATE:
3715 return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3716 }
3717
3718 if (!TOOLBAR_GetInfoPtr (hwnd))
3719 {
3720 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3721 }
3722
3723 switch (uMsg)
3724 {
3725 case TB_ADDBITMAP:
3726 return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
3727
3728 case TB_ADDBUTTONSA:
3729 return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
3730
3731 case TB_ADDBUTTONSW:
3732 return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
3733
3734 case TB_ADDSTRINGA:
3735 return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3736
3737 case TB_ADDSTRINGW:
3738 return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3739
3740 case TB_AUTOSIZE:
3741 return TOOLBAR_AutoSize (hwnd);
3742
3743 case TB_BUTTONCOUNT:
3744 return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3745
3746 case TB_BUTTONSTRUCTSIZE:
3747 return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3748
3749 case TB_CHANGEBITMAP:
3750 return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3751
3752 case TB_CHECKBUTTON:
3753 return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3754
3755 case TB_COMMANDTOINDEX:
3756 return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3757
3758 case TB_CUSTOMIZE:
3759 return TOOLBAR_Customize (hwnd);
3760
3761 case TB_DELETEBUTTON:
3762 return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3763
3764 case TB_ENABLEBUTTON:
3765 return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3766
3767 case TB_GETANCHORHIGHLIGHT:
3768 return TOOLBAR_GetAnchorHighlight (hwnd);
3769
3770 case TB_GETBITMAP:
3771 return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3772
3773 case TB_GETBITMAPFLAGS:
3774 return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3775
3776 case TB_GETBUTTON:
3777 return TOOLBAR_GetButton (hwnd, wParam, lParam);
3778
3779 case TB_GETBUTTONINFOA:
3780 return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3781
3782 case TB_GETBUTTONINFOW:
3783 return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
3784
3785 case TB_GETBUTTONSIZE:
3786 return TOOLBAR_GetButtonSize (hwnd);
3787
3788 case TB_GETBUTTONTEXTA:
3789 return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3790
3791 case TB_GETBUTTONTEXTW:
3792 return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
3793
3794/* case TB_GETCOLORSCHEME: */ /* 4.71 */
3795
3796 case TB_GETDISABLEDIMAGELIST:
3797 return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3798
3799 case TB_GETEXTENDEDSTYLE:
3800 return TOOLBAR_GetExtendedStyle (hwnd);
3801
3802 case TB_GETHOTIMAGELIST:
3803 return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3804
3805 case TB_GETHOTITEM:
3806 return TOOLBAR_GetHotItem (hwnd);
3807
3808 case TB_GETIMAGELIST:
3809 return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3810
3811/* case TB_GETINSERTMARK: */ /* 4.71 */
3812/* case TB_GETINSERTMARKCOLOR: */ /* 4.71 */
3813
3814 case TB_GETITEMRECT:
3815 return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3816
3817 case TB_GETMAXSIZE:
3818 return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3819
3820/* case TB_GETOBJECT: */ /* 4.71 */
3821/* case TB_GETPADDING: */ /* 4.71 */
3822
3823 case TB_GETRECT:
3824 return TOOLBAR_GetRect (hwnd, wParam, lParam);
3825
3826 case TB_GETROWS:
3827 return TOOLBAR_GetRows (hwnd, wParam, lParam);
3828
3829 case TB_GETSTATE:
3830 return TOOLBAR_GetState (hwnd, wParam, lParam);
3831
3832 case TB_GETSTYLE:
3833 return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3834
3835 case TB_GETTEXTROWS:
3836 return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3837
3838 case TB_GETTOOLTIPS:
3839 return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3840
3841 case TB_GETUNICODEFORMAT:
3842 return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3843
3844 case CCM_GETVERSION:
3845 return TOOLBAR_GetVersion (hwnd);
3846
3847 case TB_HIDEBUTTON:
3848 return TOOLBAR_HideButton (hwnd, wParam, lParam);
3849
3850 case TB_HITTEST:
3851 return TOOLBAR_HitTest (hwnd, wParam, lParam);
3852
3853 case TB_INDETERMINATE:
3854 return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3855
3856 case TB_INSERTBUTTONA:
3857 return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3858
3859 case TB_INSERTBUTTONW:
3860 return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
3861
3862/* case TB_INSERTMARKHITTEST: */ /* 4.71 */
3863
3864 case TB_ISBUTTONCHECKED:
3865 return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3866
3867 case TB_ISBUTTONENABLED:
3868 return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3869
3870 case TB_ISBUTTONHIDDEN:
3871 return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3872
3873 case TB_ISBUTTONHIGHLIGHTED:
3874 return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3875
3876 case TB_ISBUTTONINDETERMINATE:
3877 return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3878
3879 case TB_ISBUTTONPRESSED:
3880 return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3881
3882 case TB_LOADIMAGES: /* 4.70 */
3883 // FIXME("missing standard imagelists\n");
3884 return 0;
3885
3886/* case TB_MAPACCELERATORA: */ /* 4.71 */
3887/* case TB_MAPACCELERATORW: */ /* 4.71 */
3888/* case TB_MARKBUTTON: */ /* 4.71 */
3889/* case TB_MOVEBUTTON: */ /* 4.71 */
3890
3891 case TB_PRESSBUTTON:
3892 return TOOLBAR_PressButton (hwnd, wParam, lParam);
3893
3894/* case TB_REPLACEBITMAP: */
3895
3896 case TB_SAVERESTOREA:
3897 return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3898
3899 case TB_SAVERESTOREW:
3900 return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
3901
3902 case TB_SETANCHORHIGHLIGHT:
3903 return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
3904
3905 case TB_SETBITMAPSIZE:
3906 return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3907
3908 case TB_SETBUTTONINFOA:
3909 return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3910
3911 case TB_SETBUTTONINFOW:
3912 return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
3913
3914 case TB_SETBUTTONSIZE:
3915 return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3916
3917 case TB_SETBUTTONWIDTH:
3918 return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3919
3920 case TB_SETCMDID:
3921 return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3922
3923/* case TB_SETCOLORSCHEME: */ /* 4.71 */
3924
3925 case TB_SETDISABLEDIMAGELIST:
3926 return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3927
3928 case TB_SETDRAWTEXTFLAGS:
3929 return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3930
3931 case TB_SETEXTENDEDSTYLE:
3932 return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3933
3934 case TB_SETHOTIMAGELIST:
3935 return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3936
3937 case TB_SETHOTITEM:
3938 return TOOLBAR_SetHotItem (hwnd, wParam);
3939
3940 case TB_SETIMAGELIST:
3941 return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3942
3943 case TB_SETINDENT:
3944 return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3945
3946/* case TB_SETINSERTMARK: */ /* 4.71 */
3947
3948 case TB_SETINSERTMARKCOLOR:
3949 return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3950
3951 case TB_SETMAXTEXTROWS:
3952 return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3953
3954/* case TB_SETPADDING: */ /* 4.71 */
3955
3956 case TB_SETPARENT:
3957 return TOOLBAR_SetParent (hwnd, wParam, lParam);
3958
3959 case TB_SETROWS:
3960 return TOOLBAR_SetRows (hwnd, wParam, lParam);
3961
3962 case TB_SETSTATE:
3963 return TOOLBAR_SetState (hwnd, wParam, lParam);
3964
3965 case TB_SETSTYLE:
3966 return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3967
3968 case TB_SETTOOLTIPS:
3969 return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3970
3971 case TB_SETUNICODEFORMAT:
3972 return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3973
3974 case CCM_SETVERSION:
3975 return TOOLBAR_SetVersion (hwnd, (INT)wParam);
3976
3977
3978/* case WM_CHAR: */
3979
3980 case WM_CREATE:
3981 return TOOLBAR_Create (hwnd, wParam, lParam);
3982
3983 case WM_ERASEBKGND:
3984 return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
3985
3986 case WM_GETFONT:
3987 return TOOLBAR_GetFont (hwnd, wParam, lParam);
3988
3989/* case WM_KEYDOWN: */
3990/* case WM_KILLFOCUS: */
3991
3992 case WM_LBUTTONDBLCLK:
3993 return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
3994
3995 case WM_LBUTTONDOWN:
3996 return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
3997
3998 case WM_LBUTTONUP:
3999 return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4000
4001 case WM_MOUSEMOVE:
4002 return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4003
4004 case WM_MOUSELEAVE:
4005 return TOOLBAR_MouseLeave (hwnd, wParam, lParam);
4006
4007 case WM_NCACTIVATE:
4008 return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4009
4010 case WM_NCCALCSIZE:
4011 return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4012
4013 case WM_NCPAINT:
4014 return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4015
4016 case WM_NOTIFY:
4017 return TOOLBAR_Notify (hwnd, wParam, lParam);
4018
4019/* case WM_NOTIFYFORMAT: */
4020
4021 case WM_PAINT:
4022 return TOOLBAR_Paint (hwnd, wParam);
4023
4024 case WM_SIZE:
4025 return TOOLBAR_Size (hwnd, wParam, lParam);
4026
4027 case WM_STYLECHANGED:
4028 return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4029
4030/* case WM_SYSCOLORCHANGE: */
4031
4032/* case WM_WININICHANGE: */
4033
4034 case WM_CHARTOITEM:
4035 case WM_COMMAND:
4036 case WM_DRAWITEM:
4037 case WM_MEASUREITEM:
4038 case WM_VKEYTOITEM:
4039 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4040
4041 default:
4042// if (uMsg >= WM_USER)
4043// ERR (toolbar, "unknown msg %04x wp=%08x lp=%08lx\n",
4044// uMsg, wParam, lParam);
4045 return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
4046 }
4047 return 0;
4048}
4049
4050
4051VOID
4052TOOLBAR_Register (void)
4053{
4054 WNDCLASSA wndClass;
4055
4056 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4057 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4058 wndClass.lpfnWndProc = (WNDPROC)ToolbarWindowProc;
4059 wndClass.cbClsExtra = 0;
4060 wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *);
4061 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4062 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4063 wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4064
4065 RegisterClassA (&wndClass);
4066}
4067
4068
4069VOID
4070TOOLBAR_Unregister (void)
4071{
4072 UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
4073}
4074
Note: See TracBrowser for help on using the repository browser.