source: trunk/src/comctl32/toolbar.c@ 2162

Last change on this file since 2162 was 2162, checked in by achimha, 26 years ago

dirty workaround for crash in customize dialog

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