source: trunk/src/comctl32/rebar.c@ 5655

Last change on this file since 5655 was 5630, checked in by sandervl, 24 years ago

wine resync

File size: 97.1 KB
Line 
1/*
2 * Rebar control rev 6e
3 *
4 * Copyright 1998, 1999 Eric Kohl
5 *
6 * NOTES
7 * An author is needed! Any volunteers?
8 * I will only improve this control once in a while.
9 * Eric <ekohl@abo.rhein-zeitung.de>
10 *
11 * TODO:
12 * - vertical placement
13 * - ComboBox and ComboBoxEx placement
14 * - center image
15 * - Layout code.
16 * - Display code.
17 * - Some messages.
18 * - All notifications.
19
20 * Changes Guy Albertelli <galberte@neo.lrun.com>
21 * rev 2,3,4
22 * - Implement initial version of row grouping, row separators,
23 * text and background colors. Support additional messages.
24 * Support RBBS_BREAK. Implement ERASEBKGND and improve painting.
25 * rev 5
26 * - implement support for dragging Gripper left or right in a row. Supports
27 * WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE. Also support
28 * RBS_BANDBORDERS.
29 * rev 6
30 * 1. Make drawing of rebar attempt to match pixel by pixel with MS. (6a)
31 * 2. Fix interlock between REBAR_ForceResize and REBAR_Size (AUTO_RESIZE flag) (6a)
32 * 3. Fix up some of the notifications (RBN_HEIGHTCHANGE). (6a)
33 * 4. Fix up DeleteBand by hiding child window. (6a)
34 * 5. Change how band borders are drawn and rects are invalidated. (6b)
35 * 6. Fix height of bar with only caption text. (6b)
36 * 7. RBBS_NOGRIPPER trumps RBBS_GRIPPERALWAYS (gripper hidden), but
37 * RBBS_GRIPPERALWAYS trumps RBBS_FIXEDSIZE (gripper displays). (6b)
38 * 8. New algorithim for AdjustBand:
39 * For all bands in a row: bands left to right are sized to their "cx"
40 * size (if space available). Also use max of (cxHeader+cxMinChild) and
41 * cx. (6c)
42 * 9. New alogrithim for Layout:
43 * Insert band in row if cxHeader space is available. If adjustment
44 * rect exists, then back out bands in row from last to second into
45 * separate rows till "y" adjustment rect equalled or exceeded. (6c)
46 * 10. Implement vertical drag. (6c)
47 * 11. Use DeferWindowPos to set child window position. (6c)
48 * 12. Fixup RBN_CHILDSIZE notify. The rcBand rectangle should start
49 * after the header. (6d)
50 * 13. Flags for DeferWindowPos seem to always be SWP_NOZORDER in the
51 * traces. (6d)
52 * 14. Make handling of ComboBox and ComboBoxEx the same in
53 * _MoveChildWindow. (6d)
54 * 15. Changes in phase 2 of _Layout for WinRAR example. (6e)
55 * 16. Do notify change size of children for WM_SIZE message. (6e)
56 * 17. Re-validate first band when second is added (for gripper add). (6e)
57 *
58 *
59 *
60 * Still to do:
61 * 1. default row height should be the max height of all visible bands
62 * 2. Following still not handled: RBBS_FIXEDBMP, RBBS_CHILDEDGE,
63 * RBBS_USECHEVRON
64 * 3. RBS_VARHEIGHT is assumed to always be on.
65 * 4. RBBS_HIDDEN (and the CCS_VERT + RBBS_NOVERT case) is not really
66 * supported by the following functions:
67 * _Layout (phase 2), _InternalEraseBkgnd, _InternalHitTest,
68 * _HandleLRDrag
69 * 5. _HandleLRDrag does not properly position ComboBox or ComboBoxEx
70 * children. (See code in _MoveChildWindow.)
71
72 */
73
74#include <stdlib.h>
75#include <string.h>
76
77#include "winbase.h"
78#include "wingdi.h"
79#include "wine/unicode.h"
80#include "commctrl.h"
81#include "debugtools.h"
82#ifdef __WIN32OS2__
83#include "ccbase.h"
84#endif
85
86DEFAULT_DEBUG_CHANNEL(rebar);
87
88typedef struct
89{
90 UINT fStyle;
91 UINT fMask;
92 COLORREF clrFore;
93 COLORREF clrBack;
94 INT iImage;
95 HWND hwndChild;
96 UINT cxMinChild;
97 UINT cyMinChild;
98 UINT cx;
99 HBITMAP hbmBack;
100 UINT wID;
101 UINT cyChild;
102 UINT cyMaxChild;
103 UINT cyIntegral;
104 UINT cxIdeal;
105 LPARAM lParam;
106 UINT cxHeader;
107
108 UINT lcx; /* minimum cx for band */
109 UINT hcx; /* maximum cx for band */
110 UINT lcy; /* minimum cy for band */
111 UINT hcy; /* maximum cy for band */
112
113 SIZE offChild; /* x,y offset if child is not FIXEDSIZE */
114 UINT uMinHeight;
115 INT iRow; /* row this band assigned to */
116 UINT fStatus; /* status flags, reset only by _Validate */
117 UINT fDraw; /* drawing flags, reset only by _Layout */
118 RECT rcBand; /* calculated band rectangle */
119 RECT rcGripper; /* calculated gripper rectangle */
120 RECT rcCapImage; /* calculated caption image rectangle */
121 RECT rcCapText; /* calculated caption text rectangle */
122 RECT rcChild; /* calculated child rectangle */
123
124 LPWSTR lpText;
125 HWND hwndPrevParent;
126} REBAR_BAND;
127
128/* fStatus flags */
129#define HAS_GRIPPER 0x00000001
130#define HAS_IMAGE 0x00000002
131#define HAS_TEXT 0x00000004
132
133/* fDraw flags */
134#define DRAW_GRIPPER 0x00000001
135#define DRAW_IMAGE 0x00000002
136#define DRAW_TEXT 0x00000004
137#define DRAW_RIGHTSEP 0x00000010
138#define DRAW_BOTTOMSEP 0x00000020
139#define DRAW_SEPBOTH (DRAW_RIGHTSEP | DRAW_BOTTOMSEP)
140#define NTF_INVALIDATE 0x01000000
141#define NTF_CHILDSIZE 0x02000000
142
143
144typedef struct
145{
146#ifdef __WIN32OS2__
147 COMCTL32_HEADER header;
148#endif
149 COLORREF clrBk; /* background color */
150 COLORREF clrText; /* text color */
151 HIMAGELIST himl; /* handle to imagelist */
152 UINT uNumBands; /* number of bands in the rebar */
153 UINT uNumRows; /* number of rows of bands */
154 HWND hwndToolTip; /* handle to the tool tip control */
155 HWND hwndNotify; /* notification window (parent) */
156 HFONT hFont; /* handle to the rebar's font */
157 SIZE imageSize; /* image size (image list) */
158
159 SIZE calcSize; /* calculated rebar size */
160 SIZE oldSize; /* previous calculated rebar size */
161 BOOL bUnicode; /* Unicode flag */
162 UINT fStatus; /* Status flags (see below) */
163 HCURSOR hcurArrow; /* handle to the arrow cursor */
164 HCURSOR hcurHorz; /* handle to the EW cursor */
165 HCURSOR hcurVert; /* handle to the NS cursor */
166 HCURSOR hcurDrag; /* handle to the drag cursor */
167 INT iVersion; /* version number */
168 POINTS dragStart; /* x,y of button down */
169 POINTS dragNow; /* x,y of this MouseMove */
170 INT ihitBand; /* band number of band whose gripper was grabbed */
171 INT ihitoffset; /* offset of hotspot from gripper.left */
172
173 REBAR_BAND *bands; /* pointer to the array of rebar bands */
174} REBAR_INFO;
175
176/* fStatus flags */
177#define BEGIN_DRAG_ISSUED 1
178#define AUTO_RESIZE 2
179#define RESIZE_ANYHOW 4
180#define NTF_HGHTCHG 8
181
182/* ---- REBAR layout constants. Mostly determined by ---- */
183/* ---- experiment on WIN 98. ---- */
184
185/* Width (or height) of separators between bands (either horz. or */
186/* vert.). True only if RBS_BANDBORDERS is set */
187#define SEP_WIDTH_SIZE 2
188#define SEP_WIDTH ((dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
189
190/* Blank (background color) space between Gripper (if present) */
191/* and next item (image, text, or window). Always present */
192#define REBAR_ALWAYS_SPACE 4
193
194/* Blank (background color) space after Image (if present). */
195#define REBAR_POST_IMAGE 2
196
197/* Blank (background color) space after Text (if present). */
198#define REBAR_POST_TEXT 4
199
200/* Height of vertical gripper in a CCS_VERT rebar. */
201#define GRIPPER_HEIGHT 16
202
203/* Blank (background color) space before Gripper (if present). */
204#define REBAR_PRE_GRIPPER 2
205
206/* Width (of normal vertical gripper) or height (of horz. gripper) */
207/* if present. */
208#define GRIPPER_WIDTH 3
209
210/* This is the increment that is used over the band height */
211/* Determined by experiment. */
212#define REBARSPACE 4
213
214/* ---- End of REBAR layout constants. ---- */
215
216
217/* The following 4 defines return the proper rcBand element */
218/* depending on whether CCS_VERT was set. */
219#define rcBlt(b) ((dwStyle & CCS_VERT) ? b->rcBand.top : b->rcBand.left)
220#define rcBrb(b) ((dwStyle & CCS_VERT) ? b->rcBand.bottom : b->rcBand.right)
221#define ircBlt(b) ((dwStyle & CCS_VERT) ? b->rcBand.left : b->rcBand.top)
222#define ircBrb(b) ((dwStyle & CCS_VERT) ? b->rcBand.right : b->rcBand.bottom)
223
224/* The following define determines if a given band is hidden */
225#define HIDDENBAND(a) (((a)->fStyle & RBBS_HIDDEN) || \
226 ((dwStyle & CCS_VERT) && \
227 ((a)->fStyle & RBBS_NOVERT)))
228
229
230#define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongA (hwnd, 0))
231
232
233/* "constant values" retrieved when DLL was initialized */
234/* FIXME we do this when the classes are registered. */
235static UINT mindragx = 0;
236static UINT mindragy = 0;
237
238
239static VOID
240REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
241{
242 TRACE("band info: ID=%u, size=%u, style=0x%08x, mask=0x%08x, child=%04x\n",
243 pB->wID, pB->cbSize, pB->fStyle, pB->fMask, pB->hwndChild);
244 TRACE("band info: cx=%u, xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
245 pB->cx, pB->cxMinChild,
246 pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
247 TRACE("band info: xIdeal=%u, xHeader=%u, lParam=0x%08lx, clrF=0x%06lx, clrB=0x%06lx\n",
248 pB->cxIdeal, pB->cxHeader, pB->lParam, pB->clrFore, pB->clrBack);
249}
250
251static VOID
252REBAR_DumpBand (HWND hwnd)
253{
254 REBAR_INFO *iP = REBAR_GetInfoPtr (hwnd);
255 REBAR_BAND *pB;
256 UINT i;
257
258 if( TRACE_ON(rebar) ) {
259
260 TRACE("hwnd=%04x: color=%08lx/%08lx, bands=%u, rows=%u, cSize=%ld,%ld\n",
261 hwnd, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
262 iP->calcSize.cx, iP->calcSize.cy);
263 TRACE("hwnd=%04x: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, ihitBand=%d\n",
264 hwnd, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
265 iP->dragNow.x, iP->dragNow.y,
266 iP->ihitBand);
267 for (i = 0; i < iP->uNumBands; i++) {
268 pB = &iP->bands[i];
269 TRACE("band # %u: ID=%u, mask=0x%08x, style=0x%08x, child=%04x, row=%u\n",
270 i, pB->wID, pB->fMask, pB->fStyle, pB->hwndChild, pB->iRow);
271 TRACE("band # %u: xMin=%u, yMin=%u, cx=%u, yChild=%u, yMax=%u, yIntgl=%u, uMinH=%u,\n",
272 i, pB->cxMinChild, pB->cyMinChild, pB->cx,
273 pB->cyChild, pB->cyMaxChild, pB->cyIntegral, pB->uMinHeight);
274 TRACE("band # %u: header=%u, lcx=%u, hcx=%u, lcy=%u, hcy=%u, offChild=%ld,%ld\n",
275 i, pB->cxHeader, pB->lcx, pB->hcx, pB->lcy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
276 TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n",
277 i, pB->fStatus, pB->fDraw,
278 pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
279 pB->rcGripper.left, pB->rcGripper.top, pB->rcGripper.right, pB->rcGripper.bottom);
280 TRACE("band # %u: Img=(%d,%d)-(%d,%d), Txt=(%d,%d)-(%d,%d), Child=(%d,%d)-(%d,%d)\n",
281 i,
282 pB->rcCapImage.left, pB->rcCapImage.top, pB->rcCapImage.right, pB->rcCapImage.bottom,
283 pB->rcCapText.left, pB->rcCapText.top, pB->rcCapText.right, pB->rcCapText.bottom,
284 pB->rcChild.left, pB->rcChild.top, pB->rcChild.right, pB->rcChild.bottom);
285 }
286
287 }
288}
289
290static INT
291REBAR_Notify (HWND hwnd, NMHDR *nmhdr, REBAR_INFO *infoPtr, UINT code)
292{
293 HWND parent, owner;
294
295 parent = infoPtr->hwndNotify;
296 if (!parent) {
297 parent = GetParent (hwnd);
298 owner = GetWindow (hwnd, GW_OWNER);
299 if (owner) parent = owner;
300 }
301 nmhdr->idFrom = GetDlgCtrlID (hwnd);
302 nmhdr->hwndFrom = hwnd;
303 nmhdr->code = code;
304
305 return SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
306 (LPARAM)nmhdr);
307}
308
309static INT
310REBAR_Notify_NMREBAR (HWND hwnd, REBAR_INFO *infoPtr, UINT uBand, UINT code)
311{
312 NMREBAR notify_rebar;
313 REBAR_BAND *lpBand;
314
315 notify_rebar.dwMask = 0;
316 if (uBand!=-1) {
317 lpBand = &infoPtr->bands[uBand];
318 if (lpBand->fMask & RBBIM_ID) {
319 notify_rebar.dwMask |= RBNM_ID;
320 notify_rebar.wID = lpBand->wID;
321 }
322 if (lpBand->fMask & RBBIM_LPARAM) {
323 notify_rebar.dwMask |= RBNM_LPARAM;
324 notify_rebar.lParam = lpBand->lParam;
325 }
326 if (lpBand->fMask & RBBIM_STYLE) {
327 notify_rebar.dwMask |= RBNM_STYLE;
328 notify_rebar.fStyle = lpBand->fStyle;
329 }
330 }
331 notify_rebar.uBand = uBand;
332 return REBAR_Notify (hwnd, (NMHDR *)&notify_rebar, infoPtr, code);
333}
334
335static VOID
336REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand, DWORD dwStyle)
337{
338
339 /* draw separators on both the bottom and right */
340 if ((lpBand->fDraw & DRAW_SEPBOTH) == DRAW_SEPBOTH) {
341 RECT rcSep;
342 SetRect (&rcSep,
343 lpBand->rcBand.left,
344 lpBand->rcBand.top,
345 lpBand->rcBand.right + SEP_WIDTH_SIZE,
346 lpBand->rcBand.bottom + SEP_WIDTH_SIZE);
347 DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOMRIGHT);
348 TRACE("drawing band separator both (%d,%d)-(%d,%d)\n",
349 rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
350 }
351
352 /* draw band separator between bands in a row */
353 if ((lpBand->fDraw & DRAW_SEPBOTH) == DRAW_RIGHTSEP) {
354 RECT rcSep;
355 if (dwStyle & CCS_VERT) {
356 SetRect (&rcSep,
357 lpBand->rcBand.left,
358 lpBand->rcBand.bottom,
359 lpBand->rcBand.right,
360 lpBand->rcBand.bottom + SEP_WIDTH_SIZE);
361 DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
362 }
363 else {
364 SetRect (&rcSep,
365 lpBand->rcBand.right,
366 lpBand->rcBand.top,
367 lpBand->rcBand.right + SEP_WIDTH_SIZE,
368 lpBand->rcBand.bottom);
369 DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
370 }
371 TRACE("drawing band separator right (%d,%d)-(%d,%d)\n",
372 rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
373 }
374
375 /* draw band separator between rows */
376 if ((lpBand->fDraw & DRAW_SEPBOTH) == DRAW_BOTTOMSEP) {
377 RECT rcRowSep;
378 if (dwStyle & CCS_VERT) {
379 SetRect (&rcRowSep,
380 lpBand->rcBand.right,
381 lpBand->rcBand.top,
382 lpBand->rcBand.right + SEP_WIDTH_SIZE,
383 lpBand->rcBand.bottom);
384 DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
385 }
386 else {
387 SetRect (&rcRowSep,
388 lpBand->rcBand.left,
389 lpBand->rcBand.bottom,
390 lpBand->rcBand.right,
391 lpBand->rcBand.bottom + SEP_WIDTH_SIZE);
392 DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
393 }
394 TRACE ("drawing band separator bottom (%d,%d)-(%d,%d)\n",
395 rcRowSep.left, rcRowSep.top,
396 rcRowSep.right, rcRowSep.bottom);
397 }
398
399 /* draw gripper */
400 if (lpBand->fDraw & DRAW_GRIPPER)
401 DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
402
403 /* draw caption image */
404 if (lpBand->fDraw & DRAW_IMAGE) {
405 POINT pt;
406
407 /* center image */
408 pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
409 pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;
410
411 ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
412 pt.x, pt.y,
413 ILD_TRANSPARENT);
414 }
415
416 /* draw caption text */
417 if (lpBand->fDraw & DRAW_TEXT) {
418 HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
419 INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
420 COLORREF oldcolor = CLR_NONE;
421 if (lpBand->clrFore != CLR_NONE)
422 oldcolor = SetTextColor (hdc, lpBand->clrFore);
423 DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
424 DT_CENTER | DT_VCENTER | DT_SINGLELINE);
425 if (oldBkMode != TRANSPARENT)
426 SetBkMode (hdc, oldBkMode);
427 if (lpBand->clrFore != CLR_NONE)
428 SetTextColor (hdc, oldcolor);
429 SelectObject (hdc, hOldFont);
430 }
431}
432
433
434static VOID
435REBAR_Refresh (HWND hwnd, HDC hdc)
436{
437 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
438 REBAR_BAND *lpBand;
439 UINT i, oldrow;
440 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
441
442 oldrow = infoPtr->bands[0].iRow;
443 for (i = 0; i < infoPtr->uNumBands; i++) {
444 lpBand = &infoPtr->bands[i];
445
446 if ((lpBand->fStyle & RBBS_HIDDEN) ||
447 ((dwStyle & CCS_VERT) &&
448 (lpBand->fStyle & RBBS_NOVERT)))
449 continue;
450
451 /* now draw the band */
452 REBAR_DrawBand (hdc, infoPtr, lpBand, dwStyle);
453
454 }
455}
456
457static void
458REBAR_AdjustBands (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
459 INT maxx, INT usedx, INT mcy, DWORD dwStyle)
460 /* Function: This routine distributes the extra space in a row */
461 /* by increasing bands from left to right to their "cx" width.*/
462 /* Uses "cxHeader"+"cxMinChild" if it is bigger than "cx". */
463{
464 REBAR_BAND *lpBand;
465 UINT i;
466 INT j, k;
467 INT incr, current_width, lastx=0;
468 RECT oldband;
469
470 TRACE("start=%u, end=%u, max x=%d, used x=%d, max y=%d\n",
471 rowstart, rowend-1, maxx, usedx, mcy);
472
473 incr = maxx - usedx;
474
475 for (i = rowstart; i<rowend; i++) {
476 lpBand = &infoPtr->bands[i];
477 if (HIDDENBAND(lpBand)) continue;
478 j = 0;
479 k = 0;
480 oldband = lpBand->rcBand;
481
482 /* get the current width of the band */
483 if (dwStyle & CCS_VERT)
484 current_width = lpBand->rcBand.bottom - lpBand->rcBand.top;
485 else
486 current_width = lpBand->rcBand.right - lpBand->rcBand.left;
487
488 /* compute (in "j") the adjustment for this band */
489 /* FIXME ??? should this not use "cx" and "cxHeader" and "cxMinChild" */
490 if (!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
491 if ((lpBand->fMask & RBBIM_SIZE) && (lpBand->cx > 0))
492 j = min(lpBand->cx - current_width, incr);
493 if ((lpBand->fMask & RBBIM_CHILDSIZE) &&
494 (lpBand->cxMinChild > 0) &&
495 (lpBand->fMask & RBBIM_CHILD) &&
496 (lpBand->hwndChild)) {
497 k = lpBand->cxHeader + lpBand->cxMinChild - current_width;
498 if (k > 0) {
499 j = max(k, j);
500 j = min(j, incr);
501 }
502 }
503 }
504
505 incr -= j;
506
507 /* validate values */
508 if (incr < 0) {
509 ERR("failed, incr=%d, current_width=%d, j=%d, k=%d\n",
510 incr, current_width, j, k);
511 j -= incr;
512 incr = 0;
513 }
514 if (lastx + j + current_width > maxx) {
515 ERR("exceeded maximum, lastx=%d, j=%d, current_width=%d\n",
516 lastx, j, current_width);
517 j = maxx - lastx - current_width;
518 incr = 0;
519 }
520
521 /* adjust the band rectangle for adding width */
522 /* and setting height of all bands in row. */
523 if (dwStyle & CCS_VERT) {
524 lpBand->rcBand.top = lastx;
525 lpBand->rcBand.bottom = lastx + j + current_width;
526 if ((lpBand->rcBand.top != oldband.top) ||
527 (lpBand->rcBand.bottom != oldband.bottom))
528 lpBand->fDraw |= NTF_INVALIDATE;
529 if (lpBand->rcBand.right != lpBand->rcBand.left + mcy) {
530 lpBand->rcBand.right = lpBand->rcBand.left + mcy;
531 lpBand->fDraw |= NTF_INVALIDATE;
532 }
533 }
534 else {
535 lpBand->rcBand.left = lastx;
536 lpBand->rcBand.right = lastx + j + current_width;
537 if ((lpBand->rcBand.left != oldband.left) ||
538 (lpBand->rcBand.right != oldband.right))
539 lpBand->fDraw |= NTF_INVALIDATE;
540 if (lpBand->rcBand.bottom != lpBand->rcBand.top + mcy) {
541 lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
542 lpBand->fDraw |= NTF_INVALIDATE;
543 }
544 }
545
546 /* update to the next band start */
547 lastx += (j + current_width + SEP_WIDTH);
548 if (j) {
549 TRACE("band %d row=%d: changed to (%d,%d)-(%d,%d)\n",
550 i, lpBand->iRow,
551 lpBand->rcBand.left, lpBand->rcBand.top,
552 lpBand->rcBand.right, lpBand->rcBand.bottom);
553 }
554 else {
555 TRACE("band %d row=%d: unchanged (%d,%d)-(%d,%d)\n",
556 i, lpBand->iRow,
557 lpBand->rcBand.left, lpBand->rcBand.top,
558 lpBand->rcBand.right, lpBand->rcBand.bottom);
559 }
560 }
561
562 /* if any remaining space then add to the rowstart band */
563 if (incr > 0) {
564 lpBand = &infoPtr->bands[rowstart];
565 lpBand->rcBand.right += incr;
566 TRACE("band %d row=%d: extended to (%d,%d)-(%d,%d)\n",
567 rowstart, lpBand->iRow,
568 lpBand->rcBand.left, lpBand->rcBand.top,
569 lpBand->rcBand.right, lpBand->rcBand.bottom);
570 for (i=rowstart+1; i<rowend; i++) {
571 lpBand = &infoPtr->bands[i];
572 if (HIDDENBAND(lpBand)) continue;
573 lpBand->rcBand.left += incr;
574 lpBand->rcBand.right += incr;
575 lpBand->fDraw |= NTF_INVALIDATE;
576 }
577 }
578}
579
580static void
581REBAR_CalcHorzBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify, DWORD dwStyle)
582 /* Function: this routine initializes all the rectangles in */
583 /* each band in a row to fit in the adjusted rcBand rect. */
584 /* *** Supports only Horizontal bars. *** */
585{
586 REBAR_BAND *lpBand;
587 UINT i, xoff, yoff;
588 HWND parenthwnd;
589 RECT oldChild, work;
590
591 /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
592 parenthwnd = GetParent (hwnd);
593
594 for(i=rstart; i<rend; i++){
595 lpBand = &infoPtr->bands[i];
596 if (HIDDENBAND(lpBand)) {
597 SetRect (&lpBand->rcChild,
598 lpBand->rcBand.right, lpBand->rcBand.top,
599 lpBand->rcBand.right, lpBand->rcBand.bottom);
600 continue;
601 }
602
603 oldChild = lpBand->rcChild;
604
605 /* set initial gripper rectangle */
606 SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
607 lpBand->rcBand.left, lpBand->rcBand.bottom);
608
609 /* calculate gripper rectangle */
610 if ( lpBand->fStatus & HAS_GRIPPER) {
611 lpBand->fDraw |= DRAW_GRIPPER;
612 lpBand->rcGripper.left += REBAR_PRE_GRIPPER;
613 lpBand->rcGripper.right = lpBand->rcGripper.left + GRIPPER_WIDTH;
614 lpBand->rcGripper.top += 2;
615 lpBand->rcGripper.bottom -= 2;
616
617 SetRect (&lpBand->rcCapImage,
618 lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.top,
619 lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.bottom);
620 }
621 else { /* no gripper will be drawn */
622 xoff = 0;
623 if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
624 /* if no gripper but either image or text, then leave space */
625 xoff = REBAR_ALWAYS_SPACE;
626 SetRect (&lpBand->rcCapImage,
627 lpBand->rcBand.left+xoff, lpBand->rcBand.top,
628 lpBand->rcBand.left+xoff, lpBand->rcBand.bottom);
629 }
630
631 /* image is visible */
632 if (lpBand->fStatus & HAS_IMAGE) {
633 lpBand->fDraw |= DRAW_IMAGE;
634 lpBand->rcCapImage.right += infoPtr->imageSize.cx;
635 lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
636
637 /* set initial caption text rectangle */
638 SetRect (&lpBand->rcCapText,
639 lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1,
640 lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
641 /* update band height
642 if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) {
643 lpBand->uMinHeight = infoPtr->imageSize.cy + 2;
644 lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight;
645 } */
646 }
647 else {
648 /* set initial caption text rectangle */
649 SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1,
650 lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
651 }
652
653 /* text is visible */
654 if (lpBand->fStatus & HAS_TEXT) {
655 lpBand->fDraw |= DRAW_TEXT;
656 lpBand->rcCapText.right = max(lpBand->rcCapText.left,
657 lpBand->rcCapText.right-REBAR_POST_TEXT);
658 }
659
660 /* set initial child window rectangle if there is a child */
661 if (lpBand->fMask & RBBIM_CHILD) {
662 xoff = lpBand->offChild.cx;
663 yoff = lpBand->offChild.cy;
664 SetRect (&lpBand->rcChild,
665 lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top+yoff,
666 lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
667 }
668 else {
669 SetRect (&lpBand->rcChild,
670 lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
671 lpBand->rcBand.right, lpBand->rcBand.bottom);
672 }
673
674 /* flag if notify required and invalidate rectangle */
675 if (notify &&
676 ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
677 (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
678 TRACE("Child rectangle changed for band %u\n", i);
679 TRACE(" from (%d,%d)-(%d,%d) to (%d,%d)-(%d,%d)\n",
680 oldChild.left, oldChild.top,
681 oldChild.right, oldChild.bottom,
682 lpBand->rcChild.left, lpBand->rcChild.top,
683 lpBand->rcChild.right, lpBand->rcChild.bottom);
684 lpBand->fDraw |= NTF_CHILDSIZE;
685 }
686 if (lpBand->fDraw & NTF_INVALIDATE) {
687 TRACE("invalidating (%d,%d)-(%d,%d)\n",
688 lpBand->rcBand.left,
689 lpBand->rcBand.top,
690 lpBand->rcBand.right + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0),
691 lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0));
692 lpBand->fDraw &= ~NTF_INVALIDATE;
693 work = lpBand->rcBand;
694 if (lpBand->fDraw & DRAW_RIGHTSEP) work.right += SEP_WIDTH_SIZE;
695 if (lpBand->fDraw & DRAW_BOTTOMSEP) work.bottom += SEP_WIDTH_SIZE;
696 InvalidateRect(hwnd, &work, TRUE);
697 }
698
699 }
700
701}
702
703
704static VOID
705REBAR_CalcVertBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify, DWORD dwStyle)
706 /* Function: this routine initializes all the rectangles in */
707 /* each band in a row to fit in the adjusted rcBand rect. */
708 /* *** Supports only Vertical bars. *** */
709{
710 REBAR_BAND *lpBand;
711 UINT i, xoff, yoff;
712 NMREBARCHILDSIZE rbcz;
713 HWND parenthwnd;
714 RECT oldChild, work;
715
716 rbcz.hdr.hwndFrom = hwnd;
717 rbcz.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
718 /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
719 parenthwnd = GetParent (hwnd);
720
721 for(i=rstart; i<rend; i++){
722 lpBand = &infoPtr->bands[i];
723 if (HIDDENBAND(lpBand)) continue;
724 oldChild = lpBand->rcChild;
725
726 /* set initial gripper rectangle */
727 SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
728 lpBand->rcBand.right, lpBand->rcBand.top);
729
730 /* calculate gripper rectangle */
731 if (lpBand->fStatus & HAS_GRIPPER) {
732 lpBand->fDraw |= DRAW_GRIPPER;
733
734 if (dwStyle & RBS_VERTICALGRIPPER) {
735 /* vertical gripper */
736 lpBand->rcGripper.left += 3;
737 lpBand->rcGripper.right = lpBand->rcGripper.left + GRIPPER_WIDTH;
738 lpBand->rcGripper.top += REBAR_PRE_GRIPPER;
739 lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
740
741 /* initialize Caption image rectangle */
742 SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
743 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
744 lpBand->rcBand.right,
745 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
746 }
747 else {
748 /* horizontal gripper */
749 lpBand->rcGripper.left += 3;
750 lpBand->rcGripper.right -= 3;
751 lpBand->rcGripper.top += REBAR_PRE_GRIPPER;
752 lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_WIDTH;
753
754 /* initialize Caption image rectangle */
755 SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
756 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
757 lpBand->rcBand.right,
758 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
759 }
760 }
761 else { /* no gripper will be drawn */
762 xoff = 0;
763 if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
764 /* if no gripper but either image or text, then leave space */
765 xoff = REBAR_ALWAYS_SPACE;
766 /* initialize Caption image rectangle */
767 SetRect (&lpBand->rcCapImage,
768 lpBand->rcBand.left, lpBand->rcBand.top+xoff,
769 lpBand->rcBand.right, lpBand->rcBand.top+xoff);
770 }
771
772 /* image is visible */
773 if (lpBand->fStatus & HAS_IMAGE) {
774 lpBand->fDraw |= DRAW_IMAGE;
775
776 lpBand->rcCapImage.right = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
777 lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;
778
779 /* set initial caption text rectangle */
780 SetRect (&lpBand->rcCapText,
781 lpBand->rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
782 lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
783 /* update band height *
784 if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) {
785 lpBand->uMinHeight = infoPtr->imageSize.cx + 2;
786 lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight;
787 } */
788 }
789 else {
790 /* set initial caption text rectangle */
791 SetRect (&lpBand->rcCapText,
792 lpBand->rcBand.left, lpBand->rcCapImage.bottom,
793 lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
794 }
795
796 /* text is visible */
797 if (lpBand->fStatus & HAS_TEXT) {
798 lpBand->fDraw |= DRAW_TEXT;
799 lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
800 lpBand->rcCapText.bottom-REBAR_POST_TEXT);
801 }
802
803 /* set initial child window rectangle if there is a child */
804 if (lpBand->fMask & RBBIM_CHILD) {
805 yoff = lpBand->offChild.cx;
806 xoff = lpBand->offChild.cy;
807 SetRect (&lpBand->rcChild,
808 lpBand->rcBand.left+xoff, lpBand->rcBand.top+lpBand->cxHeader,
809 lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
810 }
811 else {
812 SetRect (&lpBand->rcChild,
813 lpBand->rcBand.left, lpBand->rcBand.top+lpBand->cxHeader,
814 lpBand->rcBand.right, lpBand->rcBand.bottom);
815 }
816
817 /* flag if notify required and invalidate rectangle */
818 if (notify &&
819 ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
820 (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
821 TRACE("Child rectangle changed for band %u\n", i);
822 TRACE(" from (%d,%d)-(%d,%d) to (%d,%d)-(%d,%d)\n",
823 oldChild.left, oldChild.top,
824 oldChild.right, oldChild.bottom,
825 lpBand->rcChild.left, lpBand->rcChild.top,
826 lpBand->rcChild.right, lpBand->rcChild.bottom);
827 lpBand->fDraw |= NTF_CHILDSIZE;
828 }
829 if (lpBand->fDraw & NTF_INVALIDATE) {
830 TRACE("invalidating (%d,%d)-(%d,%d)\n",
831 lpBand->rcBand.left,
832 lpBand->rcBand.top,
833 lpBand->rcBand.right + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0),
834 lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0));
835 lpBand->fDraw &= ~NTF_INVALIDATE;
836 work = lpBand->rcBand;
837 if (lpBand->fDraw & DRAW_RIGHTSEP) work.bottom += SEP_WIDTH_SIZE;
838 if (lpBand->fDraw & DRAW_BOTTOMSEP) work.right += SEP_WIDTH_SIZE;
839 InvalidateRect(hwnd, &work, TRUE);
840 }
841
842 }
843}
844
845
846static VOID
847REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
848 /* Function: This routine is resposible for laying out all */
849 /* the bands in a rebar. It assigns each band to a row and*/
850 /* determines when to start a new row. */
851{
852 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
853 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
854 REBAR_BAND *lpBand, *prevBand;
855 RECT rcClient, rcAdj, rcoldBand;
856 INT x, y, cx, cxsep, mcy, clientcx, clientcy;
857 INT adjcx, adjcy, row, rightx, bottomy, origheight;
858 UINT i, rowstartband;
859 BOOL dobreak;
860
861 GetClientRect (hwnd, &rcClient);
862 TRACE("Client is (%d,%d)-(%d,%d)\n",
863 rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
864
865 if (lpRect) {
866 rcAdj = *lpRect;
867 TRACE("adjustment rect is (%d,%d)-(%d,%d)\n",
868 rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
869 }
870 else {
871 CopyRect (&rcAdj, &rcClient);
872 }
873
874 clientcx = rcClient.right - rcClient.left;
875 clientcy = rcClient.bottom - rcClient.top;
876 adjcx = rcAdj.right - rcAdj.left;
877 adjcy = rcAdj.bottom - rcAdj.top;
878 if (resetclient) {
879 TRACE("window client rect will be set to adj rect\n");
880 clientcx = adjcx;
881 clientcy = adjcy;
882 }
883
884 /* save height of original control */
885 if (dwStyle & CCS_VERT)
886 origheight = infoPtr->calcSize.cx;
887 else
888 origheight = infoPtr->calcSize.cy;
889
890
891 /* ******* Start Phase 1 - all bands on row at minimum size ******* */
892
893 x = 0;
894 y = 0;
895 row = 1;
896 cx = 0;
897 mcy = 0;
898 prevBand = NULL;
899
900 for (i = 0; i < infoPtr->uNumBands; i++) {
901 lpBand = &infoPtr->bands[i];
902 lpBand->fDraw = 0;
903 lpBand->iRow = row;
904
905 if ((lpBand->fStyle & RBBS_HIDDEN) ||
906 ((dwStyle & CCS_VERT) && (lpBand->fStyle & RBBS_NOVERT)))
907 continue;
908
909 rcoldBand = lpBand->rcBand;
910
911 /* separator from previous band */
912 cxsep = ( ((dwStyle & CCS_VERT) ? y : x)==0) ? 0 : SEP_WIDTH;
913
914 /* Header: includes gripper, text, image */
915 cx = lpBand->cxHeader;
916 if (lpBand->fStyle & RBBS_FIXEDSIZE) cx += lpBand->lcx;
917
918 if (dwStyle & CCS_VERT)
919 dobreak = (y + cx + cxsep > adjcy);
920 else
921 dobreak = (x + cx + cxsep > adjcx);
922
923 /* This is the check for whether we need to start a new row */
924 if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
925 ( ((dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
926 TRACE("Spliting to new row %d on band %u\n", row+1, i);
927 if (dwStyle & CCS_VERT) {
928 y = 0;
929 x += (mcy + SEP_WIDTH);
930 }
931 else {
932 x = 0;
933 y += (mcy + SEP_WIDTH);
934 }
935
936 /* FIXME: if not RBS_VARHEIGHT then find max */
937 mcy = 0;
938 cxsep = 0;
939 row++;
940 lpBand->iRow = row;
941 prevBand = NULL;
942 }
943
944 if (mcy < lpBand->lcy + REBARSPACE) mcy = lpBand->lcy + REBARSPACE;
945
946 /* if boundary rect specified then limit mcy */
947 if (lpRect) {
948 if (dwStyle & CCS_VERT) {
949 if (x+mcy > adjcx) {
950 mcy = adjcx - x;
951 TRACE("row %u limiting mcy=%d, adjcx=%d, x=%d\n",
952 i, mcy, adjcx, x);
953 }
954 }
955 else {
956 if (y+mcy > adjcy) {
957 mcy = adjcy - y;
958 TRACE("row %u limiting mcy=%d, adjcy=%d, y=%d\n",
959 i, mcy, adjcy, y);
960 }
961 }
962 }
963
964 if (dwStyle & CCS_VERT) {
965 /* bound the bottom side if we have a bounding rectangle */
966 if ((x>0) && (dwStyle & RBS_BANDBORDERS) && prevBand)
967 prevBand->fDraw |= DRAW_RIGHTSEP;
968 rightx = clientcx;
969 bottomy = (lpRect) ? min(clientcy, y+cxsep+cx) : y+cxsep+cx;
970 lpBand->rcBand.left = x;
971 lpBand->rcBand.right = x + min(mcy, lpBand->lcy+REBARSPACE);
972 lpBand->rcBand.top = min(bottomy, y + cxsep);
973 lpBand->rcBand.bottom = bottomy;
974 lpBand->uMinHeight = lpBand->lcy;
975 if (!EqualRect(&rcoldBand, &lpBand->rcBand))
976 lpBand->fDraw |= NTF_INVALIDATE;
977 y = bottomy;
978 }
979 else {
980 /* bound the right side if we have a bounding rectangle */
981 if ((x>0) && (dwStyle & RBS_BANDBORDERS) && prevBand)
982 prevBand->fDraw |= DRAW_RIGHTSEP;
983 rightx = (lpRect) ? min(clientcx, x+cxsep+cx) : x+cxsep+cx;
984 bottomy = clientcy;
985 lpBand->rcBand.left = min(rightx, x + cxsep);
986 lpBand->rcBand.right = rightx;
987 lpBand->rcBand.top = y;
988 lpBand->rcBand.bottom = y + min(mcy, lpBand->lcy+REBARSPACE);
989 lpBand->uMinHeight = lpBand->lcy;
990 if (!EqualRect(&rcoldBand, &lpBand->rcBand))
991 lpBand->fDraw |= NTF_INVALIDATE;
992 x = rightx;
993 }
994 TRACE("band %u, row %d, (%d,%d)-(%d,%d)\n",
995 i, row,
996 lpBand->rcBand.left, lpBand->rcBand.top,
997 lpBand->rcBand.right, lpBand->rcBand.bottom);
998 prevBand = lpBand;
999
1000 } /* for (i = 0; i < infoPtr->uNumBands... */
1001
1002 if (dwStyle & CCS_VERT)
1003 x += mcy;
1004 else
1005 y += mcy;
1006
1007 if (infoPtr->uNumBands)
1008 infoPtr->uNumRows = row;
1009
1010 /* ******* End Phase 1 - all bands on row at minimum size ******* */
1011
1012
1013 /* ******* Start Phase 2 - split rows till adjustment height full ******* */
1014
1015 /* assumes that the following variables contain: */
1016 /* y/x current height/width of all rows */
1017 if (lpRect) {
1018 INT i, j, prev_rh, current_rh, new_rh, adj_rh;
1019 REBAR_BAND *prev, *current, *walk;
1020
1021/* if (((dwStyle & CCS_VERT) ? (x < adjcx) : (y < adjcy)) && */
1022
1023 if (((dwStyle & CCS_VERT) ? (adjcx - x > 4) : (adjcy - y > 4)) &&
1024 (infoPtr->uNumBands > 1)) {
1025 for (i=infoPtr->uNumBands-2; i>=0; i--) {
1026 TRACE("adjcx=%d, adjcy=%d, x=%d, y=%d\n",
1027 adjcx, adjcy, x, y);
1028 prev = &infoPtr->bands[i];
1029 prev_rh = ircBrb(prev) - ircBlt(prev);
1030 current = &infoPtr->bands[i+1];
1031 current_rh = ircBrb(current) - ircBlt(current);
1032 if (prev->iRow == current->iRow) {
1033 new_rh = current->lcy + REBARSPACE;
1034 adj_rh = prev_rh + new_rh + SEP_WIDTH - current_rh;
1035 infoPtr->uNumRows++;
1036 current->fDraw |= NTF_INVALIDATE;
1037 current->iRow++;
1038 if (dwStyle & CCS_VERT) {
1039 current->rcBand.top = 0;
1040 current->rcBand.bottom = clientcy;
1041 current->rcBand.left += (prev_rh + SEP_WIDTH);
1042 current->rcBand.right = current->rcBand.left + new_rh;
1043 x += adj_rh;
1044 }
1045 else {
1046 current->rcBand.left = 0;
1047 current->rcBand.right = clientcx;
1048 current->rcBand.top += (prev_rh + SEP_WIDTH);
1049 current->rcBand.bottom = current->rcBand.top + new_rh;
1050 y += adj_rh;
1051 }
1052 TRACE("moving band %d to own row at (%d,%d)-(%d,%d)\n",
1053 i+1,
1054 current->rcBand.left, current->rcBand.top,
1055 current->rcBand.right, current->rcBand.bottom);
1056 TRACE("prev band %d at (%d,%d)-(%d,%d)\n",
1057 i,
1058 prev->rcBand.left, prev->rcBand.top,
1059 prev->rcBand.right, prev->rcBand.bottom);
1060 TRACE("values: prev_rh=%d, current_rh=%d, new_rh=%d, adj_rh=%d\n",
1061 prev_rh, current_rh, new_rh, adj_rh);
1062 /* for bands below current adjust row # and top/bottom */
1063 for (j = i+2; j<infoPtr->uNumBands; j++) {
1064 walk = &infoPtr->bands[j];
1065 walk->fDraw |= NTF_INVALIDATE;
1066 walk->iRow++;
1067 if (dwStyle & CCS_VERT) {
1068 walk->rcBand.left += adj_rh;
1069 walk->rcBand.right += adj_rh;
1070 }
1071 else {
1072 walk->rcBand.top += adj_rh;
1073 walk->rcBand.bottom += adj_rh;
1074 }
1075 }
1076 if ((dwStyle & CCS_VERT) ? (x >= adjcx) : (y >= adjcy))
1077 break; /* all done */
1078 }
1079 }
1080 }
1081 }
1082
1083 /* ******* End Phase 2 - split rows till adjustment height full ******* */
1084
1085
1086
1087 /* ******* Start Phase 3 - adjust all bands for width full ******* */
1088
1089 if (infoPtr->uNumBands) {
1090 REBAR_BAND *prev, *current;
1091 /* If RBS_BANDBORDERS set then indicate to draw bottom separator */
1092 if (dwStyle & RBS_BANDBORDERS) {
1093 for (i = 0; i < infoPtr->uNumBands; i++) {
1094 lpBand = &infoPtr->bands[i];
1095 if (HIDDENBAND(lpBand)) continue;
1096 if (lpBand->iRow < infoPtr->uNumRows)
1097 lpBand->fDraw |= DRAW_BOTTOMSEP;
1098 }
1099 }
1100
1101 /* Adjust the horizontal and vertical of each band */
1102 prev = &infoPtr->bands[0];
1103 current = prev;
1104 mcy = prev->lcy + REBARSPACE;
1105 rowstartband = 0;
1106 for (i=1; i<infoPtr->uNumBands; i++) {
1107 prev = &infoPtr->bands[i-1];
1108 current = &infoPtr->bands[i];
1109 if (prev->iRow != current->iRow) {
1110 REBAR_AdjustBands (infoPtr, rowstartband, i,
1111 (dwStyle & CCS_VERT) ? clientcy : clientcx,
1112 rcBrb(prev),
1113 mcy, dwStyle);
1114 mcy = 0;
1115 rowstartband = i;
1116 }
1117 if (mcy < current->lcy + REBARSPACE)
1118 mcy = current->lcy + REBARSPACE;
1119 }
1120 REBAR_AdjustBands (infoPtr, rowstartband, infoPtr->uNumBands,
1121 (dwStyle & CCS_VERT) ? clientcy : clientcx,
1122 rcBrb(current),
1123 mcy, dwStyle);
1124
1125 /* Calculate the other rectangles in each band */
1126 if (dwStyle & CCS_VERT) {
1127 REBAR_CalcVertBand (hwnd, infoPtr, 0, infoPtr->uNumBands,
1128 notify, dwStyle);
1129 }
1130 else {
1131 REBAR_CalcHorzBand (hwnd, infoPtr, 0, infoPtr->uNumBands,
1132 notify, dwStyle);
1133 }
1134 }
1135
1136 /* ******* End Phase 3 - adjust all bands for width full ******* */
1137
1138
1139 /* FIXME: if not RBS_VARHEIGHT then find max mcy and adj rect*/
1140
1141 infoPtr->oldSize = infoPtr->calcSize;
1142 if (dwStyle & CCS_VERT) {
1143 infoPtr->calcSize.cx = x;
1144 infoPtr->calcSize.cy = clientcy;
1145 TRACE("vert, notify=%d, x=%d, origheight=%d\n",
1146 notify, x, origheight);
1147 if (notify && (x != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
1148 }
1149 else {
1150 infoPtr->calcSize.cx = clientcx;
1151 infoPtr->calcSize.cy = y;
1152 TRACE("horz, notify=%d, y=%d, origheight=%d\n",
1153 notify, y, origheight);
1154 if (notify && (y != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
1155 }
1156 REBAR_DumpBand (hwnd);
1157}
1158
1159
1160static VOID
1161REBAR_ForceResize (HWND hwnd)
1162 /* Function: This changes the size of the REBAR window to that */
1163 /* calculated by REBAR_Layout. */
1164{
1165 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1166 RECT rc;
1167
1168 TRACE( " from [%ld x %ld] to [%ld x %ld]!\n",
1169 infoPtr->oldSize.cx, infoPtr->oldSize.cy,
1170 infoPtr->calcSize.cx, infoPtr->calcSize.cy);
1171
1172 /* if size did not change then skip process */
1173 if ((infoPtr->oldSize.cx == infoPtr->calcSize.cx) &&
1174 (infoPtr->oldSize.cy == infoPtr->calcSize.cy) &&
1175 !(infoPtr->fStatus & RESIZE_ANYHOW))
1176 return;
1177
1178 infoPtr->fStatus &= ~RESIZE_ANYHOW;
1179 /* Set flag to ignore next WM_SIZE message */
1180 infoPtr->fStatus |= AUTO_RESIZE;
1181
1182 rc.left = 0;
1183 rc.top = 0;
1184 rc.right = infoPtr->calcSize.cx;
1185 rc.bottom = infoPtr->calcSize.cy;
1186
1187 if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
1188 InflateRect (&rc, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
1189 }
1190
1191 SetWindowPos (hwnd, 0, 0, 0,
1192 rc.right - rc.left, rc.bottom - rc.top,
1193 SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
1194}
1195
1196
1197static VOID
1198REBAR_MoveChildWindows (HWND hwnd)
1199{
1200 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1201 REBAR_BAND *lpBand;
1202 CHAR szClassName[40];
1203 UINT i;
1204 NMREBARCHILDSIZE rbcz;
1205 NMHDR heightchange;
1206 HDWP deferpos;
1207 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1208
1209 if (!(deferpos = BeginDeferWindowPos(8)))
1210 ERR("BeginDeferWindowPso returned NULL\n");
1211
1212 for (i = 0; i < infoPtr->uNumBands; i++) {
1213 lpBand = &infoPtr->bands[i];
1214
1215 if (HIDDENBAND(lpBand)) continue;
1216 if (lpBand->hwndChild) {
1217 TRACE("hwndChild = %x\n", lpBand->hwndChild);
1218
1219 if (lpBand->fDraw & NTF_CHILDSIZE) {
1220 lpBand->fDraw &= ~NTF_CHILDSIZE;
1221 rbcz.uBand = i;
1222 rbcz.wID = lpBand->wID;
1223 rbcz.rcChild = lpBand->rcChild;
1224 rbcz.rcBand = lpBand->rcBand;
1225 rbcz.rcBand.left += lpBand->cxHeader;
1226 REBAR_Notify (hwnd, (NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
1227 if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
1228 TRACE("Child rect changed by NOTIFY for band %u\n", i);
1229 TRACE(" from (%d,%d)-(%d,%d) to (%d,%d)-(%d,%d)\n",
1230 lpBand->rcChild.left, lpBand->rcChild.top,
1231 lpBand->rcChild.right, lpBand->rcChild.bottom,
1232 rbcz.rcChild.left, rbcz.rcChild.top,
1233 rbcz.rcChild.right, rbcz.rcChild.bottom);
1234 }
1235 }
1236
1237 GetClassNameA (lpBand->hwndChild, szClassName, 40);
1238 if (!lstrcmpA (szClassName, "ComboBox") ||
1239 !lstrcmpA (szClassName, WC_COMBOBOXEXA)) {
1240 INT nEditHeight, yPos;
1241 RECT rc;
1242
1243 /* special placement code for combo or comboex box */
1244
1245
1246 /* get size of edit line */
1247 GetWindowRect (lpBand->hwndChild, &rc);
1248 nEditHeight = rc.bottom - rc.top;
1249 yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
1250
1251 /* center combo box inside child area */
1252 TRACE("moving child (Combo(Ex)) %04x to (%d,%d)-(%d,%d)\n",
1253 lpBand->hwndChild,
1254 lpBand->rcChild.left, yPos,
1255 lpBand->rcChild.right - lpBand->rcChild.left,
1256 nEditHeight);
1257 deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
1258 lpBand->rcChild.left,
1259 /*lpBand->rcChild.top*/ yPos,
1260 lpBand->rcChild.right - lpBand->rcChild.left,
1261 nEditHeight,
1262 SWP_NOZORDER);
1263 if (!deferpos)
1264 ERR("DeferWindowPos returned NULL\n");
1265 }
1266 else {
1267 TRACE("moving child (Other) %04x to (%d,%d)-(%d,%d)\n",
1268 lpBand->hwndChild,
1269 lpBand->rcChild.left, lpBand->rcChild.top,
1270 lpBand->rcChild.right - lpBand->rcChild.left,
1271 lpBand->rcChild.bottom - lpBand->rcChild.top);
1272 deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
1273 lpBand->rcChild.left,
1274 lpBand->rcChild.top,
1275 lpBand->rcChild.right - lpBand->rcChild.left,
1276 lpBand->rcChild.bottom - lpBand->rcChild.top,
1277 SWP_NOZORDER);
1278 if (!deferpos)
1279 ERR("DeferWindowPos returned NULL\n");
1280 }
1281 }
1282 }
1283 if (!EndDeferWindowPos(deferpos))
1284 ERR("EndDeferWindowPos returned NULL\n");
1285 if (infoPtr->fStatus & NTF_HGHTCHG) {
1286 infoPtr->fStatus &= ~NTF_HGHTCHG;
1287 REBAR_Notify (hwnd, &heightchange, infoPtr, RBN_HEIGHTCHANGE);
1288 }
1289}
1290
1291
1292static VOID
1293REBAR_ValidateBand (HWND hwnd, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
1294 /* Function: This routine evaluates the band specs supplied */
1295 /* by the user and updates the following 5 fields in */
1296 /* the internal band structure: cxHeader, lcx, lcy, hcx, hcy*/
1297{
1298 UINT header=0;
1299 UINT textheight=0;
1300 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1301
1302 lpBand->fStatus = 0;
1303 lpBand->lcx = 0;
1304 lpBand->lcy = 0;
1305 lpBand->hcx = 0;
1306 lpBand->hcy = 0;
1307
1308 /* Data comming in from users into the cx... and cy... fields */
1309 /* may be bad, just garbage, because the user never clears */
1310 /* the fields. RB_{SET|INSERT}BAND{A|W} just passes the data */
1311 /* along if the fields exist in the input area. Here we must */
1312 /* determine if the data is valid. I have no idea how MS does */
1313 /* the validation, but it does because the RB_GETBANDINFO */
1314 /* returns a 0 when I know the sample program passed in an */
1315 /* address. Here I will use the algorithim that if the value */
1316 /* is greater than 65535 then it is bad and replace it with */
1317 /* a zero. Feel free to improve the algorithim. - GA 12/2000 */
1318 if (lpBand->cxMinChild > 65535) lpBand->cxMinChild = 0;
1319 if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0;
1320 if (lpBand->cx > 65535) lpBand->cx = 0;
1321 if (lpBand->cyChild > 65535) lpBand->cyChild = 0;
1322 if (lpBand->cyMaxChild > 65535) lpBand->cyMaxChild = 0;
1323 if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0;
1324 if (lpBand->cxIdeal > 65535) lpBand->cxIdeal = 0;
1325 if (lpBand->cxHeader > 65535) lpBand->cxHeader = 0;
1326
1327 /* Header is where the image, text and gripper exist */
1328 /* in the band and preceed the child window. */
1329
1330 /* calculate gripper rectangle */
1331 if ( (!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
1332 ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
1333 ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (infoPtr->uNumBands > 1)))
1334 ) {
1335 lpBand->fStatus |= HAS_GRIPPER;
1336 if (dwStyle & CCS_VERT)
1337 if (dwStyle & RBS_VERTICALGRIPPER)
1338 header += (GRIPPER_HEIGHT + REBAR_PRE_GRIPPER);
1339 else
1340 header += (GRIPPER_WIDTH + REBAR_PRE_GRIPPER);
1341 else
1342 header += (REBAR_PRE_GRIPPER + GRIPPER_WIDTH);
1343 /* Always have 4 pixels before anything else */
1344 header += REBAR_ALWAYS_SPACE;
1345 }
1346
1347 /* image is visible */
1348 if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) {
1349 lpBand->fStatus |= HAS_IMAGE;
1350 if (dwStyle & CCS_VERT) {
1351 header += (infoPtr->imageSize.cy + REBAR_POST_IMAGE);
1352 lpBand->lcy = infoPtr->imageSize.cx + 2;
1353 }
1354 else {
1355 header += (infoPtr->imageSize.cx + REBAR_POST_IMAGE);
1356 lpBand->lcy = infoPtr->imageSize.cy + 2;
1357 }
1358 }
1359
1360 /* text is visible */
1361 if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText)) {
1362 HDC hdc = GetDC (0);
1363 HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
1364 SIZE size;
1365
1366 lpBand->fStatus |= HAS_TEXT;
1367 GetTextExtentPoint32W (hdc, lpBand->lpText,
1368 lstrlenW (lpBand->lpText), &size);
1369 header += ((dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT));
1370 textheight = (dwStyle & CCS_VERT) ? 0 : size.cy;
1371
1372 SelectObject (hdc, hOldFont);
1373 ReleaseDC (0, hdc);
1374 }
1375
1376 /* if no gripper but either image or text, then leave space */
1377 if ((lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) &&
1378 !(lpBand->fStatus & HAS_GRIPPER)) {
1379 header += REBAR_ALWAYS_SPACE;
1380 }
1381
1382 /* check if user overrode the header value */
1383 if (!(lpBand->fMask & RBBIM_HEADERSIZE))
1384 lpBand->cxHeader = header;
1385
1386
1387 /* Now compute minimum size of child window */
1388 lpBand->offChild.cx = 0;
1389 lpBand->offChild.cy = 0;
1390 lpBand->lcy = textheight;
1391 if (lpBand->fMask & RBBIM_CHILDSIZE) {
1392 if (!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
1393 lpBand->offChild.cx = 4;
1394 lpBand->offChild.cy = 2;
1395 }
1396 lpBand->lcx = lpBand->cxMinChild;
1397 lpBand->lcy = max(lpBand->lcy, lpBand->cyMinChild);
1398 lpBand->hcy = lpBand->lcy;
1399 if (lpBand->fStyle & RBBS_VARIABLEHEIGHT) {
1400 if (lpBand->cyChild != 0xffffffff)
1401 lpBand->lcy = max (lpBand->cyChild, lpBand->lcy);
1402 lpBand->hcy = lpBand->cyMaxChild;
1403 }
1404 TRACE("_CHILDSIZE\n");
1405 }
1406 if (lpBand->fMask & RBBIM_SIZE) {
1407 lpBand->hcx = max (lpBand->cx, lpBand->lcx);
1408 TRACE("_SIZE\n");
1409 }
1410 else
1411 lpBand->hcx = lpBand->lcx;
1412
1413}
1414
1415static void
1416REBAR_CommonSetupBand (HWND hwnd, LPREBARBANDINFOA lprbbi, REBAR_BAND *lpBand)
1417 /* Function: This routine copies the supplied values from */
1418 /* user input (lprbbi) to the internal band structure. */
1419{
1420 lpBand->fMask |= lprbbi->fMask;
1421
1422 if (lprbbi->fMask & RBBIM_STYLE)
1423 lpBand->fStyle = lprbbi->fStyle;
1424
1425 if (lprbbi->fMask & RBBIM_COLORS) {
1426 lpBand->clrFore = lprbbi->clrFore;
1427 lpBand->clrBack = lprbbi->clrBack;
1428 }
1429
1430 if (lprbbi->fMask & RBBIM_IMAGE)
1431 lpBand->iImage = lprbbi->iImage;
1432
1433 if (lprbbi->fMask & RBBIM_CHILD) {
1434 if (lprbbi->hwndChild) {
1435 lpBand->hwndChild = lprbbi->hwndChild;
1436 lpBand->hwndPrevParent =
1437 SetParent (lpBand->hwndChild, hwnd);
1438 }
1439 else {
1440 TRACE("child: 0x%x prev parent: 0x%x\n",
1441 lpBand->hwndChild, lpBand->hwndPrevParent);
1442 lpBand->hwndChild = 0;
1443 lpBand->hwndPrevParent = 0;
1444 }
1445 }
1446
1447 if (lprbbi->fMask & RBBIM_CHILDSIZE) {
1448 lpBand->cxMinChild = lprbbi->cxMinChild;
1449 lpBand->cyMinChild = lprbbi->cyMinChild;
1450 if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
1451 lpBand->cyChild = lprbbi->cyChild;
1452 lpBand->cyMaxChild = lprbbi->cyMaxChild;
1453 lpBand->cyIntegral = lprbbi->cyIntegral;
1454 }
1455 else { /* special case - these should be zeroed out since */
1456 /* RBBIM_CHILDSIZE added these in WIN32_IE >= 0x0400 */
1457 lpBand->cyChild = 0;
1458 lpBand->cyMaxChild = 0;
1459 lpBand->cyIntegral = 0;
1460 }
1461 }
1462
1463 if (lprbbi->fMask & RBBIM_SIZE)
1464 lpBand->cx = lprbbi->cx;
1465
1466 if (lprbbi->fMask & RBBIM_BACKGROUND)
1467 lpBand->hbmBack = lprbbi->hbmBack;
1468
1469 if (lprbbi->fMask & RBBIM_ID)
1470 lpBand->wID = lprbbi->wID;
1471
1472 /* check for additional data */
1473 if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
1474 if (lprbbi->fMask & RBBIM_IDEALSIZE)
1475 lpBand->cxIdeal = lprbbi->cxIdeal;
1476
1477 if (lprbbi->fMask & RBBIM_LPARAM)
1478 lpBand->lParam = lprbbi->lParam;
1479
1480 if (lprbbi->fMask & RBBIM_HEADERSIZE)
1481 lpBand->cxHeader = lprbbi->cxHeader;
1482 }
1483}
1484
1485static LRESULT
1486REBAR_InternalEraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam, RECT *clip)
1487 /* Function: This erases the background rectangle with the */
1488 /* default brush, then with any band that has a different */
1489 /* background color. */
1490{
1491 HBRUSH hbrBackground = GetClassWord(hwnd, GCW_HBRBACKGROUND);
1492 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1493 RECT eraserect;
1494 REBAR_BAND *lpBand;
1495 INT i;
1496
1497 if (hbrBackground)
1498 FillRect( (HDC) wParam, clip, hbrBackground);
1499
1500 for(i=0; i<infoPtr->uNumBands; i++) {
1501 lpBand = &infoPtr->bands[i];
1502 if (lpBand->clrBack != CLR_NONE) {
1503 if (IntersectRect (&eraserect, clip, &lpBand->rcBand)) {
1504 /* draw background */
1505 HBRUSH brh = CreateSolidBrush (lpBand->clrBack);
1506 TRACE("backround color=0x%06lx, band (%d,%d)-(%d,%d), clip (%d,%d)-(%d,%d)\n",
1507 lpBand->clrBack,
1508 lpBand->rcBand.left,lpBand->rcBand.top,
1509 lpBand->rcBand.right,lpBand->rcBand.bottom,
1510 clip->left, clip->top,
1511 clip->right, clip->bottom);
1512 FillRect ( (HDC)wParam, &eraserect, brh);
1513 DeleteObject (brh);
1514 }
1515 }
1516 }
1517 return TRUE;
1518}
1519
1520static void
1521REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
1522{
1523 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1524 REBAR_BAND *lpBand;
1525 RECT rect;
1526 INT iCount;
1527
1528 GetClientRect (hwnd, &rect);
1529
1530 *pFlags = RBHT_NOWHERE;
1531 if (PtInRect (&rect, *lpPt))
1532 {
1533 if (infoPtr->uNumBands == 0) {
1534 *pFlags = RBHT_NOWHERE;
1535 if (pBand)
1536 *pBand = -1;
1537 TRACE("NOWHERE\n");
1538 return;
1539 }
1540 else {
1541 /* somewhere inside */
1542 infoPtr->ihitBand = -1;
1543 for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
1544 lpBand = &infoPtr->bands[iCount];
1545 if (PtInRect (&lpBand->rcBand, *lpPt)) {
1546 if (pBand)
1547 *pBand = iCount;
1548 if (PtInRect (&lpBand->rcGripper, *lpPt)) {
1549 *pFlags = RBHT_GRABBER;
1550 infoPtr->ihitBand = iCount;
1551 TRACE("ON GRABBER %d\n", iCount);
1552 return;
1553 }
1554 else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
1555 *pFlags = RBHT_CAPTION;
1556 TRACE("ON CAPTION %d\n", iCount);
1557 return;
1558 }
1559 else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
1560 *pFlags = RBHT_CAPTION;
1561 TRACE("ON CAPTION %d\n", iCount);
1562 return;
1563 }
1564 else if (PtInRect (&lpBand->rcChild, *lpPt)) {
1565 *pFlags = RBHT_CLIENT;
1566 TRACE("ON CLIENT %d\n", iCount);
1567 return;
1568 }
1569 else {
1570 *pFlags = RBHT_NOWHERE;
1571 TRACE("NOWHERE %d\n", iCount);
1572 return;
1573 }
1574 }
1575 }
1576
1577 *pFlags = RBHT_NOWHERE;
1578 if (pBand)
1579 *pBand = -1;
1580
1581 TRACE("NOWHERE\n");
1582 return;
1583 }
1584 }
1585 else {
1586 *pFlags = RBHT_NOWHERE;
1587 if (pBand)
1588 *pBand = -1;
1589 TRACE("NOWHERE\n");
1590 return;
1591 }
1592
1593 TRACE("flags=0x%X\n", *pFlags);
1594 return;
1595}
1596
1597#define READJ(b,i) {if(dwStyle & CCS_VERT) b->rcBand.bottom+=(i); \
1598 else b->rcBand.right += (i);}
1599#define LEADJ(b,i) {if(dwStyle & CCS_VERT) b->rcBand.top+=(i); \
1600 else b->rcBand.left += (i);}
1601
1602
1603static INT
1604REBAR_Shrink (REBAR_BAND *band, INT movement, INT i, DWORD dwStyle)
1605 /* Function: This attempts to shrink the given band by the */
1606 /* the amount in "movement". A shrink to the left is indi- */
1607 /* cated by "movement" being negative. "i" is merely the */
1608 /* band index for trace messages. */
1609{
1610 INT Leadjust, Readjust, avail, ret;
1611
1612 /* Note: a left drag is indicated by "movement" being negative. */
1613 /* Similarly, a right drag is indicated by "movement" */
1614 /* being positive. "movement" should never be 0, but if */
1615 /* it is then the band does not move. */
1616
1617 avail = rcBrb(band) - rcBlt(band) - band->cxHeader - band->lcx;
1618
1619 /* now compute the Left End adjustment factor and Right End */
1620 /* adjustment factor. They may be different if shrinking. */
1621 if (avail <= 0) {
1622 /* if this band is not shrinkable, then just move it */
1623 Leadjust = Readjust = movement;
1624 ret = movement;
1625 }
1626 else {
1627 if (movement < 0) {
1628 /* Drag to left */
1629 if (avail <= abs(movement)) {
1630 Readjust = movement;
1631 Leadjust = movement + avail;
1632 ret = Leadjust;
1633 }
1634 else {
1635 Readjust = movement;
1636 Leadjust = 0;
1637 ret = 0;
1638 }
1639 }
1640 else {
1641 /* Drag to right */
1642 if (avail <= abs(movement)) {
1643 Leadjust = movement;
1644 Readjust = movement - avail;
1645 ret = Readjust;
1646 }
1647 else {
1648 Leadjust = movement;
1649 Readjust = 0;
1650 ret = 0;
1651 }
1652 }
1653 }
1654
1655 /* Reasonability Check */
1656 if (rcBlt(band) + Leadjust < 0) {
1657 ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n",
1658 i, Leadjust, Readjust, movement, ret);
1659 }
1660
1661 LEADJ(band, Leadjust);
1662 READJ(band, Readjust);
1663
1664 TRACE("band %d: left=%d, right=%d, move=%d, rtn=%d, rcBand=(%d,%d)-(%d,%d)\n",
1665 i, Leadjust, Readjust, movement, ret,
1666 band->rcBand.left, band->rcBand.top,
1667 band->rcBand.right, band->rcBand.bottom);
1668 return ret;
1669}
1670
1671
1672static void
1673REBAR_HandleLRDrag (HWND hwnd, REBAR_INFO *infoPtr, POINTS *ptsmove, DWORD dwStyle)
1674 /* Function: This will implement the functionality of a */
1675 /* Gripper drag within a row. It will not implement "out- */
1676 /* of-row" drags. (They are detected and handled in */
1677 /* REBAR_MouseMove.) */
1678 /* **** FIXME Switching order of bands in a row not **** */
1679 /* **** yet implemented. **** */
1680{
1681 REBAR_BAND *hitBand, *band, *prevband, *mindBand, *maxdBand;
1682 HDWP deferpos;
1683 NMREBARCHILDSIZE cs;
1684 RECT newrect;
1685 INT imindBand = -1, imaxdBand, ihitBand, i, movement, tempx;
1686 INT RHeaderSum = 0, LHeaderSum = 0;
1687 INT compress;
1688
1689 /* on first significant mouse movement, issue notify */
1690
1691 if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
1692 if (REBAR_Notify_NMREBAR (hwnd, infoPtr, -1, RBN_BEGINDRAG)) {
1693 /* Notify returned TRUE - abort drag */
1694 infoPtr->dragStart.x = 0;
1695 infoPtr->dragStart.y = 0;
1696 infoPtr->dragNow = infoPtr->dragStart;
1697 infoPtr->ihitBand = -1;
1698 ReleaseCapture ();
1699 return ;
1700 }
1701 infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
1702 }
1703
1704 ihitBand = infoPtr->ihitBand;
1705 hitBand = &infoPtr->bands[ihitBand];
1706 imaxdBand = ihitBand; /* to suppress warning message */
1707
1708 /* find all the bands in the row of the one whose Gripper was seized */
1709 for (i=0; i<infoPtr->uNumBands; i++) {
1710 band = &infoPtr->bands[i];
1711 if (HIDDENBAND(band)) continue;
1712 if (band->iRow == hitBand->iRow) {
1713 imaxdBand = i;
1714 if (imindBand == -1) imindBand = i;
1715 /* minimum size of each band is size of header plus */
1716 /* size of minimum child plus offset of child from header plus */
1717 /* a one to separate each band. */
1718 if (i < ihitBand)
1719 LHeaderSum += (band->cxHeader + band->lcx + SEP_WIDTH);
1720 else
1721 RHeaderSum += (band->cxHeader + band->lcx + SEP_WIDTH);
1722
1723 }
1724 }
1725 if (RHeaderSum) RHeaderSum -= SEP_WIDTH; /* no separator afterlast band */
1726
1727 mindBand = &infoPtr->bands[imindBand];
1728 maxdBand = &infoPtr->bands[imaxdBand];
1729
1730 if (imindBand == imaxdBand) return; /* nothing to drag agains */
1731 if (imindBand == ihitBand) return; /* first band in row, cant drag */
1732
1733 /* limit movement to inside adjustable bands - Left */
1734 if ( (ptsmove->x < mindBand->rcBand.left) ||
1735 (ptsmove->x > maxdBand->rcBand.right) ||
1736 (ptsmove->y < mindBand->rcBand.top) ||
1737 (ptsmove->y > maxdBand->rcBand.bottom))
1738 return; /* should swap bands */
1739
1740 if (dwStyle & CCS_VERT)
1741 movement = ptsmove->y - ((hitBand->rcBand.top+REBAR_PRE_GRIPPER) -
1742 infoPtr->ihitoffset);
1743 else
1744 movement = ptsmove->x - ((hitBand->rcBand.left+REBAR_PRE_GRIPPER) -
1745 infoPtr->ihitoffset);
1746 infoPtr->dragNow = *ptsmove;
1747
1748 TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
1749 movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
1750 imaxdBand, LHeaderSum, RHeaderSum);
1751 REBAR_DumpBand (hwnd);
1752
1753 if (movement < 0) {
1754
1755 /* *** Drag left/up *** */
1756 compress = rcBlt(hitBand) - rcBlt(mindBand) -
1757 LHeaderSum;
1758 if (compress < abs(movement)) {
1759 TRACE("limiting left drag, was %d changed to %d\n",
1760 movement, -compress);
1761 movement = -compress;
1762 }
1763 for (i=ihitBand; i>=imindBand; i--) {
1764 band = &infoPtr->bands[i];
1765 if (i == ihitBand) {
1766 prevband = &infoPtr->bands[i-1];
1767 if (rcBlt(band) - movement <= rcBlt(prevband)) {
1768 tempx = movement - (rcBrb(prevband)-rcBlt(band)+1);
1769 ERR("movement bad. BUG!! was %d, left=%d, right=%d, setting to %d\n",
1770 movement, rcBlt(band), rcBlt(prevband), tempx);
1771 movement = tempx;
1772 }
1773 LEADJ(band, movement)
1774 }
1775 else
1776 movement = REBAR_Shrink (band, movement, i, dwStyle);
1777 }
1778 }
1779 else {
1780
1781 /* *** Drag right/down *** */
1782 compress = rcBrb(maxdBand) - rcBlt(hitBand) -
1783 RHeaderSum;
1784 if (compress < abs(movement)) {
1785 TRACE("limiting right drag, was %d changed to %d\n",
1786 movement, compress);
1787 movement = compress;
1788 }
1789 for (i=ihitBand-1; i<=imaxdBand; i++) {
1790 band = &infoPtr->bands[i];
1791 if (HIDDENBAND(band)) continue;
1792 if (i == ihitBand-1) {
1793 READJ(band, movement)
1794 }
1795 else
1796 movement = REBAR_Shrink (band, movement, i, dwStyle);
1797 }
1798 }
1799
1800 /* recompute all rectangles */
1801 if (dwStyle & CCS_VERT) {
1802 REBAR_CalcVertBand (hwnd, infoPtr, imindBand, imaxdBand+1,
1803 FALSE, dwStyle);
1804 }
1805 else {
1806 REBAR_CalcHorzBand (hwnd, infoPtr, imindBand, imaxdBand+1,
1807 FALSE, dwStyle);
1808 }
1809
1810 TRACE("bands after adjustment, see band # %d, %d\n",
1811 imindBand, imaxdBand);
1812 REBAR_DumpBand (hwnd);
1813
1814 SetRect (&newrect,
1815 mindBand->rcBand.left,
1816 mindBand->rcBand.top,
1817 maxdBand->rcBand.right,
1818 maxdBand->rcBand.bottom);
1819
1820 if (!(deferpos = BeginDeferWindowPos (4))) {
1821 ERR("BeginDeferWindowPos returned NULL\n");
1822 }
1823
1824 for (i=imindBand; i<=imaxdBand; i++) {
1825 band = &infoPtr->bands[i];
1826 if ((band->fMask & RBBIM_CHILD) && band->hwndChild) {
1827 cs.uBand = i;
1828 cs.wID = band->wID;
1829 cs.rcChild = band->rcChild;
1830 cs.rcBand = band->rcBand;
1831 cs.rcBand.left += band->cxHeader;
1832 REBAR_Notify (hwnd, (NMHDR *) &cs, infoPtr, RBN_CHILDSIZE);
1833 deferpos = DeferWindowPos (deferpos, band->hwndChild, HWND_TOP,
1834 cs.rcChild.left, cs.rcChild.top,
1835 cs.rcChild.right - cs.rcChild.left,
1836 cs.rcChild.bottom - cs.rcChild.top,
1837 SWP_NOZORDER);
1838 if (!deferpos) {
1839 ERR("DeferWindowPos returned NULL\n");
1840 }
1841 }
1842 }
1843
1844 if (!EndDeferWindowPos (deferpos)) {
1845 ERR("EndDeferWindowPos failed\n");
1846 }
1847
1848 InvalidateRect (hwnd, &newrect, TRUE);
1849 UpdateWindow (hwnd);
1850
1851}
1852#undef READJ
1853#undef LEADJ
1854
1855
1856
1857/* << REBAR_BeginDrag >> */
1858
1859
1860static LRESULT
1861REBAR_DeleteBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
1862{
1863 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1864 UINT uBand = (UINT)wParam;
1865 HWND childhwnd = 0;
1866 REBAR_BAND *lpBand;
1867
1868 if (uBand >= infoPtr->uNumBands)
1869 return FALSE;
1870
1871 TRACE("deleting band %u!\n", uBand);
1872 lpBand = &infoPtr->bands[uBand];
1873 REBAR_Notify_NMREBAR (hwnd, infoPtr, uBand, RBN_DELETINGBAND);
1874
1875 if (infoPtr->uNumBands == 1) {
1876 TRACE(" simple delete!\n");
1877 if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
1878 childhwnd = lpBand->hwndChild;
1879 COMCTL32_Free (infoPtr->bands);
1880 infoPtr->bands = NULL;
1881 infoPtr->uNumBands = 0;
1882 }
1883 else {
1884 REBAR_BAND *oldBands = infoPtr->bands;
1885 TRACE("complex delete! [uBand=%u]\n", uBand);
1886
1887 if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
1888 childhwnd = lpBand->hwndChild;
1889
1890 infoPtr->uNumBands--;
1891 infoPtr->bands = COMCTL32_Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands);
1892 if (uBand > 0) {
1893 memcpy (&infoPtr->bands[0], &oldBands[0],
1894 uBand * sizeof(REBAR_BAND));
1895 }
1896
1897 if (uBand < infoPtr->uNumBands) {
1898 memcpy (&infoPtr->bands[uBand], &oldBands[uBand+1],
1899 (infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND));
1900 }
1901
1902 COMCTL32_Free (oldBands);
1903 }
1904
1905 if (childhwnd)
1906 ShowWindow (childhwnd, SW_HIDE);
1907
1908 REBAR_Notify_NMREBAR (hwnd, infoPtr, -1, RBN_DELETEDBAND);
1909
1910 /* if only 1 band left the re-validate to possible eliminate gripper */
1911 if (infoPtr->uNumBands == 1)
1912 REBAR_ValidateBand (hwnd, infoPtr, &infoPtr->bands[0]);
1913
1914 REBAR_Layout (hwnd, NULL, TRUE, FALSE);
1915 infoPtr->fStatus |= RESIZE_ANYHOW;
1916 REBAR_ForceResize (hwnd);
1917 REBAR_MoveChildWindows (hwnd);
1918
1919 return TRUE;
1920}
1921
1922
1923/* << REBAR_DragMove >> */
1924/* << REBAR_EndDrag >> */
1925
1926
1927static LRESULT
1928REBAR_GetBandBorders (HWND hwnd, WPARAM wParam, LPARAM lParam)
1929{
1930 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1931 LPRECT lpRect = (LPRECT)lParam;
1932 REBAR_BAND *lpBand;
1933 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1934
1935 if (!lParam)
1936 return 0;
1937 if ((UINT)wParam >= infoPtr->uNumBands)
1938 return 0;
1939
1940 lpBand = &infoPtr->bands[(UINT)wParam];
1941
1942 /* FIXME - the following values were determined by experimentation */
1943 /* with the REBAR Control Spy. I have guesses as to what the 4 and */
1944 /* 1 are, but I am not sure. There doesn't seem to be any actual */
1945 /* difference in size of the control area with and without the */
1946 /* style. - GA */
1947 if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_BANDBORDERS) {
1948 if (dwStyle & CCS_VERT) {
1949 lpRect->left = 1;
1950 lpRect->top = lpBand->cxHeader + 4;
1951 lpRect->right = 1;
1952 lpRect->bottom = 0;
1953 }
1954 else {
1955 lpRect->left = lpBand->cxHeader + 4;
1956 lpRect->top = 1;
1957 lpRect->right = 0;
1958 lpRect->bottom = 1;
1959 }
1960 }
1961 else {
1962 lpRect->left = lpBand->cxHeader;
1963 }
1964 FIXME("stub\n");
1965 return 0;
1966}
1967
1968
1969inline static LRESULT
1970REBAR_GetBandCount (HWND hwnd)
1971{
1972 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1973
1974 TRACE("band count %u!\n", infoPtr->uNumBands);
1975
1976 return infoPtr->uNumBands;
1977}
1978
1979
1980static LRESULT
1981REBAR_GetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1982{
1983 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1984 LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
1985 REBAR_BAND *lpBand;
1986
1987 if (lprbbi == NULL)
1988 return FALSE;
1989 if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
1990 return FALSE;
1991 if ((UINT)wParam >= infoPtr->uNumBands)
1992 return FALSE;
1993
1994 TRACE("index %u\n", (UINT)wParam);
1995
1996 /* copy band information */
1997 lpBand = &infoPtr->bands[(UINT)wParam];
1998
1999 if (lprbbi->fMask & RBBIM_STYLE)
2000 lprbbi->fStyle = lpBand->fStyle;
2001
2002 if (lprbbi->fMask & RBBIM_COLORS) {
2003 lprbbi->clrFore = lpBand->clrFore;
2004 lprbbi->clrBack = lpBand->clrBack;
2005 if (lprbbi->clrBack == CLR_NONE)
2006 lprbbi->clrBack = GetSysColor (COLOR_BTNFACE);
2007 }
2008
2009 if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2010 if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
2011 {
2012 if (!WideCharToMultiByte( CP_ACP, 0, lpBand->lpText, -1,
2013 lprbbi->lpText, lprbbi->cch, NULL, NULL ))
2014 lprbbi->lpText[lprbbi->cch-1] = 0;
2015 }
2016 else
2017 *lprbbi->lpText = 0;
2018 }
2019
2020 if (lprbbi->fMask & RBBIM_IMAGE) {
2021 if (lpBand->fMask & RBBIM_IMAGE)
2022 lprbbi->iImage = lpBand->iImage;
2023 else
2024 lprbbi->iImage = -1;
2025 }
2026
2027 if (lprbbi->fMask & RBBIM_CHILD)
2028 lprbbi->hwndChild = lpBand->hwndChild;
2029
2030 if (lprbbi->fMask & RBBIM_CHILDSIZE) {
2031 lprbbi->cxMinChild = lpBand->cxMinChild;
2032 lprbbi->cyMinChild = lpBand->cyMinChild;
2033 if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2034 lprbbi->cyChild = lpBand->cyChild;
2035 lprbbi->cyMaxChild = lpBand->cyMaxChild;
2036 lprbbi->cyIntegral = lpBand->cyIntegral;
2037 }
2038 }
2039
2040 if (lprbbi->fMask & RBBIM_SIZE)
2041 lprbbi->cx = lpBand->cx;
2042
2043 if (lprbbi->fMask & RBBIM_BACKGROUND)
2044 lprbbi->hbmBack = lpBand->hbmBack;
2045
2046 if (lprbbi->fMask & RBBIM_ID)
2047 lprbbi->wID = lpBand->wID;
2048
2049 /* check for additional data */
2050 if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2051 if (lprbbi->fMask & RBBIM_IDEALSIZE)
2052 lprbbi->cxIdeal = lpBand->cxIdeal;
2053
2054 if (lprbbi->fMask & RBBIM_LPARAM)
2055 lprbbi->lParam = lpBand->lParam;
2056
2057 if (lprbbi->fMask & RBBIM_HEADERSIZE)
2058 lprbbi->cxHeader = lpBand->cxHeader;
2059 }
2060
2061 REBAR_DumpBandInfo (lprbbi);
2062
2063 return TRUE;
2064}
2065
2066
2067static LRESULT
2068REBAR_GetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2069{
2070 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2071 LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
2072 REBAR_BAND *lpBand;
2073
2074 if (lprbbi == NULL)
2075 return FALSE;
2076 if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
2077 return FALSE;
2078 if ((UINT)wParam >= infoPtr->uNumBands)
2079 return FALSE;
2080
2081 TRACE("index %u\n", (UINT)wParam);
2082
2083 /* copy band information */
2084 lpBand = &infoPtr->bands[(UINT)wParam];
2085
2086 if (lprbbi->fMask & RBBIM_STYLE)
2087 lprbbi->fStyle = lpBand->fStyle;
2088
2089 if (lprbbi->fMask & RBBIM_COLORS) {
2090 lprbbi->clrFore = lpBand->clrFore;
2091 lprbbi->clrBack = lpBand->clrBack;
2092 if (lprbbi->clrBack == CLR_NONE)
2093 lprbbi->clrBack = GetSysColor (COLOR_BTNFACE);
2094 }
2095
2096 if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2097 if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
2098 lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch);
2099 else
2100 *lprbbi->lpText = 0;
2101 }
2102
2103 if (lprbbi->fMask & RBBIM_IMAGE) {
2104 if (lpBand->fMask & RBBIM_IMAGE)
2105 lprbbi->iImage = lpBand->iImage;
2106 else
2107 lprbbi->iImage = -1;
2108 }
2109
2110 if (lprbbi->fMask & RBBIM_CHILD)
2111 lprbbi->hwndChild = lpBand->hwndChild;
2112
2113 if (lprbbi->fMask & RBBIM_CHILDSIZE) {
2114 lprbbi->cxMinChild = lpBand->cxMinChild;
2115 lprbbi->cyMinChild = lpBand->cyMinChild;
2116 if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
2117 lprbbi->cyChild = lpBand->cyChild;
2118 lprbbi->cyMaxChild = lpBand->cyMaxChild;
2119 lprbbi->cyIntegral = lpBand->cyIntegral;
2120 }
2121 }
2122
2123 if (lprbbi->fMask & RBBIM_SIZE)
2124 lprbbi->cx = lpBand->cx;
2125
2126 if (lprbbi->fMask & RBBIM_BACKGROUND)
2127 lprbbi->hbmBack = lpBand->hbmBack;
2128
2129 if (lprbbi->fMask & RBBIM_ID)
2130 lprbbi->wID = lpBand->wID;
2131
2132 /* check for additional data */
2133 if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
2134 if (lprbbi->fMask & RBBIM_IDEALSIZE)
2135 lprbbi->cxIdeal = lpBand->cxIdeal;
2136
2137 if (lprbbi->fMask & RBBIM_LPARAM)
2138 lprbbi->lParam = lpBand->lParam;
2139
2140 if (lprbbi->fMask & RBBIM_HEADERSIZE)
2141 lprbbi->cxHeader = lpBand->cxHeader;
2142 }
2143
2144 REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
2145
2146 return TRUE;
2147}
2148
2149
2150static LRESULT
2151REBAR_GetBarHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
2152{
2153 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2154 INT nHeight;
2155 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2156
2157 nHeight = (dwStyle & CCS_VERT) ? infoPtr->calcSize.cx : infoPtr->calcSize.cy;
2158
2159 TRACE("height = %d\n", nHeight);
2160
2161 return nHeight;
2162}
2163
2164
2165static LRESULT
2166REBAR_GetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
2167{
2168 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2169 LPREBARINFO lpInfo = (LPREBARINFO)lParam;
2170
2171 if (lpInfo == NULL)
2172 return FALSE;
2173
2174 if (lpInfo->cbSize < sizeof (REBARINFO))
2175 return FALSE;
2176
2177 TRACE("getting bar info!\n");
2178
2179 if (infoPtr->himl) {
2180 lpInfo->himl = infoPtr->himl;
2181 lpInfo->fMask |= RBIM_IMAGELIST;
2182 }
2183
2184 return TRUE;
2185}
2186
2187
2188inline static LRESULT
2189REBAR_GetBkColor (HWND hwnd)
2190{
2191 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2192 COLORREF clr = infoPtr->clrBk;
2193
2194 if (clr == CLR_NONE)
2195 clr = GetSysColor (COLOR_BTNFACE);
2196
2197 TRACE("background color 0x%06lx!\n", clr);
2198
2199 return clr;
2200}
2201
2202
2203/* << REBAR_GetColorScheme >> */
2204/* << REBAR_GetDropTarget >> */
2205
2206
2207static LRESULT
2208REBAR_GetPalette (HWND hwnd, WPARAM wParam, LPARAM lParam)
2209{
2210 FIXME("empty stub!\n");
2211
2212 return 0;
2213}
2214
2215
2216static LRESULT
2217REBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2218{
2219 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2220 INT iBand = (INT)wParam;
2221 LPRECT lprc = (LPRECT)lParam;
2222 REBAR_BAND *lpBand;
2223
2224 if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
2225 return FALSE;
2226 if (!lprc)
2227 return FALSE;
2228
2229 lpBand = &infoPtr->bands[iBand];
2230 CopyRect (lprc, &lpBand->rcBand);
2231
2232 TRACE("band %d, (%d,%d)-(%d,%d)\n", iBand,
2233 lprc->left, lprc->top, lprc->right, lprc->bottom);
2234
2235 return TRUE;
2236}
2237
2238
2239inline static LRESULT
2240REBAR_GetRowCount (HWND hwnd)
2241{
2242 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2243
2244 TRACE("%u\n", infoPtr->uNumRows);
2245
2246 return infoPtr->uNumRows;
2247}
2248
2249
2250static LRESULT
2251REBAR_GetRowHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
2252{
2253 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2254 INT iRow = (INT)wParam;
2255 int ret = 0;
2256 int i, j = 0;
2257 REBAR_BAND *lpBand;
2258 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2259
2260 for (i=0; i<infoPtr->uNumBands; i++) {
2261 lpBand = &infoPtr->bands[i];
2262 if (HIDDENBAND(lpBand)) continue;
2263 if (lpBand->iRow != iRow) continue;
2264 if (dwStyle & CCS_VERT)
2265 j = lpBand->rcBand.right - lpBand->rcBand.left;
2266 else
2267 j = lpBand->rcBand.bottom - lpBand->rcBand.top;
2268 if (j > ret) ret = j;
2269 }
2270
2271 TRACE("row %d, height %d\n", iRow, ret);
2272
2273 return ret;
2274}
2275
2276
2277inline static LRESULT
2278REBAR_GetTextColor (HWND hwnd)
2279{
2280 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2281
2282 TRACE("text color 0x%06lx!\n", infoPtr->clrText);
2283
2284 return infoPtr->clrText;
2285}
2286
2287
2288inline static LRESULT
2289REBAR_GetToolTips (HWND hwnd)
2290{
2291 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2292 return infoPtr->hwndToolTip;
2293}
2294
2295
2296inline static LRESULT
2297REBAR_GetUnicodeFormat (HWND hwnd)
2298{
2299 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2300 return infoPtr->bUnicode;
2301}
2302
2303
2304inline static LRESULT
2305REBAR_GetVersion (HWND hwnd)
2306{
2307 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2308 TRACE("version %d\n", infoPtr->iVersion);
2309 return infoPtr->iVersion;
2310}
2311
2312
2313static LRESULT
2314REBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2315{
2316 /* REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
2317 LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam;
2318
2319 if (!lprbht)
2320 return -1;
2321
2322 REBAR_InternalHitTest (hwnd, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
2323
2324 return lprbht->iBand;
2325}
2326
2327
2328static LRESULT
2329REBAR_IdToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2330{
2331 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2332 UINT i;
2333
2334 if (infoPtr == NULL)
2335 return -1;
2336
2337 if (infoPtr->uNumBands < 1)
2338 return -1;
2339
2340 for (i = 0; i < infoPtr->uNumBands; i++) {
2341 if (infoPtr->bands[i].wID == (UINT)wParam) {
2342 TRACE("id %u is band %u found!\n", (UINT)wParam, i);
2343 return i;
2344 }
2345 }
2346
2347 TRACE("id %u is not found\n", (UINT)wParam);
2348 return -1;
2349}
2350
2351
2352static LRESULT
2353REBAR_InsertBandA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2354{
2355 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2356 LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
2357 UINT uIndex = (UINT)wParam;
2358 REBAR_BAND *lpBand;
2359
2360 if (infoPtr == NULL)
2361 return FALSE;
2362 if (lprbbi == NULL)
2363 return FALSE;
2364 if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
2365 return FALSE;
2366
2367 /* trace the index as signed to see the -1 */
2368 TRACE("insert band at %d!\n", (INT)uIndex);
2369 REBAR_DumpBandInfo (lprbbi);
2370
2371 if (infoPtr->uNumBands == 0) {
2372 infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
2373 uIndex = 0;
2374 }
2375 else {
2376 REBAR_BAND *oldBands = infoPtr->bands;
2377 infoPtr->bands =
2378 (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
2379 if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
2380 uIndex = infoPtr->uNumBands;
2381
2382 /* pre insert copy */
2383 if (uIndex > 0) {
2384 memcpy (&infoPtr->bands[0], &oldBands[0],
2385 uIndex * sizeof(REBAR_BAND));
2386 }
2387
2388 /* post copy */
2389 if (uIndex < infoPtr->uNumBands - 1) {
2390 memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
2391 (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
2392 }
2393
2394 COMCTL32_Free (oldBands);
2395 }
2396
2397 infoPtr->uNumBands++;
2398
2399 TRACE("index %u!\n", uIndex);
2400
2401 /* initialize band (infoPtr->bands[uIndex])*/
2402 lpBand = &infoPtr->bands[uIndex];
2403 lpBand->fMask = 0;
2404 lpBand->fStatus = 0;
2405 lpBand->clrFore = infoPtr->clrText;
2406 lpBand->clrBack = infoPtr->clrBk;
2407 lpBand->hwndChild = 0;
2408 lpBand->hwndPrevParent = 0;
2409
2410 REBAR_CommonSetupBand (hwnd, lprbbi, lpBand);
2411 lpBand->lpText = NULL;
2412 if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2413 INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
2414 if (len > 1) {
2415 lpBand->lpText = (LPWSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
2416 MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
2417 }
2418 }
2419
2420 REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2421 /* On insert of second band, revalidate band 1 to possible add gripper */
2422 if (infoPtr->uNumBands == 2)
2423 REBAR_ValidateBand (hwnd, infoPtr, &infoPtr->bands[0]);
2424
2425 REBAR_DumpBand (hwnd);
2426
2427 REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2428 REBAR_ForceResize (hwnd);
2429 REBAR_MoveChildWindows (hwnd);
2430
2431 return TRUE;
2432}
2433
2434
2435static LRESULT
2436REBAR_InsertBandW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2437{
2438 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2439 LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
2440 UINT uIndex = (UINT)wParam;
2441 REBAR_BAND *lpBand;
2442
2443 if (infoPtr == NULL)
2444 return FALSE;
2445 if (lprbbi == NULL)
2446 return FALSE;
2447 if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
2448 return FALSE;
2449
2450 /* trace the index as signed to see the -1 */
2451 TRACE("insert band at %d!\n", (INT)uIndex);
2452 REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
2453
2454 if (infoPtr->uNumBands == 0) {
2455 infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
2456 uIndex = 0;
2457 }
2458 else {
2459 REBAR_BAND *oldBands = infoPtr->bands;
2460 infoPtr->bands =
2461 (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
2462 if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
2463 uIndex = infoPtr->uNumBands;
2464
2465 /* pre insert copy */
2466 if (uIndex > 0) {
2467 memcpy (&infoPtr->bands[0], &oldBands[0],
2468 uIndex * sizeof(REBAR_BAND));
2469 }
2470
2471 /* post copy */
2472 if (uIndex < infoPtr->uNumBands - 1) {
2473 memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
2474 (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
2475 }
2476
2477 COMCTL32_Free (oldBands);
2478 }
2479
2480 infoPtr->uNumBands++;
2481
2482 TRACE("index %u!\n", uIndex);
2483
2484 /* initialize band (infoPtr->bands[uIndex])*/
2485 lpBand = &infoPtr->bands[uIndex];
2486 lpBand->fMask = 0;
2487 lpBand->fStatus = 0;
2488 lpBand->clrFore = infoPtr->clrText;
2489 lpBand->clrBack = infoPtr->clrBk;
2490 lpBand->hwndChild = 0;
2491 lpBand->hwndPrevParent = 0;
2492
2493 REBAR_CommonSetupBand (hwnd, (LPREBARBANDINFOA)lprbbi, lpBand);
2494 lpBand->lpText = NULL;
2495 if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2496 INT len = lstrlenW (lprbbi->lpText);
2497 if (len > 0) {
2498 lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
2499 strcpyW (lpBand->lpText, lprbbi->lpText);
2500 }
2501 }
2502
2503 REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2504 /* On insert of second band, revalidate band 1 to possible add gripper */
2505 if (infoPtr->uNumBands == 2)
2506 REBAR_ValidateBand (hwnd, infoPtr, &infoPtr->bands[0]);
2507
2508 REBAR_DumpBand (hwnd);
2509
2510 REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2511 REBAR_ForceResize (hwnd);
2512 REBAR_MoveChildWindows (hwnd);
2513
2514 return TRUE;
2515}
2516
2517
2518static LRESULT
2519REBAR_MaximizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2520{
2521/* REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
2522
2523 FIXME("(uBand = %u fIdeal = %s) stub\n",
2524 (UINT)wParam, lParam ? "TRUE" : "FALSE");
2525
2526
2527 return 0;
2528}
2529
2530
2531static LRESULT
2532REBAR_MinimizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2533{
2534/* REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
2535
2536 FIXME("(uBand = %u) stub\n", (UINT)wParam);
2537
2538
2539 return 0;
2540}
2541
2542
2543static LRESULT
2544REBAR_MoveBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2545{
2546/* REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
2547
2548 FIXME("(iFrom = %u iTof = %u) stub\n",
2549 (UINT)wParam, (UINT)lParam);
2550
2551
2552 return FALSE;
2553}
2554
2555
2556static LRESULT
2557REBAR_SetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2558{
2559 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2560 LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
2561 REBAR_BAND *lpBand;
2562
2563 if (lprbbi == NULL)
2564 return FALSE;
2565 if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
2566 return FALSE;
2567 if ((UINT)wParam >= infoPtr->uNumBands)
2568 return FALSE;
2569
2570 TRACE("index %u\n", (UINT)wParam);
2571 REBAR_DumpBandInfo (lprbbi);
2572
2573 /* set band information */
2574 lpBand = &infoPtr->bands[(UINT)wParam];
2575
2576 REBAR_CommonSetupBand (hwnd, lprbbi, lpBand);
2577 if (lprbbi->fMask & RBBIM_TEXT) {
2578 if (lpBand->lpText) {
2579 COMCTL32_Free (lpBand->lpText);
2580 lpBand->lpText = NULL;
2581 }
2582 if (lprbbi->lpText) {
2583 INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
2584 lpBand->lpText = (LPWSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
2585 MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
2586 }
2587 }
2588
2589 REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2590
2591 REBAR_DumpBand (hwnd);
2592
2593 if (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) {
2594 REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2595 REBAR_ForceResize (hwnd);
2596 REBAR_MoveChildWindows (hwnd);
2597 }
2598
2599 return TRUE;
2600}
2601
2602
2603static LRESULT
2604REBAR_SetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2605{
2606 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2607 LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
2608 REBAR_BAND *lpBand;
2609
2610 if (lprbbi == NULL)
2611 return FALSE;
2612 if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
2613 return FALSE;
2614 if ((UINT)wParam >= infoPtr->uNumBands)
2615 return FALSE;
2616
2617 TRACE("index %u\n", (UINT)wParam);
2618 REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
2619
2620 /* set band information */
2621 lpBand = &infoPtr->bands[(UINT)wParam];
2622
2623 REBAR_CommonSetupBand (hwnd, (LPREBARBANDINFOA)lprbbi, lpBand);
2624 if (lprbbi->fMask & RBBIM_TEXT) {
2625 if (lpBand->lpText) {
2626 COMCTL32_Free (lpBand->lpText);
2627 lpBand->lpText = NULL;
2628 }
2629 if (lprbbi->lpText) {
2630 INT len = lstrlenW (lprbbi->lpText);
2631 lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
2632 strcpyW (lpBand->lpText, lprbbi->lpText);
2633 }
2634 }
2635
2636 REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2637
2638 REBAR_DumpBand (hwnd);
2639
2640 if (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) {
2641 REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2642 REBAR_ForceResize (hwnd);
2643 REBAR_MoveChildWindows (hwnd);
2644 }
2645
2646 return TRUE;
2647}
2648
2649
2650static LRESULT
2651REBAR_SetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
2652{
2653 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2654 LPREBARINFO lpInfo = (LPREBARINFO)lParam;
2655 REBAR_BAND *lpBand;
2656 UINT i;
2657
2658 if (lpInfo == NULL)
2659 return FALSE;
2660
2661 if (lpInfo->cbSize < sizeof (REBARINFO))
2662 return FALSE;
2663
2664 TRACE("setting bar info!\n");
2665
2666 if (lpInfo->fMask & RBIM_IMAGELIST) {
2667 infoPtr->himl = lpInfo->himl;
2668 if (infoPtr->himl) {
2669 INT cx, cy;
2670 ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
2671 infoPtr->imageSize.cx = cx;
2672 infoPtr->imageSize.cy = cy;
2673 }
2674 else {
2675 infoPtr->imageSize.cx = 0;
2676 infoPtr->imageSize.cy = 0;
2677 }
2678 TRACE("new image cx=%ld, cy=%ld\n", infoPtr->imageSize.cx,
2679 infoPtr->imageSize.cy);
2680 }
2681
2682 /* revalidate all bands to reset flags for images in headers of bands */
2683 for (i=0; i<infoPtr->uNumBands; i++) {
2684 lpBand = &infoPtr->bands[i];
2685 REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2686 }
2687
2688 return TRUE;
2689}
2690
2691
2692static LRESULT
2693REBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2694{
2695 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2696 COLORREF clrTemp;
2697
2698 clrTemp = infoPtr->clrBk;
2699 infoPtr->clrBk = (COLORREF)lParam;
2700
2701 TRACE("background color 0x%06lx!\n", infoPtr->clrBk);
2702
2703 return clrTemp;
2704}
2705
2706
2707/* << REBAR_SetColorScheme >> */
2708/* << REBAR_SetPalette >> */
2709
2710
2711static LRESULT
2712REBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2713{
2714 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2715 HWND hwndTemp = infoPtr->hwndNotify;
2716
2717 infoPtr->hwndNotify = (HWND)wParam;
2718
2719 return (LRESULT)hwndTemp;
2720}
2721
2722
2723static LRESULT
2724REBAR_SetTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2725{
2726 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2727 COLORREF clrTemp;
2728
2729 clrTemp = infoPtr->clrText;
2730 infoPtr->clrText = (COLORREF)lParam;
2731
2732 TRACE("text color 0x%06lx!\n", infoPtr->clrText);
2733
2734 return clrTemp;
2735}
2736
2737
2738/* << REBAR_SetTooltips >> */
2739
2740
2741inline static LRESULT
2742REBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
2743{
2744 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2745 BOOL bTemp = infoPtr->bUnicode;
2746 infoPtr->bUnicode = (BOOL)wParam;
2747 return bTemp;
2748}
2749
2750
2751static LRESULT
2752REBAR_SetVersion (HWND hwnd, INT iVersion)
2753{
2754 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2755 INT iOldVersion = infoPtr->iVersion;
2756
2757 if (iVersion > COMCTL32_VERSION)
2758 return -1;
2759
2760 infoPtr->iVersion = iVersion;
2761
2762 TRACE("new version %d\n", iVersion);
2763
2764 return iOldVersion;
2765}
2766
2767
2768static LRESULT
2769REBAR_ShowBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2770{
2771 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2772 REBAR_BAND *lpBand;
2773
2774 if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands))
2775 return FALSE;
2776
2777 lpBand = &infoPtr->bands[(INT)wParam];
2778
2779 if ((BOOL)lParam) {
2780 TRACE("show band %d\n", (INT)wParam);
2781 lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
2782 if (IsWindow (lpBand->hwndChild))
2783 ShowWindow (lpBand->hwndChild, SW_SHOW);
2784 }
2785 else {
2786 TRACE("hide band %d\n", (INT)wParam);
2787 lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
2788 if (IsWindow (lpBand->hwndChild))
2789 ShowWindow (lpBand->hwndChild, SW_HIDE);
2790 }
2791
2792 REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2793 REBAR_ForceResize (hwnd);
2794 REBAR_MoveChildWindows (hwnd);
2795
2796 return TRUE;
2797}
2798
2799
2800static LRESULT
2801REBAR_SizeToRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2802{
2803 LPRECT lpRect = (LPRECT)lParam;
2804 RECT t1;
2805
2806 if (lpRect == NULL)
2807 return FALSE;
2808
2809 TRACE("[%d %d %d %d]\n",
2810 lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
2811
2812 /* what is going on???? */
2813 GetWindowRect(hwnd, &t1);
2814 TRACE("window rect [%d %d %d %d]\n",
2815 t1.left, t1.top, t1.right, t1.bottom);
2816 GetClientRect(hwnd, &t1);
2817 TRACE("client rect [%d %d %d %d]\n",
2818 t1.left, t1.top, t1.right, t1.bottom);
2819
2820 REBAR_Layout (hwnd, lpRect, TRUE, FALSE);
2821 REBAR_ForceResize (hwnd);
2822 REBAR_MoveChildWindows (hwnd);
2823 return TRUE;
2824}
2825
2826
2827
2828static LRESULT
2829REBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
2830{
2831 REBAR_INFO *infoPtr;
2832
2833 /* allocate memory for info structure */
2834#ifdef __WIN32OS2__
2835 infoPtr = (REBAR_INFO*)initControl(hwnd,sizeof(REBAR_INFO));
2836#else
2837 infoPtr = (REBAR_INFO *)COMCTL32_Alloc (sizeof(REBAR_INFO));
2838#endif
2839 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
2840
2841 /* initialize info structure - initial values are 0 */
2842 infoPtr->clrBk = CLR_NONE;
2843 infoPtr->clrText = GetSysColor (COLOR_BTNTEXT);
2844 infoPtr->ihitBand = -1;
2845
2846 infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
2847 infoPtr->hcurHorz = LoadCursorA (0, IDC_SIZEWEA);
2848 infoPtr->hcurVert = LoadCursorA (0, IDC_SIZENSA);
2849 infoPtr->hcurDrag = LoadCursorA (0, IDC_SIZEA);
2850
2851 infoPtr->bUnicode = IsWindowUnicode (hwnd);
2852
2853 if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_AUTOSIZE)
2854 FIXME("style RBS_AUTOSIZE set!\n");
2855
2856#if 0
2857 SendMessageA (hwnd, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
2858#endif
2859
2860 TRACE("created!\n");
2861 return 0;
2862}
2863
2864
2865static LRESULT
2866REBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
2867{
2868 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2869 REBAR_BAND *lpBand;
2870 INT i;
2871
2872
2873 /* free rebar bands */
2874 if ((infoPtr->uNumBands > 0) && infoPtr->bands) {
2875 /* clean up each band */
2876 for (i = 0; i < infoPtr->uNumBands; i++) {
2877 lpBand = &infoPtr->bands[i];
2878
2879 /* delete text strings */
2880 if (lpBand->lpText) {
2881 COMCTL32_Free (lpBand->lpText);
2882 lpBand->lpText = NULL;
2883 }
2884 /* destroy child window */
2885 DestroyWindow (lpBand->hwndChild);
2886 }
2887
2888 /* free band array */
2889 COMCTL32_Free (infoPtr->bands);
2890 infoPtr->bands = NULL;
2891 }
2892
2893 DeleteObject (infoPtr->hcurArrow);
2894 DeleteObject (infoPtr->hcurHorz);
2895 DeleteObject (infoPtr->hcurVert);
2896 DeleteObject (infoPtr->hcurDrag);
2897
2898 /* free rebar info data */
2899 COMCTL32_Free (infoPtr);
2900 SetWindowLongA (hwnd, 0, 0);
2901 TRACE("destroyed!\n");
2902 return 0;
2903}
2904
2905
2906static LRESULT
2907REBAR_EraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
2908{
2909 RECT cliprect;
2910
2911 if (GetClipBox ( (HDC)wParam, &cliprect))
2912 return REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &cliprect);
2913 return 0;
2914}
2915
2916
2917static LRESULT
2918REBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2919{
2920 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2921
2922 return (LRESULT)infoPtr->hFont;
2923}
2924
2925
2926static LRESULT
2927REBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
2928{
2929 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2930 REBAR_BAND *lpBand;
2931 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2932
2933 /* If InternalHitTest did not find a hit on the Gripper, */
2934 /* then ignore the button click. */
2935 if (infoPtr->ihitBand == -1) return 0;
2936
2937 SetCapture (hwnd);
2938
2939 /* save off the LOWORD and HIWORD of lParam as initial x,y */
2940 lpBand = &infoPtr->bands[infoPtr->ihitBand];
2941 infoPtr->dragStart = MAKEPOINTS(lParam);
2942 infoPtr->dragNow = infoPtr->dragStart;
2943 if (dwStyle & CCS_VERT)
2944 infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.top+REBAR_PRE_GRIPPER);
2945 else
2946 infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left+REBAR_PRE_GRIPPER);
2947
2948 return 0;
2949}
2950
2951
2952static LRESULT
2953REBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
2954{
2955 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2956 NMHDR layout;
2957 RECT rect;
2958
2959 /* If InternalHitTest did not find a hit on the Gripper, */
2960 /* then ignore the button click. */
2961 if (infoPtr->ihitBand == -1) return 0;
2962
2963 infoPtr->dragStart.x = 0;
2964 infoPtr->dragStart.y = 0;
2965 infoPtr->dragNow = infoPtr->dragStart;
2966 infoPtr->ihitBand = -1;
2967
2968 ReleaseCapture ();
2969
2970 if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
2971 REBAR_Notify(hwnd, (NMHDR *) &layout, infoPtr, RBN_LAYOUTCHANGED);
2972 REBAR_Notify_NMREBAR (hwnd, infoPtr, -1, RBN_ENDDRAG);
2973 infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
2974 }
2975
2976 GetClientRect(hwnd, &rect);
2977 InvalidateRect(hwnd, NULL, TRUE);
2978
2979 return 0;
2980}
2981
2982
2983static LRESULT
2984REBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
2985{
2986 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2987 REBAR_BAND *band1, *band2;
2988 POINTS ptsmove;
2989 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2990
2991 /* Validate entry as hit on Gripper has occured */
2992 if (GetCapture() != hwnd) return 0;
2993 if (infoPtr->ihitBand == -1) return 0;
2994
2995 ptsmove = MAKEPOINTS(lParam);
2996
2997 /* if mouse did not move much, exit */
2998 if ((abs(ptsmove.x - infoPtr->dragNow.x) <= mindragx) &&
2999 (abs(ptsmove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
3000
3001 band1 = &infoPtr->bands[infoPtr->ihitBand-1];
3002 band2 = &infoPtr->bands[infoPtr->ihitBand];
3003
3004 /* Test for valid drag case - must not be first band in row */
3005 if (dwStyle & CCS_VERT) {
3006 if ((ptsmove.x < band2->rcBand.left) ||
3007 (ptsmove.x > band2->rcBand.right) ||
3008 ((infoPtr->ihitBand > 0) && (band1->iRow != band2->iRow))) {
3009 FIXME("Cannot drag to other rows yet!!\n");
3010 }
3011 else {
3012 REBAR_HandleLRDrag (hwnd, infoPtr, &ptsmove, dwStyle);
3013 }
3014 }
3015 else {
3016 if ((ptsmove.y < band2->rcBand.top) ||
3017 (ptsmove.y > band2->rcBand.bottom) ||
3018 ((infoPtr->ihitBand > 0) && (band1->iRow != band2->iRow))) {
3019 FIXME("Cannot drag to other rows yet!!\n");
3020 }
3021 else {
3022 REBAR_HandleLRDrag (hwnd, infoPtr, &ptsmove, dwStyle);
3023 }
3024 }
3025 return 0;
3026}
3027
3028
3029inline static LRESULT
3030REBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3031{
3032 if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
3033 ((LPRECT)lParam)->left += GetSystemMetrics(SM_CXEDGE);
3034 ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
3035 ((LPRECT)lParam)->right -= GetSystemMetrics(SM_CXEDGE);
3036 ((LPRECT)lParam)->bottom -= GetSystemMetrics(SM_CYEDGE);
3037 }
3038
3039 return 0;
3040}
3041
3042
3043static LRESULT
3044REBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3045{
3046 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3047 RECT rcWindow;
3048 HDC hdc;
3049
3050 if (dwStyle & WS_MINIMIZE)
3051 return 0; /* Nothing to do */
3052
3053 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
3054
3055 if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW )))
3056 return 0;
3057
3058 if (dwStyle & WS_BORDER) {
3059 GetWindowRect (hwnd, &rcWindow);
3060 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3061 DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
3062 }
3063
3064 ReleaseDC( hwnd, hdc );
3065
3066 return 0;
3067}
3068
3069
3070static LRESULT
3071REBAR_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
3072{
3073 HDC hdc;
3074 PAINTSTRUCT ps;
3075
3076 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
3077
3078 TRACE("painting (%d,%d)-(%d,%d)\n",
3079 ps.rcPaint.left, ps.rcPaint.top,
3080 ps.rcPaint.right, ps.rcPaint.bottom);
3081
3082 if (ps.fErase) {
3083 /* Erase area of paint if requested */
3084 REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &ps.rcPaint);
3085 }
3086
3087 REBAR_Refresh (hwnd, hdc);
3088 if (!wParam)
3089 EndPaint (hwnd, &ps);
3090 return 0;
3091}
3092
3093
3094static LRESULT
3095REBAR_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3096{
3097 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
3098 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3099 POINT pt;
3100 UINT flags;
3101
3102 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
3103
3104 GetCursorPos (&pt);
3105 ScreenToClient (hwnd, &pt);
3106
3107 REBAR_InternalHitTest (hwnd, &pt, &flags, NULL);
3108
3109 if (flags == RBHT_GRABBER) {
3110 if ((dwStyle & CCS_VERT) &&
3111 !(dwStyle & RBS_VERTICALGRIPPER))
3112 SetCursor (infoPtr->hcurVert);
3113 else
3114 SetCursor (infoPtr->hcurHorz);
3115 }
3116 else if (flags != RBHT_CLIENT)
3117 SetCursor (infoPtr->hcurArrow);
3118
3119 return 0;
3120}
3121
3122
3123static LRESULT
3124REBAR_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3125{
3126 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
3127 RECT rcClient;
3128 REBAR_BAND *lpBand;
3129 UINT i;
3130
3131 infoPtr->hFont = (HFONT)wParam;
3132
3133 /* revalidate all bands to change sizes of text in headers of bands */
3134 for (i=0; i<infoPtr->uNumBands; i++) {
3135 lpBand = &infoPtr->bands[i];
3136 REBAR_ValidateBand (hwnd, infoPtr, lpBand);
3137 }
3138
3139
3140 if (lParam) {
3141 GetClientRect (hwnd, &rcClient);
3142 REBAR_Layout (hwnd, &rcClient, FALSE, TRUE);
3143 REBAR_ForceResize (hwnd);
3144 REBAR_MoveChildWindows (hwnd);
3145 }
3146
3147 return 0;
3148}
3149
3150
3151static LRESULT
3152REBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
3153{
3154 REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
3155 RECT rcClient;
3156
3157 /* auto resize deadlock check */
3158 if (infoPtr->fStatus & AUTO_RESIZE) {
3159 infoPtr->fStatus &= ~AUTO_RESIZE;
3160 TRACE("AUTO_RESIZE was set, reset, fStatus=%08x\n",
3161 infoPtr->fStatus);
3162 return 0;
3163 }
3164
3165 GetClientRect (hwnd, &rcClient);
3166 if ((lParam == 0) && (rcClient.right == 0) && (rcClient.bottom == 0)) {
3167 /* native control seems to do this */
3168 GetClientRect (GetParent(hwnd), &rcClient);
3169 TRACE("sizing rebar, message and client zero, parent client (%d,%d)\n",
3170 rcClient.right, rcClient.bottom);
3171 }
3172 else {
3173 TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%d,%d)\n",
3174 infoPtr->calcSize.cx, infoPtr->calcSize.cy,
3175 LOWORD(lParam), HIWORD(lParam),
3176 rcClient.right, rcClient.bottom);
3177 }
3178
3179 REBAR_Layout (hwnd, &rcClient, TRUE, TRUE);
3180 REBAR_ForceResize (hwnd);
3181 infoPtr->fStatus &= ~AUTO_RESIZE;
3182 REBAR_MoveChildWindows (hwnd);
3183
3184 return 0;
3185}
3186
3187
3188static LRESULT WINAPI
3189REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3190{
3191 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
3192 if (!REBAR_GetInfoPtr (hwnd) && (uMsg != WM_CREATE))
3193 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3194 switch (uMsg)
3195 {
3196/* case RB_BEGINDRAG: */
3197
3198 case RB_DELETEBAND:
3199 return REBAR_DeleteBand (hwnd, wParam, lParam);
3200
3201/* case RB_DRAGMOVE: */
3202/* case RB_ENDDRAG: */
3203
3204 case RB_GETBANDBORDERS:
3205 return REBAR_GetBandBorders (hwnd, wParam, lParam);
3206
3207 case RB_GETBANDCOUNT:
3208 return REBAR_GetBandCount (hwnd);
3209
3210 case RB_GETBANDINFO: /* obsoleted after IE3, but we have to
3211 support it anyway. */
3212 case RB_GETBANDINFOA:
3213 return REBAR_GetBandInfoA (hwnd, wParam, lParam);
3214
3215 case RB_GETBANDINFOW:
3216 return REBAR_GetBandInfoW (hwnd, wParam, lParam);
3217
3218 case RB_GETBARHEIGHT:
3219 return REBAR_GetBarHeight (hwnd, wParam, lParam);
3220
3221 case RB_GETBARINFO:
3222 return REBAR_GetBarInfo (hwnd, wParam, lParam);
3223
3224 case RB_GETBKCOLOR:
3225 return REBAR_GetBkColor (hwnd);
3226
3227/* case RB_GETCOLORSCHEME: */
3228/* case RB_GETDROPTARGET: */
3229
3230 case RB_GETPALETTE:
3231 return REBAR_GetPalette (hwnd, wParam, lParam);
3232
3233 case RB_GETRECT:
3234 return REBAR_GetRect (hwnd, wParam, lParam);
3235
3236 case RB_GETROWCOUNT:
3237 return REBAR_GetRowCount (hwnd);
3238
3239 case RB_GETROWHEIGHT:
3240 return REBAR_GetRowHeight (hwnd, wParam, lParam);
3241
3242 case RB_GETTEXTCOLOR:
3243 return REBAR_GetTextColor (hwnd);
3244
3245 case RB_GETTOOLTIPS:
3246 return REBAR_GetToolTips (hwnd);
3247
3248 case RB_GETUNICODEFORMAT:
3249 return REBAR_GetUnicodeFormat (hwnd);
3250
3251 case CCM_GETVERSION:
3252 return REBAR_GetVersion (hwnd);
3253
3254 case RB_HITTEST:
3255 return REBAR_HitTest (hwnd, wParam, lParam);
3256
3257 case RB_IDTOINDEX:
3258 return REBAR_IdToIndex (hwnd, wParam, lParam);
3259
3260 case RB_INSERTBANDA:
3261 return REBAR_InsertBandA (hwnd, wParam, lParam);
3262
3263 case RB_INSERTBANDW:
3264 return REBAR_InsertBandW (hwnd, wParam, lParam);
3265
3266 case RB_MAXIMIZEBAND:
3267 return REBAR_MaximizeBand (hwnd, wParam, lParam);
3268
3269 case RB_MINIMIZEBAND:
3270 return REBAR_MinimizeBand (hwnd, wParam, lParam);
3271
3272 case RB_MOVEBAND:
3273 return REBAR_MoveBand (hwnd, wParam, lParam);
3274
3275 case RB_SETBANDINFOA:
3276 return REBAR_SetBandInfoA (hwnd, wParam, lParam);
3277
3278 case RB_SETBANDINFOW:
3279 return REBAR_SetBandInfoW (hwnd, wParam, lParam);
3280
3281 case RB_SETBARINFO:
3282 return REBAR_SetBarInfo (hwnd, wParam, lParam);
3283
3284 case RB_SETBKCOLOR:
3285 return REBAR_SetBkColor (hwnd, wParam, lParam);
3286
3287/* case RB_SETCOLORSCHEME: */
3288/* case RB_SETPALETTE: */
3289/* return REBAR_GetPalette (hwnd, wParam, lParam); */
3290
3291 case RB_SETPARENT:
3292 return REBAR_SetParent (hwnd, wParam, lParam);
3293
3294 case RB_SETTEXTCOLOR:
3295 return REBAR_SetTextColor (hwnd, wParam, lParam);
3296
3297/* case RB_SETTOOLTIPS: */
3298
3299 case RB_SETUNICODEFORMAT:
3300 return REBAR_SetUnicodeFormat (hwnd, wParam);
3301
3302 case CCM_SETVERSION:
3303 return REBAR_SetVersion (hwnd, (INT)wParam);
3304
3305 case RB_SHOWBAND:
3306 return REBAR_ShowBand (hwnd, wParam, lParam);
3307
3308 case RB_SIZETORECT:
3309 return REBAR_SizeToRect (hwnd, wParam, lParam);
3310
3311
3312/* Messages passed to parent */
3313 case WM_COMMAND:
3314 case WM_DRAWITEM:
3315 case WM_NOTIFY:
3316 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
3317
3318
3319/* case WM_CHARTOITEM: supported according to ControlSpy */
3320
3321 case WM_CREATE:
3322 return REBAR_Create (hwnd, wParam, lParam);
3323
3324 case WM_DESTROY:
3325 return REBAR_Destroy (hwnd, wParam, lParam);
3326
3327 case WM_ERASEBKGND:
3328 return REBAR_EraseBkGnd (hwnd, wParam, lParam);
3329
3330 case WM_GETFONT:
3331 return REBAR_GetFont (hwnd, wParam, lParam);
3332
3333/* case WM_LBUTTONDBLCLK: supported according to ControlSpy */
3334
3335 case WM_LBUTTONDOWN:
3336 return REBAR_LButtonDown (hwnd, wParam, lParam);
3337
3338 case WM_LBUTTONUP:
3339 return REBAR_LButtonUp (hwnd, wParam, lParam);
3340
3341/* case WM_MEASUREITEM: supported according to ControlSpy */
3342
3343 case WM_MOUSEMOVE:
3344 return REBAR_MouseMove (hwnd, wParam, lParam);
3345
3346 case WM_NCCALCSIZE:
3347 return REBAR_NCCalcSize (hwnd, wParam, lParam);
3348
3349/* case WM_NCCREATE: supported according to ControlSpy */
3350/* case WM_NCHITTEST: supported according to ControlSpy */
3351
3352 case WM_NCPAINT:
3353 return REBAR_NCPaint (hwnd, wParam, lParam);
3354
3355/* case WM_NOTIFYFORMAT: supported according to ControlSpy */
3356
3357 case WM_PAINT:
3358 return REBAR_Paint (hwnd, wParam, lParam);
3359
3360/* case WM_PALETTECHANGED: supported according to ControlSpy */
3361/* case WM_PRINTCLIENT: supported according to ControlSpy */
3362/* case WM_QUERYNEWPALETTE:supported according to ControlSpy */
3363/* case WM_RBUTTONDOWN: supported according to ControlSpy */
3364/* case WM_RBUTTONUP: supported according to ControlSpy */
3365
3366 case WM_SETCURSOR:
3367 return REBAR_SetCursor (hwnd, wParam, lParam);
3368
3369 case WM_SETFONT:
3370 return REBAR_SetFont (hwnd, wParam, lParam);
3371
3372/* case WM_SETREDRAW: supported according to ControlSpy */
3373
3374 case WM_SIZE:
3375 return REBAR_Size (hwnd, wParam, lParam);
3376
3377/* case WM_STYLECHANGED: supported according to ControlSpy */
3378/* case WM_SYSCOLORCHANGE: supported according to ControlSpy */
3379/* case WM_VKEYTOITEM: supported according to ControlSpy */
3380/* case WM_WININICHANGE: */
3381
3382 default:
3383 if (uMsg >= WM_USER)
3384 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
3385 uMsg, wParam, lParam);
3386#ifdef __WIN32OS2__
3387 return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
3388#else
3389 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3390#endif
3391 }
3392 return 0;
3393}
3394
3395
3396VOID
3397REBAR_Register (void)
3398{
3399 WNDCLASSA wndClass;
3400
3401 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
3402 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
3403 wndClass.lpfnWndProc = (WNDPROC)REBAR_WindowProc;
3404 wndClass.cbClsExtra = 0;
3405 wndClass.cbWndExtra = sizeof(REBAR_INFO *);
3406 wndClass.hCursor = 0;
3407 wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
3408 wndClass.lpszClassName = REBARCLASSNAMEA;
3409
3410 RegisterClassA (&wndClass);
3411
3412 mindragx = GetSystemMetrics (SM_CXDRAG);
3413 mindragy = GetSystemMetrics (SM_CYDRAG);
3414
3415}
3416
3417
3418VOID
3419REBAR_Unregister (void)
3420{
3421 UnregisterClassA (REBARCLASSNAMEA, (HINSTANCE)NULL);
3422}
3423
Note: See TracBrowser for help on using the repository browser.