ReactOS  0.4.14-dev-583-g2a1ba2c
rebar.c
Go to the documentation of this file.
1 /*
2  * Rebar control
3  *
4  * Copyright 1998, 1999 Eric Kohl
5  * Copyright 2007, 2008 Mikolaj Zalewski
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * NOTES
22  *
23  * This code was audited for completeness against the documented features
24  * of Comctl32.dll version 6.0 on Oct. 19, 2004, by Robert Shearman.
25  *
26  * Unless otherwise noted, we believe this code to be complete, as per
27  * the specification mentioned above.
28  * If you discover missing features or bugs please note them below.
29  *
30  * TODO
31  * Styles:
32  * - RBS_DBLCLKTOGGLE
33  * - RBS_FIXEDORDER
34  * - RBS_REGISTERDROP
35  * - RBS_TOOLTIPS
36  * Messages:
37  * - RB_BEGINDRAG
38  * - RB_DRAGMOVE
39  * - RB_ENDDRAG
40  * - RB_GETBANDMARGINS
41  * - RB_GETCOLORSCHEME
42  * - RB_GETDROPTARGET
43  * - RB_GETPALETTE
44  * - RB_SETCOLORSCHEME
45  * - RB_SETPALETTE
46  * - RB_SETTOOLTIPS
47  * - WM_CHARTOITEM
48  * - WM_LBUTTONDBLCLK
49  * - WM_PALETTECHANGED
50  * - WM_QUERYNEWPALETTE
51  * - WM_RBUTTONDOWN
52  * - WM_RBUTTONUP
53  * - WM_VKEYTOITEM
54  * - WM_WININICHANGE
55  * Notifications:
56  * - NM_HCHITTEST
57  * - NM_RELEASEDCAPTURE
58  * - RBN_AUTOBREAK
59  * - RBN_GETOBJECT
60  * - RBN_MINMAX
61  * Band styles:
62  * - RBBS_FIXEDBMP
63  * Native uses (on each draw!!) SM_CYBORDER (or SM_CXBORDER for CCS_VERT)
64  * to set the size of the separator width (the value SEP_WIDTH_SIZE
65  * in here). Should be fixed!!
66  */
67 
68 /*
69  * Testing: set to 1 to make background brush *always* green
70  */
71 #define GLATESTING 0
72 
73 /*
74  * 3. REBAR_MoveChildWindows should have a loop because more than
75  * one pass (together with the RBN_CHILDSIZEs) is made on
76  * at least RB_INSERTBAND
77  */
78 
79 #include <assert.h>
80 #include <stdarg.h>
81 #include <stdlib.h>
82 #include <string.h>
83 
84 #include "windef.h"
85 #include "winbase.h"
86 #include "wingdi.h"
87 #include "wine/unicode.h"
88 #include "winuser.h"
89 #include "winnls.h"
90 #include "commctrl.h"
91 #include "comctl32.h"
92 #include "uxtheme.h"
93 #include "vssym32.h"
94 #include "wine/debug.h"
95 
97 
98 typedef struct
99 {
106  UINT cxMinChild; /* valid if _CHILDSIZE */
107  UINT cyMinChild; /* valid if _CHILDSIZE */
108  UINT cx; /* valid if _SIZE */
111  UINT cyChild; /* valid if _CHILDSIZE */
112  UINT cyMaxChild; /* valid if _CHILDSIZE */
113  UINT cyIntegral; /* valid if _CHILDSIZE */
117 
118  INT cxEffective; /* current cx for band */
119  UINT cyHeader; /* the height of the header */
120  UINT cxMinBand; /* minimum cx for band */
121  UINT cyMinBand; /* minimum cy for band */
122 
123  UINT cyRowSoFar; /* for RBS_VARHEIGHT - the height of the row if it would break on this band (set by _Layout) */
124  INT iRow; /* zero-based index of the row this band assigned to */
125  UINT fStatus; /* status flags, reset only by _Validate */
126  UINT fDraw; /* drawing flags, reset only by _Layout */
127  UINT uCDret; /* last return from NM_CUSTOMDRAW */
128  RECT rcBand; /* calculated band rectangle - coordinates swapped for CCS_VERT */
129  RECT rcGripper; /* calculated gripper rectangle */
130  RECT rcCapImage; /* calculated caption image rectangle */
131  RECT rcCapText; /* calculated caption text rectangle */
132  RECT rcChild; /* calculated child rectangle */
133  RECT rcChevron; /* calculated chevron rectangle */
134 
137 } REBAR_BAND;
138 
139 /* has a value of: 0, CCS_TOP, CCS_NOMOVEY, CCS_BOTTOM */
140 #define CCS_LAYOUT_MASK 0x3
141 
142 /* fStatus flags */
143 #define HAS_GRIPPER 0x00000001
144 #define HAS_IMAGE 0x00000002
145 #define HAS_TEXT 0x00000004
146 
147 /* fDraw flags */
148 #define DRAW_GRIPPER 0x00000001
149 #define DRAW_IMAGE 0x00000002
150 #define DRAW_TEXT 0x00000004
151 #define DRAW_CHEVRONHOT 0x00000040
152 #define DRAW_CHEVRONPUSHED 0x00000080
153 #define NTF_INVALIDATE 0x01000000
154 
155 typedef struct
156 {
157  COLORREF clrBk; /* background color */
158  COLORREF clrText; /* text color */
159  COLORREF clrBtnText; /* system color for BTNTEXT */
160  COLORREF clrBtnFace; /* system color for BTNFACE */
161  HIMAGELIST himl; /* handle to imagelist */
162  UINT uNumBands; /* # of bands in rebar (first=0, last=uNumBands-1 */
163  UINT uNumRows; /* # of rows of bands (first=1, last=uNumRows */
164  HWND hwndSelf; /* handle of REBAR window itself */
165  HWND hwndToolTip; /* handle to the tool tip control */
166  HWND hwndNotify; /* notification window (parent) */
168  HFONT hFont; /* handle to the rebar's font */
169  SIZE imageSize; /* image size (image list) */
170  DWORD dwStyle; /* window style */
171  DWORD orgStyle; /* original style (dwStyle may change) */
172  SIZE calcSize; /* calculated rebar size - coordinates swapped for CCS_VERT */
173  BOOL bUnicode; /* TRUE if parent wants notify in W format */
174  BOOL DoRedraw; /* TRUE to actually draw bands */
175  UINT fStatus; /* Status flags (see below) */
176  HCURSOR hcurArrow; /* handle to the arrow cursor */
177  HCURSOR hcurHorz; /* handle to the EW cursor */
178  HCURSOR hcurVert; /* handle to the NS cursor */
179  HCURSOR hcurDrag; /* handle to the drag cursor */
180  INT iVersion; /* version number */
181  POINT dragStart; /* x,y of button down */
182  POINT dragNow; /* x,y of this MouseMove */
183  INT iOldBand; /* last band that had the mouse cursor over it */
184  INT ihitoffset; /* offset of hotspot from gripper.left */
185  INT ichevronhotBand; /* last band that had a hot chevron */
186  INT iGrabbedBand;/* band number of band whose gripper was grabbed */
187 
188  HDPA bands; /* pointer to the array of rebar bands */
189 } REBAR_INFO;
190 
191 /* fStatus flags */
192 #define BEGIN_DRAG_ISSUED 0x00000001
193 #define SELF_RESIZE 0x00000002
194 #define BAND_NEEDS_REDRAW 0x00000020
195 
196 /* used by Windows to mark that the header size has been set by the user and shouldn't be changed */
197 #define RBBS_UNDOC_FIXEDHEADER 0x40000000
198 
199 /* ---- REBAR layout constants. Mostly determined by ---- */
200 /* ---- experiment on WIN 98. ---- */
201 
202 /* Width (or height) of separators between bands (either horz. or */
203 /* vert.). True only if RBS_BANDBORDERS is set */
204 #define SEP_WIDTH_SIZE 2
205 #define SEP_WIDTH ((infoPtr->dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
206 
207 /* Blank (background color) space between Gripper (if present) */
208 /* and next item (image, text, or window). Always present */
209 #define REBAR_ALWAYS_SPACE 4
210 
211 /* Blank (background color) space after Image (if present). */
212 #define REBAR_POST_IMAGE 2
213 
214 /* Blank (background color) space after Text (if present). */
215 #define REBAR_POST_TEXT 4
216 
217 /* Height of vertical gripper in a CCS_VERT rebar. */
218 #define GRIPPER_HEIGHT 16
219 
220 /* Blank (background color) space before Gripper (if present). */
221 #define REBAR_PRE_GRIPPER 2
222 
223 /* Width (of normal vertical gripper) or height (of horz. gripper) */
224 /* if present. */
225 #define GRIPPER_WIDTH 3
226 
227 /* Width of the chevron button if present */
228 #define CHEVRON_WIDTH 10
229 
230 /* the gap between the child and the next band */
231 #define REBAR_POST_CHILD 4
232 
233 /* Height of divider for Rebar if not disabled (CCS_NODIVIDER) */
234 /* either top or bottom */
235 #define REBAR_DIVIDER 2
236 
237 /* height of a rebar without a child */
238 #define REBAR_NO_CHILD_HEIGHT 4
239 
240 /* minimum vertical height of a normal bar */
241 /* or minimum width of a CCS_VERT bar - from experiment on Win2k */
242 #define REBAR_MINSIZE 23
243 
244 /* This is the increment that is used over the band height */
245 #define REBARSPACE(a) ((a->fStyle & RBBS_CHILDEDGE) ? 2*REBAR_DIVIDER : 0)
246 
247 /* ---- End of REBAR layout constants. ---- */
248 
249 #define RB_GETBANDINFO_OLD (WM_USER+5) /* obsoleted after IE3, but we have to support it anyway */
250 
251 /* The following define determines if a given band is hidden */
252 #define HIDDENBAND(a) (((a)->fStyle & RBBS_HIDDEN) || \
253  ((infoPtr->dwStyle & CCS_VERT) && \
254  ((a)->fStyle & RBBS_NOVERT)))
255 
256 #define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongPtrW (hwnd, 0))
257 
259 static void REBAR_AutoSize(REBAR_INFO *infoPtr, BOOL needsLayout);
260 
261 /* no index check here */
262 static inline REBAR_BAND* REBAR_GetBand(const REBAR_INFO *infoPtr, INT i)
263 {
264  assert(i >= 0 && i < infoPtr->uNumBands);
265  return DPA_GetPtr(infoPtr->bands, i);
266 }
267 
268 /* "constant values" retrieved when DLL was initialized */
269 /* FIXME we do this when the classes are registered. */
270 static UINT mindragx = 0;
271 static UINT mindragy = 0;
272 
273 static const char * const band_stylename[] = {
274  "RBBS_BREAK", /* 0001 */
275  "RBBS_FIXEDSIZE", /* 0002 */
276  "RBBS_CHILDEDGE", /* 0004 */
277  "RBBS_HIDDEN", /* 0008 */
278  "RBBS_NOVERT", /* 0010 */
279  "RBBS_FIXEDBMP", /* 0020 */
280  "RBBS_VARIABLEHEIGHT", /* 0040 */
281  "RBBS_GRIPPERALWAYS", /* 0080 */
282  "RBBS_NOGRIPPER", /* 0100 */
283  NULL };
284 
285 static const char * const band_maskname[] = {
286  "RBBIM_STYLE", /* 0x00000001 */
287  "RBBIM_COLORS", /* 0x00000002 */
288  "RBBIM_TEXT", /* 0x00000004 */
289  "RBBIM_IMAGE", /* 0x00000008 */
290  "RBBIM_CHILD", /* 0x00000010 */
291  "RBBIM_CHILDSIZE", /* 0x00000020 */
292  "RBBIM_SIZE", /* 0x00000040 */
293  "RBBIM_BACKGROUND", /* 0x00000080 */
294  "RBBIM_ID", /* 0x00000100 */
295  "RBBIM_IDEALSIZE", /* 0x00000200 */
296  "RBBIM_LPARAM", /* 0x00000400 */
297  "RBBIM_HEADERSIZE", /* 0x00000800 */
298  NULL };
299 
300 
301 static CHAR line[200];
302 
303 static const WCHAR themeClass[] = { 'R','e','b','a','r',0 };
304 
305 static CHAR *
307 {
308  INT i = 0;
309 
310  *line = 0;
311  while (band_stylename[i]) {
312  if (style & (1<<i)) {
313  if (*line != 0) strcat(line, " | ");
315  }
316  i++;
317  }
318  return line;
319 }
320 
321 
322 static CHAR *
324 {
325  INT i = 0;
326 
327  *line = 0;
328  while (band_maskname[i]) {
329  if (mask & (1<<i)) {
330  if (*line != 0) strcat(line, " | ");
332  }
333  i++;
334  }
335  return line;
336 }
337 
338 
339 static VOID
341 {
342  if( !TRACE_ON(rebar) ) return;
343  TRACE("band info: ");
344  if (pB->fMask & RBBIM_ID)
345  TRACE("ID=%u, ", pB->wID);
346  TRACE("size=%u, child=%p", pB->cbSize, pB->hwndChild);
347  if (pB->fMask & RBBIM_COLORS)
348  TRACE(", clrF=0x%06x, clrB=0x%06x", pB->clrFore, pB->clrBack);
349  TRACE("\n");
350 
351  TRACE("band info: mask=0x%08x (%s)\n", pB->fMask, REBAR_FmtMask(pB->fMask));
352  if (pB->fMask & RBBIM_STYLE)
353  TRACE("band info: style=0x%08x (%s)\n", pB->fStyle, REBAR_FmtStyle(pB->fStyle));
355  TRACE("band info:");
356  if (pB->fMask & RBBIM_SIZE)
357  TRACE(" cx=%u", pB->cx);
358  if (pB->fMask & RBBIM_IDEALSIZE)
359  TRACE(" xIdeal=%u", pB->cxIdeal);
360  if (pB->fMask & RBBIM_HEADERSIZE)
361  TRACE(" xHeader=%u", pB->cxHeader);
362  if (pB->fMask & RBBIM_LPARAM)
363  TRACE(" lParam=0x%08lx", pB->lParam);
364  TRACE("\n");
365  }
366  if (pB->fMask & RBBIM_CHILDSIZE)
367  TRACE("band info: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
368  pB->cxMinChild,
369  pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
370 }
371 
372 static VOID
374 {
375  REBAR_BAND *pB;
376  UINT i;
377 
378  if(! TRACE_ON(rebar) ) return;
379 
380  TRACE("hwnd=%p: color=%08x/%08x, bands=%u, rows=%u, cSize=%d,%d\n",
381  iP->hwndSelf, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
382  iP->calcSize.cx, iP->calcSize.cy);
383  TRACE("hwnd=%p: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, iGrabbedBand=%d\n",
384  iP->hwndSelf, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
385  iP->dragNow.x, iP->dragNow.y,
386  iP->iGrabbedBand);
387  TRACE("hwnd=%p: style=%08x, notify in Unicode=%s, redraw=%s\n",
388  iP->hwndSelf, iP->dwStyle, (iP->bUnicode)?"TRUE":"FALSE",
389  (iP->DoRedraw)?"TRUE":"FALSE");
390  for (i = 0; i < iP->uNumBands; i++) {
391  pB = REBAR_GetBand(iP, i);
392  TRACE("band # %u:", i);
393  if (pB->fMask & RBBIM_ID)
394  TRACE(" ID=%u", pB->wID);
395  if (pB->fMask & RBBIM_CHILD)
396  TRACE(" child=%p", pB->hwndChild);
397  if (pB->fMask & RBBIM_COLORS)
398  TRACE(" clrF=0x%06x clrB=0x%06x", pB->clrFore, pB->clrBack);
399  TRACE("\n");
400  TRACE("band # %u: mask=0x%08x (%s)\n", i, pB->fMask, REBAR_FmtMask(pB->fMask));
401  if (pB->fMask & RBBIM_STYLE)
402  TRACE("band # %u: style=0x%08x (%s)\n",
403  i, pB->fStyle, REBAR_FmtStyle(pB->fStyle));
404  TRACE("band # %u: xHeader=%u",
405  i, pB->cxHeader);
406  if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_LPARAM )) {
407  if (pB->fMask & RBBIM_SIZE)
408  TRACE(" cx=%u", pB->cx);
409  if (pB->fMask & RBBIM_IDEALSIZE)
410  TRACE(" xIdeal=%u", pB->cxIdeal);
411  if (pB->fMask & RBBIM_LPARAM)
412  TRACE(" lParam=0x%08lx", pB->lParam);
413  }
414  TRACE("\n");
415  if (RBBIM_CHILDSIZE)
416  TRACE("band # %u: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
417  i, pB->cxMinChild, pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
418  if (pB->fMask & RBBIM_TEXT)
419  TRACE("band # %u: text=%s\n",
420  i, (pB->lpText) ? debugstr_w(pB->lpText) : "(null)");
421  TRACE("band # %u: cxMinBand=%u, cxEffective=%u, cyMinBand=%u\n",
422  i, pB->cxMinBand, pB->cxEffective, pB->cyMinBand);
423  TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%s), Grip=(%s)\n",
424  i, pB->fStatus, pB->fDraw, wine_dbgstr_rect(&pB->rcBand),
426  TRACE("band # %u: Img=(%s), Txt=(%s), Child=(%s)\n",
429  }
430 
431 }
432 
433 /* dest can be equal to src */
434 static void translate_rect(const REBAR_INFO *infoPtr, RECT *dest, const RECT *src)
435 {
436  if (infoPtr->dwStyle & CCS_VERT) {
437  int tmp;
438  tmp = src->left;
439  dest->left = src->top;
440  dest->top = tmp;
441 
442  tmp = src->right;
443  dest->right = src->bottom;
444  dest->bottom = tmp;
445  } else {
446  *dest = *src;
447  }
448 }
449 
450 static int get_rect_cx(const REBAR_INFO *infoPtr, const RECT *lpRect)
451 {
452  if (infoPtr->dwStyle & CCS_VERT)
453  return lpRect->bottom - lpRect->top;
454  return lpRect->right - lpRect->left;
455 }
456 
457 static int get_rect_cy(const REBAR_INFO *infoPtr, const RECT *lpRect)
458 {
459  if (infoPtr->dwStyle & CCS_VERT)
460  return lpRect->right - lpRect->left;
461  return lpRect->bottom - lpRect->top;
462 }
463 
464 static int round_child_height(const REBAR_BAND *lpBand, int cyHeight)
465 {
466  int cy = 0;
467  if (lpBand->cyIntegral == 0)
468  return cyHeight;
469  cy = max(cyHeight - (int)lpBand->cyMinChild, 0);
470  cy = lpBand->cyMinChild + (cy/lpBand->cyIntegral) * lpBand->cyIntegral;
471  cy = min(cy, lpBand->cyMaxChild);
472  return cy;
473 }
474 
475 static void update_min_band_height(const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
476 {
477  lpBand->cyMinBand = max(lpBand->cyHeader,
478  (lpBand->hwndChild ? lpBand->cyChild + REBARSPACE(lpBand) : REBAR_NO_CHILD_HEIGHT));
479 }
480 
481 static void
483 {
484  INT x, y;
485  HPEN hPen, hOldPen;
486 
487  if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return;
488  hOldPen = SelectObject ( hdc, hPen );
489  x = left + 2;
490  y = top;
491  MoveToEx (hdc, x, y, NULL);
492  LineTo (hdc, x+5, y++); x++;
493  MoveToEx (hdc, x, y, NULL);
494  LineTo (hdc, x+3, y++); x++;
495  MoveToEx (hdc, x, y, NULL);
496  LineTo (hdc, x+1, y);
497  SelectObject( hdc, hOldPen );
498  DeleteObject( hPen );
499 }
500 
501 static HWND
503 {
504  HWND parent, owner;
505 
506  parent = infoPtr->hwndNotify;
507  if (!parent) {
508  parent = GetParent (infoPtr->hwndSelf);
509  owner = GetWindow (infoPtr->hwndSelf, GW_OWNER);
510  if (owner) parent = owner;
511  }
512  return parent;
513 }
514 
515 
516 static INT
517 REBAR_Notify (NMHDR *nmhdr, const REBAR_INFO *infoPtr, UINT code)
518 {
519  HWND parent;
520 
521  parent = REBAR_GetNotifyParent (infoPtr);
522  nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
523  nmhdr->hwndFrom = infoPtr->hwndSelf;
524  nmhdr->code = code;
525 
526  TRACE("window %p, code=%08x, via %s\n", parent, code, (infoPtr->bUnicode)?"Unicode":"ANSI");
527 
528  return SendMessageW(parent, WM_NOTIFY, nmhdr->idFrom, (LPARAM)nmhdr);
529 }
530 
531 static INT
532 REBAR_Notify_NMREBAR (const REBAR_INFO *infoPtr, UINT uBand, UINT code)
533 {
534  NMREBAR notify_rebar;
535 
536  notify_rebar.dwMask = 0;
537  if (uBand != -1) {
538  REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, uBand);
539 
540  if (lpBand->fMask & RBBIM_ID) {
541  notify_rebar.dwMask |= RBNM_ID;
542  notify_rebar.wID = lpBand->wID;
543  }
544  if (lpBand->fMask & RBBIM_LPARAM) {
545  notify_rebar.dwMask |= RBNM_LPARAM;
546  notify_rebar.lParam = lpBand->lParam;
547  }
548  if (lpBand->fMask & RBBIM_STYLE) {
549  notify_rebar.dwMask |= RBNM_STYLE;
550  notify_rebar.fStyle = lpBand->fStyle;
551  }
552  }
553  notify_rebar.uBand = uBand;
554  return REBAR_Notify ((NMHDR *)&notify_rebar, infoPtr, code);
555 }
556 
557 static VOID
558 REBAR_DrawBand (HDC hdc, const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
559 {
560  HFONT hOldFont = 0;
561  INT oldBkMode = 0;
562  NMCUSTOMDRAW nmcd;
563  HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
564  RECT rcBand;
565 
566  translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
567 
568  if (lpBand->fDraw & DRAW_TEXT) {
569  hOldFont = SelectObject (hdc, infoPtr->hFont);
570  oldBkMode = SetBkMode (hdc, TRANSPARENT);
571  }
572 
573  /* should test for CDRF_NOTIFYITEMDRAW here */
575  nmcd.hdc = hdc;
576  nmcd.rc = rcBand;
577  nmcd.rc.right = lpBand->rcCapText.right;
578  nmcd.rc.bottom = lpBand->rcCapText.bottom;
579  nmcd.dwItemSpec = lpBand->wID;
580  nmcd.uItemState = 0;
581  nmcd.lItemlParam = lpBand->lParam;
582  lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
583  if (lpBand->uCDret == CDRF_SKIPDEFAULT) {
584  if (oldBkMode != TRANSPARENT)
585  SetBkMode (hdc, oldBkMode);
586  SelectObject (hdc, hOldFont);
587  return;
588  }
589 
590  /* draw gripper */
591  if (lpBand->fDraw & DRAW_GRIPPER)
592  {
593  if (theme)
594  {
595  RECT rcGripper = lpBand->rcGripper;
596  int partId = (infoPtr->dwStyle & CCS_VERT) ? RP_GRIPPERVERT : RP_GRIPPER;
597  GetThemeBackgroundExtent (theme, hdc, partId, 0, &rcGripper, &rcGripper);
598  OffsetRect (&rcGripper, lpBand->rcGripper.left - rcGripper.left,
599  lpBand->rcGripper.top - rcGripper.top);
600  DrawThemeBackground (theme, hdc, partId, 0, &rcGripper, NULL);
601  }
602  else
604  }
605 
606  /* draw caption image */
607  if (lpBand->fDraw & DRAW_IMAGE) {
608  POINT pt;
609 
610  /* center image */
611  pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
612  pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;
613 
614  ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
615  pt.x, pt.y,
617  }
618 
619  /* draw caption text */
620  if (lpBand->fDraw & DRAW_TEXT) {
621  /* need to handle CDRF_NEWFONT here */
622  INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
623  COLORREF oldcolor = CLR_NONE;
624  COLORREF new;
625  if (lpBand->clrFore != CLR_NONE) {
626  new = (lpBand->clrFore == CLR_DEFAULT) ? infoPtr->clrBtnText :
627  lpBand->clrFore;
628  oldcolor = SetTextColor (hdc, new);
629  }
630 
631 #ifdef __REACTOS__
632  if (!theme)
633  {
634  DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
635  }
636  else
637  {
638  DrawThemeText(theme, hdc, 0, 0, lpBand->lpText, -1, DT_CENTER | DT_VCENTER | DT_SINGLELINE, 0, &lpBand->rcCapText);
639  }
640 #else
641  DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
643 #endif
644 
645  if (oldBkMode != TRANSPARENT)
646  SetBkMode (hdc, oldBkMode);
647  if (lpBand->clrFore != CLR_NONE)
648  SetTextColor (hdc, oldcolor);
649  SelectObject (hdc, hOldFont);
650  }
651 
652  if (!IsRectEmpty(&lpBand->rcChevron))
653  {
654  if (theme)
655  {
656  int stateId;
657  if (lpBand->fDraw & DRAW_CHEVRONPUSHED)
658  stateId = CHEVS_PRESSED;
659  else if (lpBand->fDraw & DRAW_CHEVRONHOT)
660  stateId = CHEVS_HOT;
661  else
662  stateId = CHEVS_NORMAL;
663  DrawThemeBackground (theme, hdc, RP_CHEVRON, stateId, &lpBand->rcChevron, NULL);
664  }
665  else
666  {
667  if (lpBand->fDraw & DRAW_CHEVRONPUSHED)
668  {
671  }
672  else if (lpBand->fDraw & DRAW_CHEVRONHOT)
673  {
676  }
677  else
679  }
680  }
681 
682  if (lpBand->uCDret == (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW)) {
683  nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
684  nmcd.hdc = hdc;
685  nmcd.rc = rcBand;
686  nmcd.rc.right = lpBand->rcCapText.right;
687  nmcd.rc.bottom = lpBand->rcCapText.bottom;
688  nmcd.dwItemSpec = lpBand->wID;
689  nmcd.uItemState = 0;
690  nmcd.lItemlParam = lpBand->lParam;
691  lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
692  }
693 }
694 
695 
696 static VOID
697 REBAR_Refresh (const REBAR_INFO *infoPtr, HDC hdc)
698 {
699  REBAR_BAND *lpBand;
700  UINT i;
701 
702  if (!infoPtr->DoRedraw) return;
703 
704  for (i = 0; i < infoPtr->uNumBands; i++) {
705  lpBand = REBAR_GetBand(infoPtr, i);
706 
707  if (HIDDENBAND(lpBand)) continue;
708 
709  /* now draw the band */
710  TRACE("[%p] drawing band %i, flags=%08x\n",
711  infoPtr->hwndSelf, i, lpBand->fDraw);
712  REBAR_DrawBand (hdc, infoPtr, lpBand);
713  }
714 }
715 
716 
717 static void
718 REBAR_CalcHorzBand (const REBAR_INFO *infoPtr, UINT rstart, UINT rend)
719  /* Function: this routine initializes all the rectangles in */
720  /* each band in a row to fit in the adjusted rcBand rect. */
721  /* *** Supports only Horizontal bars. *** */
722 {
723  REBAR_BAND *lpBand;
724  UINT i, xoff;
725  RECT work;
726 
727  for(i=rstart; i<rend; i++){
728  lpBand = REBAR_GetBand(infoPtr, i);
729  if (HIDDENBAND(lpBand)) {
730  SetRect (&lpBand->rcChild,
731  lpBand->rcBand.right, lpBand->rcBand.top,
732  lpBand->rcBand.right, lpBand->rcBand.bottom);
733  continue;
734  }
735 
736  /* set initial gripper rectangle */
737  SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
738  lpBand->rcBand.left, lpBand->rcBand.bottom);
739 
740  /* calculate gripper rectangle */
741  if ( lpBand->fStatus & HAS_GRIPPER) {
742  lpBand->fDraw |= DRAW_GRIPPER;
743  lpBand->rcGripper.left += REBAR_PRE_GRIPPER;
744  lpBand->rcGripper.right = lpBand->rcGripper.left + GRIPPER_WIDTH;
745  InflateRect(&lpBand->rcGripper, 0, -2);
746 
747  SetRect (&lpBand->rcCapImage,
748  lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.top,
749  lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.bottom);
750  }
751  else { /* no gripper will be drawn */
752  xoff = 0;
753  if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
754  /* if no gripper but either image or text, then leave space */
755  xoff = REBAR_ALWAYS_SPACE;
756  SetRect (&lpBand->rcCapImage,
757  lpBand->rcBand.left+xoff, lpBand->rcBand.top,
758  lpBand->rcBand.left+xoff, lpBand->rcBand.bottom);
759  }
760 
761  /* image is visible */
762  if (lpBand->fStatus & HAS_IMAGE) {
763  lpBand->fDraw |= DRAW_IMAGE;
764  lpBand->rcCapImage.right += infoPtr->imageSize.cx;
765  lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
766 
767  /* set initial caption text rectangle */
768  SetRect (&lpBand->rcCapText,
769  lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1,
770  lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
771  }
772  else {
773  /* set initial caption text rectangle */
774  SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1,
775  lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
776  }
777 
778  /* text is visible */
779  if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
780  lpBand->fDraw |= DRAW_TEXT;
781  lpBand->rcCapText.right = max(lpBand->rcCapText.left,
783  }
784 
785  /* set initial child window rectangle if there is a child */
786  if (lpBand->hwndChild) {
787 
788  lpBand->rcChild.left = lpBand->rcBand.left + lpBand->cxHeader;
789  lpBand->rcChild.right = lpBand->rcBand.right - REBAR_POST_CHILD;
790 
791  if (lpBand->cyChild > 0) {
792 
793  UINT yoff = (lpBand->rcBand.bottom - lpBand->rcBand.top - lpBand->cyChild) / 2;
794 
795  /* center child if height is known */
796  lpBand->rcChild.top = lpBand->rcBand.top + yoff;
797  lpBand->rcChild.bottom = lpBand->rcBand.top + yoff + lpBand->cyChild;
798  }
799  else {
800  lpBand->rcChild.top = lpBand->rcBand.top;
801  lpBand->rcChild.bottom = lpBand->rcBand.bottom;
802  }
803 
804  if ((lpBand->fStyle & RBBS_USECHEVRON) && (lpBand->rcChild.right - lpBand->rcChild.left < lpBand->cxIdeal))
805  {
806  lpBand->rcChild.right -= CHEVRON_WIDTH;
807  SetRect(&lpBand->rcChevron, lpBand->rcChild.right,
808  lpBand->rcChild.top, lpBand->rcChild.right + CHEVRON_WIDTH,
809  lpBand->rcChild.bottom);
810  }
811  }
812  else {
813  SetRect (&lpBand->rcChild,
814  lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
815  lpBand->rcBand.right, lpBand->rcBand.bottom);
816  }
817 
818  /* flag if notify required and invalidate rectangle */
819  if (lpBand->fDraw & NTF_INVALIDATE) {
820  lpBand->fDraw &= ~NTF_INVALIDATE;
821  work = lpBand->rcBand;
822  work.right += SEP_WIDTH;
823  work.bottom += SEP_WIDTH;
824  TRACE("invalidating %s\n", wine_dbgstr_rect(&work));
825  InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
826  if (lpBand->hwndChild) InvalidateRect(lpBand->hwndChild, NULL, TRUE);
827  }
828 
829  }
830 
831 }
832 
833 
834 static VOID
835 REBAR_CalcVertBand (const REBAR_INFO *infoPtr, UINT rstart, UINT rend)
836  /* Function: this routine initializes all the rectangles in */
837  /* each band in a row to fit in the adjusted rcBand rect. */
838  /* *** Supports only Vertical bars. *** */
839 {
840  REBAR_BAND *lpBand;
841  UINT i, xoff;
842  RECT work;
843 
844  for(i=rstart; i<rend; i++){
845  RECT rcBand;
846  lpBand = REBAR_GetBand(infoPtr, i);
847  if (HIDDENBAND(lpBand)) continue;
848 
849  translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
850 
851  /* set initial gripper rectangle */
852  SetRect (&lpBand->rcGripper, rcBand.left, rcBand.top, rcBand.right, rcBand.top);
853 
854  /* calculate gripper rectangle */
855  if (lpBand->fStatus & HAS_GRIPPER) {
856  lpBand->fDraw |= DRAW_GRIPPER;
857 
858  if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) {
859  /* vertical gripper */
860  lpBand->rcGripper.left += 3;
861  lpBand->rcGripper.right = lpBand->rcGripper.left + GRIPPER_WIDTH;
862  lpBand->rcGripper.top += REBAR_PRE_GRIPPER;
863  lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
864 
865  /* initialize Caption image rectangle */
866  SetRect (&lpBand->rcCapImage, rcBand.left,
868  rcBand.right,
870  }
871  else {
872  /* horizontal gripper */
873  InflateRect(&lpBand->rcGripper, -2, 0);
874  lpBand->rcGripper.top += REBAR_PRE_GRIPPER;
875  lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_WIDTH;
876 
877  /* initialize Caption image rectangle */
878  SetRect (&lpBand->rcCapImage, rcBand.left,
880  rcBand.right,
882  }
883  }
884  else { /* no gripper will be drawn */
885  xoff = 0;
886  if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
887  /* if no gripper but either image or text, then leave space */
888  xoff = REBAR_ALWAYS_SPACE;
889  /* initialize Caption image rectangle */
890  SetRect (&lpBand->rcCapImage,
891  rcBand.left, rcBand.top+xoff,
892  rcBand.right, rcBand.top+xoff);
893  }
894 
895  /* image is visible */
896  if (lpBand->fStatus & HAS_IMAGE) {
897  lpBand->fDraw |= DRAW_IMAGE;
898 
899  lpBand->rcCapImage.right = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
900  lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;
901 
902  /* set initial caption text rectangle */
903  SetRect (&lpBand->rcCapText,
904  rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
905  rcBand.right, rcBand.top+lpBand->cxHeader);
906  }
907  else {
908  /* set initial caption text rectangle */
909  SetRect (&lpBand->rcCapText,
910  rcBand.left, lpBand->rcCapImage.bottom,
911  rcBand.right, rcBand.top+lpBand->cxHeader);
912  }
913 
914  /* text is visible */
915  if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
916  lpBand->fDraw |= DRAW_TEXT;
917  lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
918  lpBand->rcCapText.bottom);
919  }
920 
921  /* set initial child window rectangle if there is a child */
922  if (lpBand->hwndChild) {
923  int cxBand = rcBand.right - rcBand.left;
924  xoff = (cxBand - lpBand->cyChild) / 2;
925  SetRect (&lpBand->rcChild,
926  rcBand.left + xoff, rcBand.top + lpBand->cxHeader,
927  rcBand.left + xoff + lpBand->cyChild, rcBand.bottom - REBAR_POST_CHILD);
928  }
929  else {
930  SetRect (&lpBand->rcChild,
931  rcBand.left, rcBand.top+lpBand->cxHeader,
932  rcBand.right, rcBand.bottom);
933  }
934 
935  if (lpBand->fDraw & NTF_INVALIDATE) {
936  lpBand->fDraw &= ~NTF_INVALIDATE;
937  work = rcBand;
938  work.bottom += SEP_WIDTH;
939  work.right += SEP_WIDTH;
940  TRACE("invalidating %s\n", wine_dbgstr_rect(&work));
941  InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
942  if (lpBand->hwndChild) InvalidateRect(lpBand->hwndChild, NULL, TRUE);
943  }
944 
945  }
946 }
947 
948 
949 static VOID
951  /* Function: This changes the size of the REBAR window to that */
952  /* calculated by REBAR_Layout. */
953 {
954  INT x, y, width, height;
955  INT xedge = 0, yedge = 0;
956  RECT rcSelf;
957 
958  TRACE("new size [%d x %d]\n", infoPtr->calcSize.cx, infoPtr->calcSize.cy);
959 
960  if (infoPtr->dwStyle & CCS_NORESIZE)
961  return;
962 
963  if (infoPtr->dwStyle & WS_BORDER)
964  {
965  xedge = GetSystemMetrics(SM_CXEDGE);
966  yedge = GetSystemMetrics(SM_CYEDGE);
967  /* swap for CCS_VERT? */
968  }
969 
970  /* compute rebar window rect in parent client coordinates */
971  GetWindowRect(infoPtr->hwndSelf, &rcSelf);
972  MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->hwndSelf), (LPPOINT)&rcSelf, 2);
973  translate_rect(infoPtr, &rcSelf, &rcSelf);
974 
975  height = infoPtr->calcSize.cy + 2*yedge;
976  if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) {
977  RECT rcParent;
978 
979  x = -xedge;
980  width = infoPtr->calcSize.cx + 2*xedge;
981  y = 0; /* quiet compiler warning */
982  switch ( infoPtr->dwStyle & CCS_LAYOUT_MASK) {
983  case 0: /* shouldn't happen - see NCCreate */
984  case CCS_TOP:
985  y = ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER) - yedge;
986  break;
987  case CCS_NOMOVEY:
988  y = rcSelf.top;
989  break;
990  case CCS_BOTTOM:
991  GetClientRect(GetParent(infoPtr->hwndSelf), &rcParent);
992  translate_rect(infoPtr, &rcParent, &rcParent);
993  y = rcParent.bottom - infoPtr->calcSize.cy - yedge;
994  break;
995  }
996  }
997  else {
998  x = rcSelf.left;
999  /* As on Windows if the CCS_NODIVIDER is not present the control will move
1000  * 2 pixel down after every layout */
1001  y = rcSelf.top + ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
1002  width = rcSelf.right - rcSelf.left;
1003  }
1004 
1005  TRACE("hwnd %p, style=%08x, setting at (%d,%d) for (%d,%d)\n",
1006  infoPtr->hwndSelf, infoPtr->dwStyle, x, y, width, height);
1007 
1008  /* Set flag to ignore next WM_SIZE message and resize the window */
1009  infoPtr->fStatus |= SELF_RESIZE;
1010  if ((infoPtr->dwStyle & CCS_VERT) == 0)
1011  SetWindowPos(infoPtr->hwndSelf, 0, x, y, width, height, SWP_NOZORDER);
1012  else
1013  SetWindowPos(infoPtr->hwndSelf, 0, y, x, height, width, SWP_NOZORDER);
1014  infoPtr->fStatus &= ~SELF_RESIZE;
1015 }
1016 
1017 
1018 static VOID
1020 {
1021  static const WCHAR strComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
1022  REBAR_BAND *lpBand;
1023  WCHAR szClassName[40];
1024  UINT i;
1025  NMREBARCHILDSIZE rbcz;
1026  HDWP deferpos;
1027 
1028  if (!(deferpos = BeginDeferWindowPos(infoPtr->uNumBands)))
1029  ERR("BeginDeferWindowPos returned NULL\n");
1030 
1031  for (i = start; i < endplus; i++) {
1032  lpBand = REBAR_GetBand(infoPtr, i);
1033 
1034  if (HIDDENBAND(lpBand)) continue;
1035  if (lpBand->hwndChild) {
1036  TRACE("hwndChild = %p\n", lpBand->hwndChild);
1037 
1038  /* Always generate the RBN_CHILDSIZE even if child
1039  did not change */
1040  rbcz.uBand = i;
1041  rbcz.wID = lpBand->wID;
1042  rbcz.rcChild = lpBand->rcChild;
1043  translate_rect(infoPtr, &rbcz.rcBand, &lpBand->rcBand);
1044  if (infoPtr->dwStyle & CCS_VERT)
1045  rbcz.rcBand.top += lpBand->cxHeader;
1046  else
1047  rbcz.rcBand.left += lpBand->cxHeader;
1048  REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
1049  if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
1050  TRACE("Child rect changed by NOTIFY for band %u\n", i);
1051  TRACE(" from (%s) to (%s)\n",
1052  wine_dbgstr_rect(&lpBand->rcChild),
1053  wine_dbgstr_rect(&rbcz.rcChild));
1054  lpBand->rcChild = rbcz.rcChild; /* *** ??? */
1055  }
1056 
1058  if (!lstrcmpW (szClassName, strComboBox) ||
1060  INT nEditHeight, yPos;
1061  RECT rc;
1062 
1063  /* special placement code for combo or comboex box */
1064 
1065 
1066  /* get size of edit line */
1067  GetWindowRect (lpBand->hwndChild, &rc);
1068  nEditHeight = rc.bottom - rc.top;
1069  yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
1070 
1071  /* center combo box inside child area */
1072  TRACE("moving child (Combo(Ex)) %p to (%d,%d) for (%d,%d)\n",
1073  lpBand->hwndChild,
1074  lpBand->rcChild.left, yPos,
1075  lpBand->rcChild.right - lpBand->rcChild.left,
1076  nEditHeight);
1077  deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
1078  lpBand->rcChild.left,
1079  /*lpBand->rcChild.top*/ yPos,
1080  lpBand->rcChild.right - lpBand->rcChild.left,
1081  nEditHeight,
1082  SWP_NOZORDER);
1083  if (!deferpos)
1084  ERR("DeferWindowPos returned NULL\n");
1085  }
1086  else {
1087  TRACE("moving child (Other) %p to (%d,%d) for (%d,%d)\n",
1088  lpBand->hwndChild,
1089  lpBand->rcChild.left, lpBand->rcChild.top,
1090  lpBand->rcChild.right - lpBand->rcChild.left,
1091  lpBand->rcChild.bottom - lpBand->rcChild.top);
1092  deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
1093  lpBand->rcChild.left,
1094  lpBand->rcChild.top,
1095  lpBand->rcChild.right - lpBand->rcChild.left,
1096  lpBand->rcChild.bottom - lpBand->rcChild.top,
1097  SWP_NOZORDER);
1098  if (!deferpos)
1099  ERR("DeferWindowPos returned NULL\n");
1100  }
1101  }
1102  }
1103  if (!EndDeferWindowPos(deferpos))
1104  ERR("EndDeferWindowPos returned NULL\n");
1105 
1106  if (infoPtr->DoRedraw)
1107  UpdateWindow (infoPtr->hwndSelf);
1108 }
1109 
1110 /* Returns the next visible band (the first visible band in [i+1; infoPtr->uNumBands) )
1111  * or infoPtr->uNumBands if none */
1112 static int next_visible(const REBAR_INFO *infoPtr, int i)
1113 {
1114  unsigned int n;
1115  for (n = i + 1; n < infoPtr->uNumBands; n++)
1116  if (!HIDDENBAND(REBAR_GetBand(infoPtr, n)))
1117  break;
1118  return n;
1119 }
1120 
1121 /* Returns the previous visible band (the last visible band in [0; i) )
1122  * or -1 if none */
1123 static int prev_visible(const REBAR_INFO *infoPtr, int i)
1124 {
1125  int n;
1126  for (n = i - 1; n >= 0; n--)
1127  if (!HIDDENBAND(REBAR_GetBand(infoPtr, n)))
1128  break;
1129  return n;
1130 }
1131 
1132 /* Returns the first visible band or infoPtr->uNumBands if none */
1133 static int first_visible(const REBAR_INFO *infoPtr)
1134 {
1135  return next_visible(infoPtr, -1); /* this works*/
1136 }
1137 
1138 /* Returns the first visible band for the given row (or iBand if none) */
1139 static int get_row_begin_for_band(const REBAR_INFO *infoPtr, INT iBand)
1140 {
1141  int iLastBand = iBand;
1142  int iRow = REBAR_GetBand(infoPtr, iBand)->iRow;
1143  while ((iBand = prev_visible(infoPtr, iBand)) >= 0) {
1144  if (REBAR_GetBand(infoPtr, iBand)->iRow != iRow)
1145  break;
1146  else
1147  iLastBand = iBand;
1148  }
1149  return iLastBand;
1150 }
1151 
1152 /* Returns the first visible band for the next row (or infoPtr->uNumBands if none) */
1153 static int get_row_end_for_band(const REBAR_INFO *infoPtr, INT iBand)
1154 {
1155  int iRow = REBAR_GetBand(infoPtr, iBand)->iRow;
1156  while ((iBand = next_visible(infoPtr, iBand)) < infoPtr->uNumBands)
1157  if (REBAR_GetBand(infoPtr, iBand)->iRow != iRow)
1158  break;
1159  return iBand;
1160 }
1161 
1162 /* Compute the rcBand.{left,right} from the cxEffective bands widths computed earlier.
1163  * iBeginBand must be visible */
1164 static void REBAR_SetRowRectsX(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand)
1165 {
1166  int xPos = 0, i;
1167  for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
1168  {
1169  REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
1170  if (lpBand->rcBand.left != xPos || lpBand->rcBand.right != xPos + lpBand->cxEffective) {
1171  lpBand->fDraw |= NTF_INVALIDATE;
1172  TRACE("Setting rect %d to %d,%d\n", i, xPos, xPos + lpBand->cxEffective);
1173  lpBand->rcBand.left = xPos;
1174  lpBand->rcBand.right = xPos + lpBand->cxEffective;
1175  }
1176  xPos += lpBand->cxEffective + SEP_WIDTH;
1177  }
1178 }
1179 
1180 /* The rationale of this function is probably as follows: if we have some space
1181  * to distribute we want to add it to a band on the right. However we don't want
1182  * to unminimize a minimized band so we search for a band that is big enough.
1183  * For some reason "big enough" is defined as bigger than the minimum size of the
1184  * first band in the row
1185  */
1186 static REBAR_BAND *REBAR_FindBandToGrow(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand)
1187 {
1188  INT cxMinFirstBand = 0, i;
1189 
1190  cxMinFirstBand = REBAR_GetBand(infoPtr, iBeginBand)->cxMinBand;
1191 
1192  for (i = prev_visible(infoPtr, iEndBand); i >= iBeginBand; i = prev_visible(infoPtr, i))
1193  if (REBAR_GetBand(infoPtr, i)->cxEffective > cxMinFirstBand &&
1194  !(REBAR_GetBand(infoPtr, i)->fStyle & RBBS_FIXEDSIZE))
1195  break;
1196 
1197  if (i < iBeginBand)
1198  for (i = prev_visible(infoPtr, iEndBand); i >= iBeginBand; i = prev_visible(infoPtr, i))
1199  if (REBAR_GetBand(infoPtr, i)->cxMinBand == cxMinFirstBand)
1200  break;
1201 
1202  TRACE("Extra space for row [%d..%d) should be added to band %d\n", iBeginBand, iEndBand, i);
1203  return REBAR_GetBand(infoPtr, i);
1204 }
1205 
1206 /* Try to shrink the visible bands in [iBeginBand; iEndBand) by cxShrink, starting from the right */
1207 static int REBAR_ShrinkBandsRTL(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT cxShrink, BOOL bEnforce)
1208 {
1209  REBAR_BAND *lpBand;
1210  INT width, i;
1211 
1212  TRACE("Shrinking bands [%d..%d) by %d, right-to-left\n", iBeginBand, iEndBand, cxShrink);
1213  for (i = prev_visible(infoPtr, iEndBand); i >= iBeginBand; i = prev_visible(infoPtr, i))
1214  {
1215  lpBand = REBAR_GetBand(infoPtr, i);
1216 
1217  width = max(lpBand->cxEffective - cxShrink, (int)lpBand->cxMinBand);
1218  cxShrink -= lpBand->cxEffective - width;
1219  lpBand->cxEffective = width;
1220  if (bEnforce && lpBand->cx > lpBand->cxEffective)
1221  lpBand->cx = lpBand->cxEffective;
1222  if (cxShrink == 0)
1223  break;
1224  }
1225  return cxShrink;
1226 }
1227 
1228 
1229 /* Try to shrink the visible bands in [iBeginBand; iEndBand) by cxShrink, starting from the left.
1230  * iBeginBand must be visible */
1231 static int REBAR_ShrinkBandsLTR(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT cxShrink, BOOL bEnforce)
1232 {
1233  REBAR_BAND *lpBand;
1234  INT width, i;
1235 
1236  TRACE("Shrinking bands [%d..%d) by %d, left-to-right\n", iBeginBand, iEndBand, cxShrink);
1237  for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
1238  {
1239  lpBand = REBAR_GetBand(infoPtr, i);
1240 
1241  width = max(lpBand->cxEffective - cxShrink, (int)lpBand->cxMinBand);
1242  cxShrink -= lpBand->cxEffective - width;
1243  lpBand->cxEffective = width;
1244  if (bEnforce)
1245  lpBand->cx = lpBand->cxEffective;
1246  if (cxShrink == 0)
1247  break;
1248  }
1249  return cxShrink;
1250 }
1251 
1252 /* Tries to move a band to a given offset within a row. */
1253 static int REBAR_MoveBandToRowOffset(REBAR_INFO *infoPtr, INT iBand, INT iFirstBand,
1254  INT iLastBand, INT xOff, BOOL reorder)
1255 {
1256  REBAR_BAND *insertBand = REBAR_GetBand(infoPtr, iBand);
1257  int xPos = 0, i;
1258  const BOOL setBreak = REBAR_GetBand(infoPtr, iFirstBand)->fStyle & RBBS_BREAK;
1259 
1260  /* Find the band's new position */
1261  if(reorder)
1262  {
1263  /* Used during an LR band reorder drag */
1264  for (i = iFirstBand; i < iLastBand; i = next_visible(infoPtr, i))
1265  {
1266  if(xPos > xOff)
1267  break;
1268  xPos += REBAR_GetBand(infoPtr, i)->cxEffective + SEP_WIDTH;
1269  }
1270  }
1271  else
1272  {
1273  /* Used during a UD band insertion drag */
1274  for (i = iFirstBand; i < iLastBand; i = next_visible(infoPtr, i))
1275  {
1276  const REBAR_BAND *band = REBAR_GetBand(infoPtr, i);
1277  if(xPos + band->cxMinBand / 2 > xOff)
1278  break;
1279  xPos += band->cxEffective + SEP_WIDTH;
1280  }
1281  }
1282 
1283  /* Move the band to its new position */
1284  DPA_DeletePtr(infoPtr->bands, iBand);
1285  if(i > iBand)
1286  i--;
1287  DPA_InsertPtr(infoPtr->bands, i, insertBand);
1288 
1289  /* Ensure only the last band has the RBBS_BREAK flag set */
1290  insertBand->fStyle &= ~RBBS_BREAK;
1291  if(setBreak)
1292  REBAR_GetBand(infoPtr, iFirstBand)->fStyle |= RBBS_BREAK;
1293 
1294  /* Return the currently grabbed band */
1295  if(infoPtr->iGrabbedBand == iBand)
1296  {
1297  infoPtr->iGrabbedBand = i;
1298  return i;
1299  }
1300  else return -1;
1301 }
1302 
1303 /* Set the heights of the visible bands in [iBeginBand; iEndBand) to the max height. iBeginBand must be visible */
1304 static int REBAR_SetBandsHeight(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT yStart)
1305 {
1306  REBAR_BAND *lpBand;
1307  int yMaxHeight = 0;
1308  int yPos = yStart;
1309  int row = REBAR_GetBand(infoPtr, iBeginBand)->iRow;
1310  int i;
1311  for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
1312  {
1313  lpBand = REBAR_GetBand(infoPtr, i);
1314  lpBand->cyRowSoFar = yMaxHeight;
1315  yMaxHeight = max(yMaxHeight, lpBand->cyMinBand);
1316  }
1317  TRACE("Bands [%d; %d) height: %d\n", iBeginBand, iEndBand, yMaxHeight);
1318 
1319  for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
1320  {
1321  lpBand = REBAR_GetBand(infoPtr, i);
1322  /* we may be called for multiple rows if RBS_VARHEIGHT not set */
1323  if (lpBand->iRow != row) {
1324  yPos += yMaxHeight + SEP_WIDTH;
1325  row = lpBand->iRow;
1326  }
1327 
1328  if (lpBand->rcBand.top != yPos || lpBand->rcBand.bottom != yPos + yMaxHeight) {
1329  lpBand->fDraw |= NTF_INVALIDATE;
1330  lpBand->rcBand.top = yPos;
1331  lpBand->rcBand.bottom = yPos + yMaxHeight;
1332  TRACE("Band %d: %s\n", i, wine_dbgstr_rect(&lpBand->rcBand));
1333  }
1334  }
1335  return yPos + yMaxHeight;
1336 }
1337 
1338 /* Layout the row [iBeginBand; iEndBand). iBeginBand must be visible */
1339 static void REBAR_LayoutRow(const REBAR_INFO *infoPtr, int iBeginBand, int iEndBand, int cx, int *piRow, int *pyPos)
1340 {
1341  REBAR_BAND *lpBand;
1342  int i, extra;
1343  int width = 0;
1344 
1345  TRACE("Adjusting row [%d;%d). Width: %d\n", iBeginBand, iEndBand, cx);
1346  for (i = iBeginBand; i < iEndBand; i++)
1347  REBAR_GetBand(infoPtr, i)->iRow = *piRow;
1348 
1349  /* compute the extra space */
1350  for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
1351  {
1352  lpBand = REBAR_GetBand(infoPtr, i);
1353  if (i > iBeginBand)
1354  width += SEP_WIDTH;
1355  lpBand->cxEffective = max(lpBand->cxMinBand, lpBand->cx);
1356  width += lpBand->cxEffective;
1357  }
1358 
1359  extra = cx - width;
1360  TRACE("Extra space: %d\n", extra);
1361  if (extra < 0) {
1362  int ret = REBAR_ShrinkBandsRTL(infoPtr, iBeginBand, iEndBand, -extra, FALSE);
1363  if (ret > 0 && next_visible(infoPtr, iBeginBand) != iEndBand) /* one band may be longer than expected... */
1364  ERR("Error layouting row %d - couldn't shrink for %d pixels (%d total shrink)\n", *piRow, ret, -extra);
1365  } else
1366  if (extra > 0) {
1367  lpBand = REBAR_FindBandToGrow(infoPtr, iBeginBand, iEndBand);
1368  lpBand->cxEffective += extra;
1369  }
1370 
1371  REBAR_SetRowRectsX(infoPtr, iBeginBand, iEndBand);
1372  if (infoPtr->dwStyle & RBS_VARHEIGHT)
1373  {
1374  if (*piRow > 0)
1375  *pyPos += SEP_WIDTH;
1376  *pyPos = REBAR_SetBandsHeight(infoPtr, iBeginBand, iEndBand, *pyPos);
1377  }
1378  (*piRow)++;
1379 }
1380 
1381 static VOID
1383 {
1384  REBAR_BAND *lpBand;
1385  RECT rcAdj;
1386  SIZE oldSize;
1387  INT adjcx, i;
1388  INT rowstart;
1389  INT row = 0;
1390  INT xMin, yPos;
1391 
1392  if (infoPtr->dwStyle & (CCS_NORESIZE | CCS_NOPARENTALIGN) || GetParent(infoPtr->hwndSelf) == NULL)
1393  GetClientRect(infoPtr->hwndSelf, &rcAdj);
1394  else
1395  GetClientRect(GetParent(infoPtr->hwndSelf), &rcAdj);
1396  TRACE("adjustment rect is (%s)\n", wine_dbgstr_rect(&rcAdj));
1397 
1398  adjcx = get_rect_cx(infoPtr, &rcAdj);
1399 
1400  if (infoPtr->uNumBands == 0) {
1401  TRACE("No bands - setting size to (0,%d), style: %x\n", adjcx, infoPtr->dwStyle);
1402  infoPtr->calcSize.cx = adjcx;
1403  /* the calcSize.cy won't change for a 0 band rebar */
1404  infoPtr->uNumRows = 0;
1405  REBAR_ForceResize(infoPtr);
1406  return;
1407  }
1408 
1409  yPos = 0;
1410  xMin = 0;
1411  rowstart = first_visible(infoPtr);
1412  /* divide rows */
1413  for (i = rowstart; i < infoPtr->uNumBands; i = next_visible(infoPtr, i))
1414  {
1415  lpBand = REBAR_GetBand(infoPtr, i);
1416 
1417  if (i > rowstart && (lpBand->fStyle & RBBS_BREAK || xMin + lpBand->cxMinBand > adjcx)) {
1418  TRACE("%s break on band %d\n", (lpBand->fStyle & RBBS_BREAK ? "Hard" : "Soft"), i - 1);
1419  REBAR_LayoutRow(infoPtr, rowstart, i, adjcx, &row, &yPos);
1420  rowstart = i;
1421  xMin = 0;
1422  }
1423  else
1424  xMin += SEP_WIDTH;
1425 
1426  xMin += lpBand->cxMinBand;
1427  }
1428  if (rowstart < infoPtr->uNumBands)
1429  REBAR_LayoutRow(infoPtr, rowstart, infoPtr->uNumBands, adjcx, &row, &yPos);
1430 
1431  if (!(infoPtr->dwStyle & RBS_VARHEIGHT))
1432  yPos = REBAR_SetBandsHeight(infoPtr, first_visible(infoPtr), infoPtr->uNumBands, 0);
1433 
1434  infoPtr->uNumRows = row;
1435 
1436  if (infoPtr->dwStyle & CCS_VERT)
1437  REBAR_CalcVertBand(infoPtr, 0, infoPtr->uNumBands);
1438  else
1439  REBAR_CalcHorzBand(infoPtr, 0, infoPtr->uNumBands);
1440  /* now compute size of Rebar itself */
1441  oldSize = infoPtr->calcSize;
1442 
1443  infoPtr->calcSize.cx = adjcx;
1444  infoPtr->calcSize.cy = yPos;
1445  TRACE("calcsize size=(%d, %d), origheight=(%d,%d)\n",
1446  infoPtr->calcSize.cx, infoPtr->calcSize.cy,
1447  oldSize.cx, oldSize.cy);
1448 
1449  REBAR_DumpBand (infoPtr);
1450  REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
1451  REBAR_ForceResize (infoPtr);
1452 
1453  /* note: after a RBN_HEIGHTCHANGE native sends once again all the RBN_CHILDSIZE
1454  * and does another ForceResize */
1455  if (oldSize.cy != infoPtr->calcSize.cy)
1456  {
1457  NMHDR heightchange;
1458  REBAR_Notify(&heightchange, infoPtr, RBN_HEIGHTCHANGE);
1459  REBAR_AutoSize(infoPtr, FALSE);
1460  }
1461 }
1462 
1463 /* iBeginBand must be visible */
1464 static int
1465 REBAR_SizeChildrenToHeight(const REBAR_INFO *infoPtr, int iBeginBand, int iEndBand, int extra, BOOL *fChanged)
1466 {
1467  int cyBandsOld;
1468  int cyBandsNew = 0;
1469  int i;
1470 
1471  TRACE("[%d;%d) by %d\n", iBeginBand, iEndBand, extra);
1472 
1473  cyBandsOld = REBAR_GetBand(infoPtr, iBeginBand)->rcBand.bottom -
1474  REBAR_GetBand(infoPtr, iBeginBand)->rcBand.top;
1475  for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
1476  {
1477  REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
1478  int cyMaxChild = cyBandsOld - REBARSPACE(lpBand) + extra;
1479  int cyChild = round_child_height(lpBand, cyMaxChild);
1480 
1481  if (lpBand->hwndChild && cyChild != lpBand->cyChild && (lpBand->fStyle & RBBS_VARIABLEHEIGHT))
1482  {
1483  TRACE("Resizing %d: %d -> %d [%d]\n", i, lpBand->cyChild, cyChild, lpBand->cyMaxChild);
1484  *fChanged = TRUE;
1485  lpBand->cyChild = cyChild;
1486  lpBand->fDraw |= NTF_INVALIDATE;
1487  update_min_band_height(infoPtr, lpBand);
1488  }
1489  cyBandsNew = max(cyBandsNew, lpBand->cyMinBand);
1490  }
1491  return cyBandsNew - cyBandsOld;
1492 }
1493 
1494 /* worker function for RB_SIZETORECT and RBS_AUTOSIZE */
1495 static VOID
1497 {
1498  int extra = height - infoPtr->calcSize.cy; /* may be negative */
1499  BOOL fChanged = FALSE;
1500  UINT uNumRows = infoPtr->uNumRows;
1501  int i;
1502 
1503  if (uNumRows == 0) /* avoid division by 0 */
1504  return;
1505 
1506  /* That's not exactly what Windows does but should be similar */
1507 
1508  /* Pass one: break-up/glue rows */
1509  if (extra > 0)
1510  {
1511  for (i = prev_visible(infoPtr, infoPtr->uNumBands); i > 0; i = prev_visible(infoPtr, i))
1512  {
1513  REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
1514  int cyBreakExtra; /* additional cy for the rebar after a RBBS_BREAK on this band */
1515 
1516  height = lpBand->rcBand.bottom - lpBand->rcBand.top;
1517 
1518  if (infoPtr->dwStyle & RBS_VARHEIGHT)
1519  cyBreakExtra = lpBand->cyRowSoFar; /* 'height' => 'lpBand->cyRowSoFar' + 'height'*/
1520  else
1521  cyBreakExtra = height; /* 'height' => 'height' + 'height'*/
1522  cyBreakExtra += SEP_WIDTH;
1523 
1524  if (extra <= cyBreakExtra / 2)
1525  break;
1526 
1527  if (!(lpBand->fStyle & RBBS_BREAK))
1528  {
1529  TRACE("Adding break on band %d - extra %d -> %d\n", i, extra, extra - cyBreakExtra);
1530  lpBand->fStyle |= RBBS_BREAK;
1531  lpBand->fDraw |= NTF_INVALIDATE;
1532  fChanged = TRUE;
1533  extra -= cyBreakExtra;
1534  uNumRows++;
1535  /* temporary change for _SizeControlsToHeight. The true values will be computed in _Layout */
1536  if (infoPtr->dwStyle & RBS_VARHEIGHT)
1537  lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->cyMinBand;
1538  }
1539  }
1540  }
1541  /* TODO: else if (extra < 0) { try to remove some RBBS_BREAKs } */
1542 
1543  /* Pass two: increase/decrease control height */
1544  if (infoPtr->dwStyle & RBS_VARHEIGHT)
1545  {
1546  int i = first_visible(infoPtr);
1547  int iRow = 0;
1548  while (i < infoPtr->uNumBands)
1549  {
1550  REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
1551  int extraForRow = extra / (int)(uNumRows - iRow);
1552  int rowEnd;
1553 
1554  /* we can't use get_row_end_for_band as we might have added RBBS_BREAK in the first phase */
1555  for (rowEnd = next_visible(infoPtr, i); rowEnd < infoPtr->uNumBands; rowEnd = next_visible(infoPtr, rowEnd))
1556  if (REBAR_GetBand(infoPtr, rowEnd)->iRow != lpBand->iRow ||
1557  REBAR_GetBand(infoPtr, rowEnd)->fStyle & RBBS_BREAK)
1558  break;
1559 
1560  extra -= REBAR_SizeChildrenToHeight(infoPtr, i, rowEnd, extraForRow, &fChanged);
1561  TRACE("extra = %d\n", extra);
1562  i = rowEnd;
1563  iRow++;
1564  }
1565  }
1566  else
1567  REBAR_SizeChildrenToHeight(infoPtr, first_visible(infoPtr), infoPtr->uNumBands, extra / infoPtr->uNumRows, &fChanged);
1568 
1569  if (fChanged)
1570  REBAR_Layout(infoPtr);
1571 }
1572 
1573 static VOID
1574 REBAR_AutoSize(REBAR_INFO *infoPtr, BOOL needsLayout)
1575 {
1576  RECT rc, rcNew;
1577  NMRBAUTOSIZE autosize;
1578 
1579  if (needsLayout)
1580  REBAR_Layout(infoPtr);
1581  GetClientRect(infoPtr->hwndSelf, &rc);
1582  REBAR_SizeToHeight(infoPtr, get_rect_cy(infoPtr, &rc));
1583  GetClientRect(infoPtr->hwndSelf, &rcNew);
1584 
1585  GetClientRect(infoPtr->hwndSelf, &autosize.rcTarget);
1586  autosize.fChanged = EqualRect(&rc, &rcNew);
1587  autosize.rcTarget = rc;
1588  autosize.rcActual = rcNew;
1589  REBAR_Notify((NMHDR *)&autosize, infoPtr, RBN_AUTOSIZE);
1590 }
1591 
1592 static VOID
1593 REBAR_ValidateBand (const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
1594  /* Function: This routine evaluates the band specs supplied */
1595  /* by the user and updates the following 5 fields in */
1596  /* the internal band structure: cxHeader, cyHeader, cxMinBand, cyMinBand, fStatus */
1597 {
1598  UINT header=0;
1599  UINT textheight=0, imageheight = 0;
1600  UINT i, nonfixed;
1601  REBAR_BAND *tBand;
1602 
1603  lpBand->fStatus = 0;
1604  lpBand->cxMinBand = 0;
1605  lpBand->cyMinBand = 0;
1606 
1607  /* Data coming in from users into the cx... and cy... fields */
1608  /* may be bad, just garbage, because the user never clears */
1609  /* the fields. RB_{SET|INSERT}BAND{A|W} just passes the data */
1610  /* along if the fields exist in the input area. Here we must */
1611  /* determine if the data is valid. I have no idea how MS does */
1612  /* the validation, but it does because the RB_GETBANDINFO */
1613  /* returns a 0 when I know the sample program passed in an */
1614  /* address. Here I will use the algorithm that if the value */
1615  /* is greater than 65535 then it is bad and replace it with */
1616  /* a zero. Feel free to improve the algorithm. - GA 12/2000 */
1617  if (lpBand->cxMinChild > 65535) lpBand->cxMinChild = 0;
1618  if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0;
1619  if (lpBand->cx > 65535) lpBand->cx = 0;
1620  if (lpBand->cyChild > 65535) lpBand->cyChild = 0;
1621  if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0;
1622  if (lpBand->cxIdeal > 65535) lpBand->cxIdeal = 0;
1623  if (lpBand->cxHeader > 65535) lpBand->cxHeader = 0;
1624 
1625  /* TODO : we could try return to the caller if a value changed so that */
1626  /* a REBAR_Layout is needed. Till now the caller should call it */
1627  /* it always (we should also check what native does) */
1628 
1629  /* Header is where the image, text and gripper exist */
1630  /* in the band and precede the child window. */
1631 
1632  /* count number of non-FIXEDSIZE and non-Hidden bands */
1633  nonfixed = 0;
1634  for (i=0; i<infoPtr->uNumBands; i++){
1635  tBand = REBAR_GetBand(infoPtr, i);
1636  if (!HIDDENBAND(tBand) && !(tBand->fStyle & RBBS_FIXEDSIZE))
1637  nonfixed++;
1638  }
1639 
1640  /* calculate gripper rectangle */
1641  if ( (!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
1642  ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
1643  ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (nonfixed > 1)))
1644  ) {
1645  lpBand->fStatus |= HAS_GRIPPER;
1646  if (infoPtr->dwStyle & CCS_VERT)
1647  if (infoPtr->dwStyle & RBS_VERTICALGRIPPER)
1649  else
1651  else
1653  /* Always have 4 pixels before anything else */
1655  }
1656 
1657  /* image is visible */
1658  if (lpBand->iImage != -1 && (infoPtr->himl)) {
1659  lpBand->fStatus |= HAS_IMAGE;
1660  if (infoPtr->dwStyle & CCS_VERT) {
1661  header += (infoPtr->imageSize.cy + REBAR_POST_IMAGE);
1662  imageheight = infoPtr->imageSize.cx + 4;
1663  }
1664  else {
1665  header += (infoPtr->imageSize.cx + REBAR_POST_IMAGE);
1666  imageheight = infoPtr->imageSize.cy + 4;
1667  }
1668  }
1669 
1670  /* text is visible */
1671  if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText) &&
1672  !(lpBand->fStyle & RBBS_HIDETITLE)) {
1673  HDC hdc = GetDC (0);
1674  HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
1675  SIZE size;
1676 
1677  lpBand->fStatus |= HAS_TEXT;
1678  GetTextExtentPoint32W (hdc, lpBand->lpText,
1679  lstrlenW (lpBand->lpText), &size);
1680  header += ((infoPtr->dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT));
1681  textheight = (infoPtr->dwStyle & CCS_VERT) ? 0 : size.cy;
1682 
1683  SelectObject (hdc, hOldFont);
1684  ReleaseDC (0, hdc);
1685  }
1686 
1687  /* if no gripper but either image or text, then leave space */
1688  if ((lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) &&
1689  !(lpBand->fStatus & HAS_GRIPPER)) {
1691  }
1692 
1693  /* check if user overrode the header value */
1694  if (!(lpBand->fStyle & RBBS_UNDOC_FIXEDHEADER))
1695  lpBand->cxHeader = header;
1696  lpBand->cyHeader = max(textheight, imageheight);
1697 
1698  /* Now compute minimum size of child window */
1699  update_min_band_height(infoPtr, lpBand); /* update lpBand->cyMinBand from cyHeader and cyChild*/
1700 
1701  lpBand->cxMinBand = lpBand->cxMinChild + lpBand->cxHeader + REBAR_POST_CHILD;
1702  if (lpBand->fStyle & RBBS_USECHEVRON && lpBand->cxMinChild < lpBand->cxIdeal)
1703  lpBand->cxMinBand += CHEVRON_WIDTH;
1704 }
1705 
1706 static UINT
1708  /* Function: This routine copies the supplied values from */
1709  /* user input (lprbbi) to the internal band structure. */
1710  /* It returns the mask of what changed. */
1711 {
1712  UINT uChanged = 0x0;
1713 
1714  lpBand->fMask |= lprbbi->fMask;
1715 
1716  if( (lprbbi->fMask & RBBIM_STYLE) &&
1717  (lpBand->fStyle != lprbbi->fStyle ) )
1718  {
1719  lpBand->fStyle = lprbbi->fStyle;
1720  uChanged |= RBBIM_STYLE;
1721  }
1722 
1723  if( (lprbbi->fMask & RBBIM_COLORS) &&
1724  ( ( lpBand->clrFore != lprbbi->clrFore ) ||
1725  ( lpBand->clrBack != lprbbi->clrBack ) ) )
1726  {
1727  lpBand->clrFore = lprbbi->clrFore;
1728  lpBand->clrBack = lprbbi->clrBack;
1729  uChanged |= RBBIM_COLORS;
1730  }
1731 
1732  if( (lprbbi->fMask & RBBIM_IMAGE) &&
1733  ( lpBand->iImage != lprbbi->iImage ) )
1734  {
1735  lpBand->iImage = lprbbi->iImage;
1736  uChanged |= RBBIM_IMAGE;
1737  }
1738 
1739  if( (lprbbi->fMask & RBBIM_CHILD) &&
1740  (lprbbi->hwndChild != lpBand->hwndChild ) )
1741  {
1742  if (lprbbi->hwndChild) {
1743  lpBand->hwndChild = lprbbi->hwndChild;
1744  lpBand->hwndPrevParent =
1745  SetParent (lpBand->hwndChild, hwnd);
1746  /* below in trace from WinRAR */
1748  /* above in trace from WinRAR */
1749  }
1750  else {
1751  TRACE("child: %p prev parent: %p\n",
1752  lpBand->hwndChild, lpBand->hwndPrevParent);
1753  lpBand->hwndChild = 0;
1754  lpBand->hwndPrevParent = 0;
1755  }
1756  uChanged |= RBBIM_CHILD;
1757  }
1758 
1759  if( (lprbbi->fMask & RBBIM_CHILDSIZE) &&
1760  ( (lpBand->cxMinChild != lprbbi->cxMinChild) ||
1761  (lpBand->cyMinChild != lprbbi->cyMinChild ) ||
1762  ( (lprbbi->cbSize >= REBARBANDINFOA_V6_SIZE && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) &&
1763  ( (lpBand->cyChild != lprbbi->cyChild ) ||
1764  (lpBand->cyMaxChild != lprbbi->cyMaxChild ) ||
1765  (lpBand->cyIntegral != lprbbi->cyIntegral ) ) ) ||
1766  ( (lprbbi->cbSize < REBARBANDINFOA_V6_SIZE) &&
1767  ( (lpBand->cyChild ||
1768  lpBand->cyMaxChild ||
1769  lpBand->cyIntegral ) ) ) ) )
1770  {
1771  lpBand->cxMinChild = lprbbi->cxMinChild;
1772  lpBand->cyMinChild = lprbbi->cyMinChild;
1773  /* These fields where added in WIN32_IE == 0x400 and are set only for RBBS_VARIABLEHEIGHT bands */
1774  if (lprbbi->cbSize >= REBARBANDINFOA_V6_SIZE && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
1775  lpBand->cyMaxChild = lprbbi->cyMaxChild;
1776  lpBand->cyIntegral = lprbbi->cyIntegral;
1777 
1778  lpBand->cyChild = round_child_height(lpBand, lprbbi->cyChild); /* make (cyChild - cyMinChild) a multiple of cyIntergral */
1779  }
1780  else {
1781  lpBand->cyChild = lpBand->cyMinChild;
1782  lpBand->cyMaxChild = 0x7fffffff;
1783  lpBand->cyIntegral = 0;
1784  }
1785  uChanged |= RBBIM_CHILDSIZE;
1786  }
1787 
1788  if( (lprbbi->fMask & RBBIM_SIZE) &&
1789  (lpBand->cx != lprbbi->cx ) )
1790  {
1791  lpBand->cx = lprbbi->cx;
1792  uChanged |= RBBIM_SIZE;
1793  }
1794 
1795  if( (lprbbi->fMask & RBBIM_BACKGROUND) &&
1796  ( lpBand->hbmBack != lprbbi->hbmBack ) )
1797  {
1798  lpBand->hbmBack = lprbbi->hbmBack;
1799  uChanged |= RBBIM_BACKGROUND;
1800  }
1801 
1802  if( (lprbbi->fMask & RBBIM_ID) &&
1803  (lpBand->wID != lprbbi->wID ) )
1804  {
1805  lpBand->wID = lprbbi->wID;
1806  uChanged |= RBBIM_ID;
1807  }
1808 
1809  /* check for additional data */
1810  if (lprbbi->cbSize >= REBARBANDINFOA_V6_SIZE) {
1811  if( (lprbbi->fMask & RBBIM_IDEALSIZE) &&
1812  ( lpBand->cxIdeal != lprbbi->cxIdeal ) )
1813  {
1814  lpBand->cxIdeal = lprbbi->cxIdeal;
1815  uChanged |= RBBIM_IDEALSIZE;
1816  }
1817 
1818  if( (lprbbi->fMask & RBBIM_LPARAM) &&
1819  (lpBand->lParam != lprbbi->lParam ) )
1820  {
1821  lpBand->lParam = lprbbi->lParam;
1822  uChanged |= RBBIM_LPARAM;
1823  }
1824 
1825  if( (lprbbi->fMask & RBBIM_HEADERSIZE) &&
1826  (lpBand->cxHeader != lprbbi->cxHeader ) )
1827  {
1828  lpBand->cxHeader = lprbbi->cxHeader;
1829  lpBand->fStyle |= RBBS_UNDOC_FIXEDHEADER;
1830  uChanged |= RBBIM_HEADERSIZE;
1831  }
1832  }
1833 
1834  return uChanged;
1835 }
1836 
1837 static LRESULT REBAR_EraseBkGnd (const REBAR_INFO *infoPtr, HDC hdc)
1838  /* Function: This erases the background rectangle by drawing */
1839  /* each band with its background color (or the default) and */
1840  /* draws each bands right separator if necessary. The row */
1841  /* separators are drawn on the first band of the next row. */
1842 {
1843  REBAR_BAND *lpBand;
1844  UINT i;
1845  INT oldrow;
1846  RECT cr;
1847  COLORREF old = CLR_NONE, new;
1848  HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
1849 
1850  GetClientRect (infoPtr->hwndSelf, &cr);
1851 
1852 #ifdef __REACTOS__
1853  if (theme)
1854  {
1855  if (IsThemeBackgroundPartiallyTransparent(theme, 0, 0))
1856  {
1857  DrawThemeParentBackground (infoPtr->hwndSelf, hdc, &cr);
1858  }
1859  DrawThemeBackground (theme, hdc, 0, 0, &cr, NULL);
1860  }
1861 #endif
1862 
1863  oldrow = -1;
1864  for(i=0; i<infoPtr->uNumBands; i++) {
1865  RECT rcBand;
1866  lpBand = REBAR_GetBand(infoPtr, i);
1867  if (HIDDENBAND(lpBand)) continue;
1868  translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
1869 
1870  /* draw band separator between rows */
1871  if (lpBand->iRow != oldrow) {
1872  oldrow = lpBand->iRow;
1873  if (infoPtr->dwStyle & RBS_BANDBORDERS) {
1874  RECT rcRowSep;
1875  rcRowSep = rcBand;
1876  if (infoPtr->dwStyle & CCS_VERT) {
1877  rcRowSep.right += SEP_WIDTH_SIZE;
1878  rcRowSep.bottom = infoPtr->calcSize.cx;
1879  if (theme)
1880  DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_RIGHT, NULL);
1881  else
1882  DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
1883  }
1884  else {
1885  rcRowSep.bottom += SEP_WIDTH_SIZE;
1886  rcRowSep.right = infoPtr->calcSize.cx;
1887  if (theme)
1888  DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_BOTTOM, NULL);
1889  else
1890  DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
1891  }
1892  TRACE ("drawing band separator bottom (%s)\n",
1893  wine_dbgstr_rect(&rcRowSep));
1894  }
1895  }
1896 
1897  /* draw band separator between bands in a row */
1898  if (infoPtr->dwStyle & RBS_BANDBORDERS && lpBand->rcBand.left > 0) {
1899  RECT rcSep;
1900  rcSep = rcBand;
1901  if (infoPtr->dwStyle & CCS_VERT) {
1902  rcSep.bottom = rcSep.top;
1903  rcSep.top -= SEP_WIDTH_SIZE;
1904  if (theme)
1905  DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_BOTTOM, NULL);
1906  else
1907  DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
1908  }
1909  else {
1910  rcSep.right = rcSep.left;
1911  rcSep.left -= SEP_WIDTH_SIZE;
1912  if (theme)
1913  DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_RIGHT, NULL);
1914  else
1915  DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
1916  }
1917  TRACE("drawing band separator right (%s)\n",
1918  wine_dbgstr_rect(&rcSep));
1919  }
1920 
1921  /* draw the actual background */
1922  if (lpBand->clrBack != CLR_NONE) {
1923  new = (lpBand->clrBack == CLR_DEFAULT) ? infoPtr->clrBtnFace :
1924  lpBand->clrBack;
1925 #if GLATESTING
1926  /* testing only - make background green to see it */
1927  new = RGB(0,128,0);
1928 #endif
1929  }
1930  else {
1931  /* In the absence of documentation for Rebar vs. CLR_NONE,
1932  * we will use the default BtnFace color. Note documentation
1933  * exists for Listview and Imagelist.
1934  */
1935  new = infoPtr->clrBtnFace;
1936 #if GLATESTING
1937  /* testing only - make background green to see it */
1938  new = RGB(0,128,0);
1939 #endif
1940  }
1941 
1942  if (theme)
1943  {
1944  /* When themed, the background color is ignored (but not a
1945  * background bitmap */
1946  DrawThemeBackground (theme, hdc, 0, 0, &cr, &rcBand);
1947  }
1948  else
1949  {
1950  old = SetBkColor (hdc, new);
1951  TRACE("%s background color=0x%06x, band %s\n",
1952  (lpBand->clrBack == CLR_NONE) ? "none" :
1953  ((lpBand->clrBack == CLR_DEFAULT) ? "dft" : ""),
1954  GetBkColor(hdc), wine_dbgstr_rect(&rcBand));
1955  ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rcBand, NULL, 0, 0);
1956  if (lpBand->clrBack != CLR_NONE)
1957  SetBkColor (hdc, old);
1958  }
1959  }
1960  return TRUE;
1961 }
1962 
1963 static void
1964 REBAR_InternalHitTest (const REBAR_INFO *infoPtr, const POINT *lpPt, UINT *pFlags, INT *pBand)
1965 {
1966  REBAR_BAND *lpBand;
1967  RECT rect;
1968  UINT iCount;
1969 
1970  GetClientRect (infoPtr->hwndSelf, &rect);
1971 
1972  *pFlags = RBHT_NOWHERE;
1973  if (PtInRect (&rect, *lpPt))
1974  {
1975  if (infoPtr->uNumBands == 0) {
1976  *pFlags = RBHT_NOWHERE;
1977  if (pBand)
1978  *pBand = -1;
1979  TRACE("NOWHERE\n");
1980  return;
1981  }
1982  else {
1983  /* somewhere inside */
1984  for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
1985  RECT rcBand;
1986  lpBand = REBAR_GetBand(infoPtr, iCount);
1987  translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
1988  if (HIDDENBAND(lpBand)) continue;
1989  if (PtInRect (&rcBand, *lpPt)) {
1990  if (pBand)
1991  *pBand = iCount;
1992  if (PtInRect (&lpBand->rcGripper, *lpPt)) {
1993  *pFlags = RBHT_GRABBER;
1994  TRACE("ON GRABBER %d\n", iCount);
1995  return;
1996  }
1997  else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
1998  *pFlags = RBHT_CAPTION;
1999  TRACE("ON CAPTION %d\n", iCount);
2000  return;
2001  }
2002  else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
2003  *pFlags = RBHT_CAPTION;
2004  TRACE("ON CAPTION %d\n", iCount);
2005  return;
2006  }
2007  else if (PtInRect (&lpBand->rcChild, *lpPt)) {
2008  *pFlags = RBHT_CLIENT;
2009  TRACE("ON CLIENT %d\n", iCount);
2010  return;
2011  }
2012  else if (PtInRect (&lpBand->rcChevron, *lpPt)) {
2013  *pFlags = RBHT_CHEVRON;
2014  TRACE("ON CHEVRON %d\n", iCount);
2015  return;
2016  }
2017  else {
2018  *pFlags = RBHT_NOWHERE;
2019  TRACE("NOWHERE %d\n", iCount);
2020  return;
2021  }
2022  }
2023  }
2024 
2025  *pFlags = RBHT_NOWHERE;
2026  if (pBand)
2027  *pBand = -1;
2028 
2029  TRACE("NOWHERE\n");
2030  return;
2031  }
2032  }
2033  else {
2034  *pFlags = RBHT_NOWHERE;
2035  if (pBand)
2036  *pBand = -1;
2037  TRACE("NOWHERE\n");
2038  return;
2039  }
2040 }
2041 
2042 static void
2043 REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
2044  /* Function: This will implement the functionality of a */
2045  /* Gripper drag within a row. It will not implement "out- */
2046  /* of-row" drags. (They are detected and handled in */
2047  /* REBAR_MouseMove.) */
2048 {
2049  REBAR_BAND *hitBand;
2050  INT iHitBand, iRowBegin, iRowEnd;
2051  INT movement, xBand, cxLeft = 0;
2052  BOOL shrunkBands = FALSE;
2053 
2054  iHitBand = infoPtr->iGrabbedBand;
2055  iRowBegin = get_row_begin_for_band(infoPtr, iHitBand);
2056  iRowEnd = get_row_end_for_band(infoPtr, iHitBand);
2057  hitBand = REBAR_GetBand(infoPtr, iHitBand);
2058 
2059  xBand = hitBand->rcBand.left;
2060  movement = (infoPtr->dwStyle&CCS_VERT ? ptsmove->y : ptsmove->x)
2061  - (xBand + REBAR_PRE_GRIPPER - infoPtr->ihitoffset);
2062 
2063  /* Dragging the first band in a row cannot cause shrinking */
2064  if(iHitBand != iRowBegin)
2065  {
2066  if (movement < 0) {
2067  cxLeft = REBAR_ShrinkBandsRTL(infoPtr, iRowBegin, iHitBand, -movement, TRUE);
2068 
2069  if(cxLeft < -movement)
2070  {
2071  hitBand->cxEffective += -movement - cxLeft;
2072  hitBand->cx = hitBand->cxEffective;
2073  shrunkBands = TRUE;
2074  }
2075 
2076  } else if (movement > 0) {
2077 
2078  cxLeft = movement;
2079  if (prev_visible(infoPtr, iHitBand) >= 0)
2080  cxLeft = REBAR_ShrinkBandsLTR(infoPtr, iHitBand, iRowEnd, movement, TRUE);
2081 
2082  if(cxLeft < movement)
2083  {
2084  REBAR_BAND *lpPrev = REBAR_GetBand(infoPtr, prev_visible(infoPtr, iHitBand));
2085  lpPrev->cxEffective += movement - cxLeft;
2086  lpPrev->cx = hitBand->cxEffective;
2087  shrunkBands = TRUE;
2088  }
2089 
2090  }
2091  }
2092 
2093  if(!shrunkBands)
2094  {
2095  /* It was not possible to move the band by shrinking bands.
2096  * Try relocating the band instead. */
2097  REBAR_MoveBandToRowOffset(infoPtr, iHitBand, iRowBegin,
2098  iRowEnd, xBand + movement, TRUE);
2099  }
2100 
2101  REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
2102  if (infoPtr->dwStyle & CCS_VERT)
2103  REBAR_CalcVertBand(infoPtr, 0, infoPtr->uNumBands);
2104  else
2105  REBAR_CalcHorzBand(infoPtr, 0, infoPtr->uNumBands);
2106  REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
2107 }
2108 
2109 static void
2110 REBAR_HandleUDDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
2111 {
2112  INT yOff = (infoPtr->dwStyle & CCS_VERT) ? ptsmove->x : ptsmove->y;
2113  INT iHitBand, iRowBegin, iNextRowBegin;
2114  REBAR_BAND *hitBand, *rowBeginBand;
2115 
2116  if(infoPtr->uNumBands <= 0)
2117  ERR("There are no bands in this rebar\n");
2118 
2119  /* Up/down dragging can only occur when there is more than one
2120  * band in the rebar */
2121  if(infoPtr->uNumBands <= 1)
2122  return;
2123 
2124  iHitBand = infoPtr->iGrabbedBand;
2125  hitBand = REBAR_GetBand(infoPtr, iHitBand);
2126 
2127  /* If we're taking a band that has the RBBS_BREAK style set, this
2128  * style needs to be reapplied to the band that is going to become
2129  * the new start of the row. */
2130  if((hitBand->fStyle & RBBS_BREAK) &&
2131  (iHitBand < infoPtr->uNumBands - 1))
2132  REBAR_GetBand(infoPtr, iHitBand + 1)->fStyle |= RBBS_BREAK;
2133 
2134  if(yOff < 0)
2135  {
2136  /* Place the band above the current top row */
2137  if(iHitBand==0 && (infoPtr->uNumBands==1 || REBAR_GetBand(infoPtr, 1)->fStyle&RBBS_BREAK))
2138  return;
2139  DPA_DeletePtr(infoPtr->bands, iHitBand);
2140  hitBand->fStyle &= ~RBBS_BREAK;
2141  REBAR_GetBand(infoPtr, 0)->fStyle |= RBBS_BREAK;
2142  infoPtr->iGrabbedBand = DPA_InsertPtr(
2143  infoPtr->bands, 0, hitBand);
2144  }
2145  else if(yOff > REBAR_GetBand(infoPtr, infoPtr->uNumBands - 1)->rcBand.bottom)
2146  {
2147  /* Place the band below the current bottom row */
2148  if(iHitBand == infoPtr->uNumBands-1 && hitBand->fStyle&RBBS_BREAK)
2149  return;
2150  DPA_DeletePtr(infoPtr->bands, iHitBand);
2151  hitBand->fStyle |= RBBS_BREAK;
2152  infoPtr->iGrabbedBand = DPA_InsertPtr(
2153  infoPtr->bands, infoPtr->uNumBands - 1, hitBand);
2154  }
2155  else
2156  {
2157  /* Place the band in the prexisting row the mouse is hovering over */
2158  iRowBegin = first_visible(infoPtr);
2159  while(iRowBegin < infoPtr->uNumBands)
2160  {
2161  iNextRowBegin = get_row_end_for_band(infoPtr, iRowBegin);
2162  rowBeginBand = REBAR_GetBand(infoPtr, iRowBegin);
2163  if(rowBeginBand->rcBand.bottom > yOff)
2164  {
2166  infoPtr, iHitBand, iRowBegin, iNextRowBegin,
2167  ((infoPtr->dwStyle & CCS_VERT) ? ptsmove->y : ptsmove->x)
2168  - REBAR_PRE_GRIPPER - infoPtr->ihitoffset, FALSE);
2169  break;
2170  }
2171 
2172  iRowBegin = iNextRowBegin;
2173  }
2174  }
2175 
2176  REBAR_Layout(infoPtr);
2177 }
2178 
2179 
2180 /* << REBAR_BeginDrag >> */
2181 
2182 
2183 static LRESULT
2185 {
2186  UINT uBand = (UINT)wParam;
2187  REBAR_BAND *lpBand;
2188 
2189  if (uBand >= infoPtr->uNumBands)
2190  return FALSE;
2191 
2192  TRACE("deleting band %u!\n", uBand);
2193  lpBand = REBAR_GetBand(infoPtr, uBand);
2194  REBAR_Notify_NMREBAR (infoPtr, uBand, RBN_DELETINGBAND);
2195  /* TODO: a return of 1 should probably cancel the deletion */
2196 
2197  if (lpBand->hwndChild)
2198  ShowWindow(lpBand->hwndChild, SW_HIDE);
2199  Free(lpBand->lpText);
2200  Free(lpBand);
2201 
2202  infoPtr->uNumBands--;
2203  DPA_DeletePtr(infoPtr->bands, uBand);
2204 
2205  REBAR_Notify_NMREBAR (infoPtr, -1, RBN_DELETEDBAND);
2206 
2207  /* if only 1 band left the re-validate to possible eliminate gripper */
2208  if (infoPtr->uNumBands == 1)
2209  REBAR_ValidateBand (infoPtr, REBAR_GetBand(infoPtr, 0));
2210 
2211  REBAR_Layout(infoPtr);
2212 
2213  return TRUE;
2214 }
2215 
2216 
2217 /* << REBAR_DragMove >> */
2218 /* << REBAR_EndDrag >> */
2219 
2220 
2221 static LRESULT
2222 REBAR_GetBandBorders (const REBAR_INFO *infoPtr, UINT uBand, RECT *lpRect)
2223 {
2224  REBAR_BAND *lpBand;
2225 
2226  if (!lpRect)
2227  return 0;
2228  if (uBand >= infoPtr->uNumBands)
2229  return 0;
2230 
2231  lpBand = REBAR_GetBand(infoPtr, uBand);
2232 
2233  /* FIXME - the following values were determined by experimentation */
2234  /* with the REBAR Control Spy. I have guesses as to what the 4 and */
2235  /* 1 are, but I am not sure. There doesn't seem to be any actual */
2236  /* difference in size of the control area with and without the */
2237  /* style. - GA */
2238  if (infoPtr->dwStyle & RBS_BANDBORDERS) {
2239  if (infoPtr->dwStyle & CCS_VERT) {
2240  lpRect->left = 1;
2241  lpRect->top = lpBand->cxHeader + 4;
2242  lpRect->right = 1;
2243  lpRect->bottom = 0;
2244  }
2245  else {
2246  lpRect->left = lpBand->cxHeader + 4;
2247  lpRect->top = 1;
2248  lpRect->right = 0;
2249  lpRect->bottom = 1;
2250  }
2251  }
2252  else {
2253  lpRect->left = lpBand->cxHeader;
2254  }
2255  return 0;
2256 }
2257 
2258 
2259 static inline LRESULT
2261 {
2262  TRACE("band count %u!\n", infoPtr->uNumBands);
2263 
2264  return infoPtr->uNumBands;
2265 }
2266 
2267 
2268 static LRESULT
2269 REBAR_GetBandInfoT(const REBAR_INFO *infoPtr, UINT uIndex, LPREBARBANDINFOW lprbbi, BOOL bUnicode)
2270 {
2271  REBAR_BAND *lpBand;
2272 
2273  if (!lprbbi || lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
2274  return FALSE;
2275 
2276  if (uIndex >= infoPtr->uNumBands)
2277  return FALSE;
2278 
2279  TRACE("index %u (bUnicode=%d)\n", uIndex, bUnicode);
2280 
2281  /* copy band information */
2282  lpBand = REBAR_GetBand(infoPtr, uIndex);
2283 
2284  if (lprbbi->fMask & RBBIM_STYLE)
2285  lprbbi->fStyle = lpBand->fStyle;
2286 
2287  if (lprbbi->fMask & RBBIM_COLORS) {
2288  lprbbi->clrFore = lpBand->clrFore;
2289  lprbbi->clrBack = lpBand->clrBack;
2290  if (lprbbi->clrBack == CLR_DEFAULT)
2291  lprbbi->clrBack = infoPtr->clrBtnFace;
2292  }
2293 
2294  if (lprbbi->fMask & RBBIM_TEXT) {
2295  if (bUnicode)
2296  Str_GetPtrW(lpBand->lpText, lprbbi->lpText, lprbbi->cch);
2297  else
2298  Str_GetPtrWtoA(lpBand->lpText, (LPSTR)lprbbi->lpText, lprbbi->cch);
2299  }
2300 
2301  if (lprbbi->fMask & RBBIM_IMAGE)
2302  lprbbi->iImage = lpBand->iImage;
2303 
2304  if (lprbbi->fMask & RBBIM_CHILD)
2305  lprbbi->hwndChild = lpBand->hwndChild;
2306 
2307  if (lprbbi->fMask & RBBIM_CHILDSIZE) {
2308  lprbbi->cxMinChild = lpBand->cxMinChild;
2309  lprbbi->cyMinChild = lpBand->cyMinChild;
2310  /* to make tests pass we follow Windows' behaviour and allow reading these fields only
2311  * for RBBS_VARIABLEHEIGHTS bands */
2312  if (lprbbi->cbSize >= REBARBANDINFOW_V6_SIZE && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
2313  lprbbi->cyChild = lpBand->cyChild;
2314  lprbbi->cyMaxChild = lpBand->cyMaxChild;
2315  lprbbi->cyIntegral = lpBand->cyIntegral;
2316  }
2317  }
2318 
2319  if (lprbbi->fMask & RBBIM_SIZE)
2320  lprbbi->cx = lpBand->cx;
2321 
2322  if (lprbbi->fMask & RBBIM_BACKGROUND)
2323  lprbbi->hbmBack = lpBand->hbmBack;
2324 
2325  if (lprbbi->fMask & RBBIM_ID)
2326  lprbbi->wID = lpBand->wID;
2327 
2328  /* check for additional data */
2329  if (lprbbi->cbSize >= REBARBANDINFOW_V6_SIZE) {
2330  if (lprbbi->fMask & RBBIM_IDEALSIZE)
2331  lprbbi->cxIdeal = lpBand->cxIdeal;
2332 
2333  if (lprbbi->fMask & RBBIM_LPARAM)
2334  lprbbi->lParam = lpBand->lParam;
2335 
2336  if (lprbbi->fMask & RBBIM_HEADERSIZE)
2337  lprbbi->cxHeader = lpBand->cxHeader;
2338  }
2339 
2340  REBAR_DumpBandInfo(lprbbi);
2341 
2342  return TRUE;
2343 }
2344 
2345 
2346 static LRESULT
2348 {
2349  INT nHeight;
2350 
2351  nHeight = infoPtr->calcSize.cy;
2352 
2353  TRACE("height = %d\n", nHeight);
2354 
2355  return nHeight;
2356 }
2357 
2358 
2359 static LRESULT
2360 REBAR_GetBarInfo (const REBAR_INFO *infoPtr, LPREBARINFO lpInfo)
2361 {
2362  if (!lpInfo || lpInfo->cbSize < sizeof (REBARINFO))
2363  return FALSE;
2364 
2365  TRACE("getting bar info!\n");
2366 
2367  if (infoPtr->himl) {
2368  lpInfo->himl = infoPtr->himl;
2369  lpInfo->fMask |= RBIM_IMAGELIST;
2370  }
2371 
2372  return TRUE;
2373 }
2374 
2375 
2376 static inline LRESULT
2378 {
2379  COLORREF clr = infoPtr->clrBk;
2380 
2381  if (clr == CLR_DEFAULT)
2382  clr = infoPtr->clrBtnFace;
2383 
2384  TRACE("background color 0x%06x!\n", clr);
2385 
2386  return clr;
2387 }
2388 
2389 
2390 /* << REBAR_GetColorScheme >> */
2391 /* << REBAR_GetDropTarget >> */
2392 
2393 
2394 static LRESULT
2396 {
2397  FIXME("empty stub!\n");
2398 
2399  return 0;
2400 }
2401 
2402 
2403 static LRESULT
2404 REBAR_GetRect (const REBAR_INFO *infoPtr, INT iBand, RECT *lprc)
2405 {
2406  REBAR_BAND *lpBand;
2407 
2408  if (iBand < 0 || iBand >= infoPtr->uNumBands)
2409  return FALSE;
2410  if (!lprc)
2411  return FALSE;
2412 
2413  lpBand = REBAR_GetBand(infoPtr, iBand);
2414  /* For CCS_VERT the coordinates will be swapped - like on Windows */
2415  *lprc = lpBand->rcBand;
2416 
2417  TRACE("band %d, (%s)\n", iBand, wine_dbgstr_rect(lprc));
2418 
2419  return TRUE;
2420 }
2421 
2422 
2423 static inline LRESULT
2425 {
2426  TRACE("%u\n", infoPtr->uNumRows);
2427 
2428  return infoPtr->uNumRows;
2429 }
2430 
2431 
2432 static LRESULT
2433 REBAR_GetRowHeight (const REBAR_INFO *infoPtr, INT iRow)
2434 {
2435  int j = 0, ret = 0;
2436  UINT i;
2437  REBAR_BAND *lpBand;
2438 
2439  for (i=0; i<infoPtr->uNumBands; i++) {
2440  lpBand = REBAR_GetBand(infoPtr, i);
2441  if (HIDDENBAND(lpBand)) continue;
2442  if (lpBand->iRow != iRow) continue;
2443  j = lpBand->rcBand.bottom - lpBand->rcBand.top;
2444  if (j > ret) ret = j;
2445  }
2446 
2447  TRACE("row %d, height %d\n", iRow, ret);
2448 
2449  return ret;
2450 }
2451 
2452 
2453 static inline LRESULT
2455 {
2456  TRACE("text color 0x%06x!\n", infoPtr->clrText);
2457 
2458  return infoPtr->clrText;
2459 }
2460 
2461 
2462 static inline LRESULT
2464 {
2465  return (LRESULT)infoPtr->hwndToolTip;
2466 }
2467 
2468 
2469 static inline LRESULT
2471 {
2472  TRACE("%s hwnd=%p\n",
2473  infoPtr->bUnicode ? "TRUE" : "FALSE", infoPtr->hwndSelf);
2474 
2475  return infoPtr->bUnicode;
2476 }
2477 
2478 
2479 static inline LRESULT
2481 {
2482  TRACE("version %d\n", infoPtr->iVersion);
2483  return infoPtr->iVersion;
2484 }
2485 
2486 
2487 static LRESULT
2488 REBAR_HitTest (const REBAR_INFO *infoPtr, LPRBHITTESTINFO lprbht)
2489 {
2490  if (!lprbht)
2491  return -1;
2492 
2493  REBAR_InternalHitTest (infoPtr, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
2494 
2495  return lprbht->iBand;
2496 }
2497 
2498 
2499 static LRESULT
2500 REBAR_IdToIndex (const REBAR_INFO *infoPtr, UINT uId)
2501 {
2502  UINT i;
2503 
2504  if (infoPtr->uNumBands < 1)
2505  return -1;
2506 
2507  for (i = 0; i < infoPtr->uNumBands; i++) {
2508  if (REBAR_GetBand(infoPtr, i)->wID == uId) {
2509  TRACE("id %u is band %u found!\n", uId, i);
2510  return i;
2511  }
2512  }
2513 
2514  TRACE("id %u is not found\n", uId);
2515  return -1;
2516 }
2517 
2518 
2519 static LRESULT
2520 REBAR_InsertBandT(REBAR_INFO *infoPtr, INT iIndex, const REBARBANDINFOW *lprbbi, BOOL bUnicode)
2521 {
2522  REBAR_BAND *lpBand;
2523 
2524  if (!lprbbi || lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
2525  return FALSE;
2526 
2527  /* trace the index as signed to see the -1 */
2528  TRACE("insert band at %d (bUnicode=%d)!\n", iIndex, bUnicode);
2529  REBAR_DumpBandInfo(lprbbi);
2530 
2531  if (!(lpBand = Alloc(sizeof(REBAR_BAND)))) return FALSE;
2532  if ((iIndex == -1) || (iIndex > infoPtr->uNumBands))
2533  iIndex = infoPtr->uNumBands;
2534  if (DPA_InsertPtr(infoPtr->bands, iIndex, lpBand) == -1)
2535  {
2536  Free(lpBand);
2537  return FALSE;
2538  }
2539  infoPtr->uNumBands++;
2540 
2541  TRACE("index %d!\n", iIndex);
2542 
2543  /* initialize band */
2544  memset(lpBand, 0, sizeof(*lpBand));
2545  lpBand->clrFore = infoPtr->clrText == CLR_NONE ? infoPtr->clrBtnText :
2546  infoPtr->clrText;
2547  lpBand->clrBack = infoPtr->clrBk == CLR_NONE ? infoPtr->clrBtnFace :
2548  infoPtr->clrBk;
2549  lpBand->iImage = -1;
2550 
2551  REBAR_CommonSetupBand(infoPtr->hwndSelf, lprbbi, lpBand);
2552 
2553  /* Make sure the defaults for these are correct */
2554  if (lprbbi->cbSize < REBARBANDINFOA_V6_SIZE || !(lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
2555  lpBand->cyChild = lpBand->cyMinChild;
2556  lpBand->cyMaxChild = 0x7fffffff;
2557  lpBand->cyIntegral = 0;
2558  }
2559 
2560  if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2561  if (bUnicode)
2562  Str_SetPtrW(&lpBand->lpText, lprbbi->lpText);
2563  else
2564  Str_SetPtrAtoW(&lpBand->lpText, (LPSTR)lprbbi->lpText);
2565  }
2566 
2567  REBAR_ValidateBand (infoPtr, lpBand);
2568  /* On insert of second band, revalidate band 1 to possible add gripper */
2569  if (infoPtr->uNumBands == 2)
2570  REBAR_ValidateBand (infoPtr, REBAR_GetBand(infoPtr, 0));
2571 
2572  REBAR_DumpBand (infoPtr);
2573 
2574  REBAR_Layout(infoPtr);
2575  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
2576 
2577  return TRUE;
2578 }
2579 
2580 
2581 static LRESULT
2583 {
2584  REBAR_BAND *lpBand;
2585  int iRowBegin, iRowEnd;
2586  int cxDesired, extra, extraOrig;
2587  int cxIdealBand;
2588 
2589  /* Validate */
2590  if (infoPtr->uNumBands == 0 || iBand < 0 || iBand >= infoPtr->uNumBands) {
2591  /* error !!! */
2592  ERR("Illegal MaximizeBand, requested=%d, current band count=%d\n",
2593  iBand, infoPtr->uNumBands);
2594  return FALSE;
2595  }
2596 
2597  lpBand = REBAR_GetBand(infoPtr, iBand);
2598 
2599  if (lpBand->fStyle & RBBS_HIDDEN)
2600  {
2601  /* Windows is buggy and creates a hole */
2602  WARN("Ignoring maximize request on a hidden band (%d)\n", iBand);
2603  return FALSE;
2604  }
2605 
2606  cxIdealBand = lpBand->cxIdeal + lpBand->cxHeader + REBAR_POST_CHILD;
2607  if (lParam && (lpBand->cxEffective < cxIdealBand))
2608  cxDesired = cxIdealBand;
2609  else
2610  cxDesired = infoPtr->calcSize.cx;
2611 
2612  iRowBegin = get_row_begin_for_band(infoPtr, iBand);
2613  iRowEnd = get_row_end_for_band(infoPtr, iBand);
2614  extraOrig = extra = cxDesired - lpBand->cxEffective;
2615  if (extra > 0)
2616  extra = REBAR_ShrinkBandsRTL(infoPtr, iRowBegin, iBand, extra, TRUE);
2617  if (extra > 0)
2618  extra = REBAR_ShrinkBandsLTR(infoPtr, next_visible(infoPtr, iBand), iRowEnd, extra, TRUE);
2619  lpBand->cxEffective += extraOrig - extra;
2620  lpBand->cx = lpBand->cxEffective;
2621  TRACE("(%d, %ld): Wanted size %d, obtained %d (shrink %d, %d)\n", iBand, lParam, cxDesired, lpBand->cx, extraOrig, extra);
2622  REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
2623 
2624  if (infoPtr->dwStyle & CCS_VERT)
2625  REBAR_CalcVertBand(infoPtr, iRowBegin, iRowEnd);
2626  else
2627  REBAR_CalcHorzBand(infoPtr, iRowBegin, iRowEnd);
2628  REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
2629  return TRUE;
2630 
2631 }
2632 
2633 
2634 static LRESULT
2635 REBAR_MinimizeBand (const REBAR_INFO *infoPtr, INT iBand)
2636 {
2637  REBAR_BAND *lpBand;
2638  int iPrev, iRowBegin, iRowEnd;
2639 
2640  /* A "minimize" band is equivalent to "dragging" the gripper
2641  * of than band to the right till the band is only the size
2642  * of the cxHeader.
2643  */
2644 
2645  /* Validate */
2646  if (infoPtr->uNumBands == 0 || iBand < 0 || iBand >= infoPtr->uNumBands) {
2647  /* error !!! */
2648  ERR("Illegal MinimizeBand, requested=%d, current band count=%d\n",
2649  iBand, infoPtr->uNumBands);
2650  return FALSE;
2651  }
2652 
2653  /* compute amount of movement and validate */
2654  lpBand = REBAR_GetBand(infoPtr, iBand);
2655 
2656  if (lpBand->fStyle & RBBS_HIDDEN)
2657  {
2658  /* Windows is buggy and creates a hole/overlap */
2659  WARN("Ignoring minimize request on a hidden band (%d)\n", iBand);
2660  return FALSE;
2661  }
2662 
2663  iPrev = prev_visible(infoPtr, iBand);
2664  /* if first band in row */
2665  if (iPrev < 0 || REBAR_GetBand(infoPtr, iPrev)->iRow != lpBand->iRow) {
2666  int iNext = next_visible(infoPtr, iBand);
2667  if (iNext < infoPtr->uNumBands && REBAR_GetBand(infoPtr, iNext)->iRow == lpBand->iRow) {
2668  TRACE("(%d): Minimizing the first band in row is by maximizing the second\n", iBand);
2669  REBAR_MaximizeBand(infoPtr, iNext, FALSE);
2670  }
2671  else
2672  TRACE("(%d): Only one band in row - nothing to do\n", iBand);
2673  return TRUE;
2674  }
2675 
2676  REBAR_GetBand(infoPtr, iPrev)->cxEffective += lpBand->cxEffective - lpBand->cxMinBand;
2677  REBAR_GetBand(infoPtr, iPrev)->cx = REBAR_GetBand(infoPtr, iPrev)->cxEffective;
2678  lpBand->cx = lpBand->cxEffective = lpBand->cxMinBand;
2679 
2680  iRowBegin = get_row_begin_for_band(infoPtr, iBand);
2681  iRowEnd = get_row_end_for_band(infoPtr, iBand);
2682  REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
2683 
2684  if (infoPtr->dwStyle & CCS_VERT)
2685  REBAR_CalcVertBand(infoPtr, iRowBegin, iRowEnd);
2686  else
2687  REBAR_CalcHorzBand(infoPtr, iRowBegin, iRowEnd);
2688  REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
2689  return FALSE;
2690 }
2691 
2692 
2693 static LRESULT
2694 REBAR_MoveBand (REBAR_INFO *infoPtr, INT iFrom, INT iTo)
2695 {
2696  REBAR_BAND *lpBand;
2697 
2698  /* Validate */
2699  if ((infoPtr->uNumBands == 0) ||
2700  (iFrom < 0) || iFrom >= infoPtr->uNumBands ||
2701  (iTo < 0) || iTo >= infoPtr->uNumBands) {
2702  /* error !!! */
2703  ERR("Illegal MoveBand, from=%d, to=%d, current band count=%d\n",
2704  iFrom, iTo, infoPtr->uNumBands);
2705  return FALSE;
2706  }
2707 
2708  lpBand = REBAR_GetBand(infoPtr, iFrom);
2709  DPA_DeletePtr(infoPtr->bands, iFrom);
2710  DPA_InsertPtr(infoPtr->bands, iTo, lpBand);
2711 
2712  TRACE("moved band %d to index %d\n", iFrom, iTo);
2713  REBAR_DumpBand (infoPtr);
2714 
2715  /* **************************************************** */
2716  /* */
2717  /* We do not do a REBAR_Layout here because the native */
2718  /* control does not do that. The actual layout and */
2719  /* repaint is done by the *next* real action, ex.: */
2720  /* RB_INSERTBAND, RB_DELETEBAND, RB_SIZETORECT, etc. */
2721  /* */
2722  /* **************************************************** */
2723 
2724  return TRUE;
2725 }
2726 
2727 
2728 /* return TRUE if two strings are different */
2729 static BOOL
2731 {
2732  return ( (a && !b) || (b && !a) || (a && b && lstrcmpW(a, b) ) );
2733 }
2734 
2735 static LRESULT
2736 REBAR_SetBandInfoT(REBAR_INFO *infoPtr, INT iBand, const REBARBANDINFOW *lprbbi, BOOL bUnicode)
2737 {
2738  REBAR_BAND *lpBand;
2739  UINT uChanged;
2740 
2741  if (!lprbbi || lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
2742  return FALSE;
2743 
2744  if (iBand >= infoPtr->uNumBands)
2745  return FALSE;
2746 
2747  TRACE("index %d\n", iBand);
2748  REBAR_DumpBandInfo (lprbbi);
2749 
2750  /* set band information */
2751  lpBand = REBAR_GetBand(infoPtr, iBand);
2752 
2753  uChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand);
2754  if (lprbbi->fMask & RBBIM_TEXT) {
2755  LPWSTR wstr = NULL;
2756  if (bUnicode)
2757  Str_SetPtrW(&wstr, lprbbi->lpText);
2758  else
2759  Str_SetPtrAtoW(&wstr, (LPSTR)lprbbi->lpText);
2760 
2761  if (REBAR_strdifW(wstr, lpBand->lpText)) {
2762  Free(lpBand->lpText);
2763  lpBand->lpText = wstr;
2764  uChanged |= RBBIM_TEXT;
2765  }
2766  else
2767  Free(wstr);
2768  }
2769 
2770  REBAR_ValidateBand (infoPtr, lpBand);
2771 
2772  REBAR_DumpBand (infoPtr);
2773 
2774  if (uChanged & (RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE | RBBIM_IMAGE)) {
2775  REBAR_Layout(infoPtr);
2776  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
2777  }
2778 
2779  return TRUE;
2780 }
2781 
2782 
2783 static LRESULT
2784 REBAR_SetBarInfo (REBAR_INFO *infoPtr, const REBARINFO *lpInfo)
2785 {
2786  REBAR_BAND *lpBand;
2787  UINT i;
2788 
2789  if (!lpInfo || lpInfo->cbSize < sizeof (REBARINFO))
2790  return FALSE;
2791 
2792  TRACE("setting bar info!\n");
2793 
2794  if (lpInfo->fMask & RBIM_IMAGELIST) {
2795  infoPtr->himl = lpInfo->himl;
2796  if (infoPtr->himl) {
2797  INT cx, cy;
2798  ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
2799  infoPtr->imageSize.cx = cx;
2800  infoPtr->imageSize.cy = cy;
2801  }
2802  else {
2803  infoPtr->imageSize.cx = 0;
2804  infoPtr->imageSize.cy = 0;
2805  }
2806  TRACE("new image cx=%d, cy=%d\n", infoPtr->imageSize.cx,
2807  infoPtr->imageSize.cy);
2808  }
2809 
2810  /* revalidate all bands to reset flags for images in headers of bands */
2811  for (i=0; i<infoPtr->uNumBands; i++) {
2812  lpBand = REBAR_GetBand(infoPtr, i);
2813  REBAR_ValidateBand (infoPtr, lpBand);
2814  }
2815 
2816  return TRUE;
2817 }
2818 
2819 
2820 static LRESULT
2822 {
2823  COLORREF clrTemp;
2824 
2825  clrTemp = infoPtr->clrBk;
2826  infoPtr->clrBk = clr;
2827 
2828  TRACE("background color 0x%06x!\n", infoPtr->clrBk);
2829 
2830  return clrTemp;
2831 }
2832 
2833 
2834 /* << REBAR_SetColorScheme >> */
2835 /* << REBAR_SetPalette >> */
2836 
2837 
2838 static LRESULT
2840 {
2841  HWND hwndTemp = infoPtr->hwndNotify;
2842 
2843  infoPtr->hwndNotify = parent;
2844 
2845  return (LRESULT)hwndTemp;
2846 }
2847 
2848 
2849 static LRESULT
2851 {
2852  COLORREF clrTemp;
2853 
2854  clrTemp = infoPtr->clrText;
2855  infoPtr->clrText = clr;
2856 
2857  TRACE("text color 0x%06x!\n", infoPtr->clrText);
2858 
2859  return clrTemp;
2860 }
2861 
2862 
2863 /* << REBAR_SetTooltips >> */
2864 
2865 
2866 static inline LRESULT
2868 {
2869  BOOL bTemp = infoPtr->bUnicode;
2870 
2871  TRACE("to %s hwnd=%p, was %s\n",
2872  unicode ? "TRUE" : "FALSE", infoPtr->hwndSelf,
2873  (bTemp) ? "TRUE" : "FALSE");
2874 
2875  infoPtr->bUnicode = unicode;
2876 
2877  return bTemp;
2878 }
2879 
2880 
2881 static LRESULT
2882 REBAR_SetVersion (REBAR_INFO *infoPtr, INT iVersion)
2883 {
2884  INT iOldVersion = infoPtr->iVersion;
2885 
2886  if (iVersion > COMCTL32_VERSION)
2887  return -1;
2888 
2889  infoPtr->iVersion = iVersion;
2890 
2891  TRACE("new version %d\n", iVersion);
2892 
2893  return iOldVersion;
2894 }
2895 
2896 
2897 static LRESULT
2898 REBAR_ShowBand (REBAR_INFO *infoPtr, INT iBand, BOOL show)
2899 {
2900  REBAR_BAND *lpBand;
2901 
2902  if (iBand < 0 || iBand >= infoPtr->uNumBands)
2903  return FALSE;
2904 
2905  lpBand = REBAR_GetBand(infoPtr, iBand);
2906 
2907  if (show) {
2908  TRACE("show band %d\n", iBand);
2909  lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
2910  if (IsWindow (lpBand->hwndChild))
2911  ShowWindow (lpBand->hwndChild, SW_SHOW);
2912  }
2913  else {
2914  TRACE("hide band %d\n", iBand);
2915  lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
2916  if (IsWindow (lpBand->hwndChild))
2917  ShowWindow (lpBand->hwndChild, SW_HIDE);
2918  }
2919 
2920  REBAR_Layout(infoPtr);
2921  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
2922 
2923  return TRUE;
2924 }
2925 
2926 
2927 static LRESULT
2928 #ifdef __REACTOS__
2929 REBAR_SizeToRect (REBAR_INFO *infoPtr, WPARAM flags, RECT *lpRect)
2930 #else
2931 REBAR_SizeToRect (REBAR_INFO *infoPtr, const RECT *lpRect)
2932 #endif
2933 {
2934  if (!lpRect) return FALSE;
2935 
2936  TRACE("[%s]\n", wine_dbgstr_rect(lpRect));
2937  REBAR_SizeToHeight(infoPtr, get_rect_cy(infoPtr, lpRect));
2938 
2939 #ifdef __REACTOS__
2940  /* Note that this undocumented flag is available on comctl32 v6 or later */
2941  if ((flags & RBSTR_CHANGERECT) != 0)
2942  {
2943  RECT rcRebar;
2944  GetClientRect(infoPtr->hwndSelf, &rcRebar);
2945  lpRect->bottom = lpRect->top + (rcRebar.bottom - rcRebar.top);
2946  }
2947 #endif
2948  return TRUE;
2949 }
2950 
2951 
2952 
2953 static LRESULT
2955 {
2956  RECT wnrc1, clrc1;
2957 
2958  if (TRACE_ON(rebar)) {
2959  GetWindowRect(infoPtr->hwndSelf, &wnrc1);
2960  GetClientRect(infoPtr->hwndSelf, &clrc1);
2961  TRACE("window=(%s) client=(%s) cs=(%d,%d %dx%d)\n",
2962  wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1),
2963  cs->x, cs->y, cs->cx, cs->cy);
2964  }
2965 
2966  TRACE("created!\n");
2967 
2968  if (OpenThemeData (infoPtr->hwndSelf, themeClass))
2969  {
2970  /* native seems to clear WS_BORDER when themed */
2971  infoPtr->dwStyle &= ~WS_BORDER;
2972  }
2973 
2974  return 0;
2975 }
2976 
2977 
2978 static LRESULT
2980 {
2981  REBAR_BAND *lpBand;
2982  UINT i;
2983 
2984  /* clean up each band */
2985  for (i = 0; i < infoPtr->uNumBands; i++) {
2986  lpBand = REBAR_GetBand(infoPtr, i);
2987 
2988  /* delete text strings */
2989  Free (lpBand->lpText);
2990  lpBand->lpText = NULL;
2991  /* destroy child window */
2992  DestroyWindow (lpBand->hwndChild);
2993  Free (lpBand);
2994  }
2995 
2996  /* free band array */
2997  DPA_Destroy (infoPtr->bands);
2998  infoPtr->bands = NULL;
2999 
3000  DestroyCursor (infoPtr->hcurArrow);
3001  DestroyCursor (infoPtr->hcurHorz);
3002  DestroyCursor (infoPtr->hcurVert);
3003  DestroyCursor (infoPtr->hcurDrag);
3004  if (infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont);
3005  SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0);
3006 
3007  CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
3008 
3009  /* free rebar info data */
3010  Free (infoPtr);
3011  TRACE("destroyed!\n");
3012  return 0;
3013 }
3014 
3015 static LRESULT
3016 REBAR_GetFont (const REBAR_INFO *infoPtr)
3017 {
3018  return (LRESULT)infoPtr->hFont;
3019 }
3020 
3021 static LRESULT
3023 {
3024  if (uBand < infoPtr->uNumBands)
3025  {
3026  NMREBARCHEVRON nmrbc;
3027  REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, uBand);
3028 
3029  TRACE("Pressed chevron on band %u\n", uBand);
3030 
3031  /* redraw chevron in pushed state */
3032  lpBand->fDraw |= DRAW_CHEVRONPUSHED;
3033  RedrawWindow(infoPtr->hwndSelf, &lpBand->rcChevron,0,
3035 
3036  /* notify app so it can display a popup menu or whatever */
3037  nmrbc.uBand = uBand;
3038  nmrbc.wID = lpBand->wID;
3039  nmrbc.lParam = lpBand->lParam;
3040  nmrbc.rc = lpBand->rcChevron;
3041  nmrbc.lParamNM = lParam;
3042  REBAR_Notify((NMHDR*)&nmrbc, infoPtr, RBN_CHEVRONPUSHED);
3043 
3044  /* redraw chevron in previous state */
3045  lpBand->fDraw &= ~DRAW_CHEVRONPUSHED;
3046  InvalidateRect(infoPtr->hwndSelf, &lpBand->rcChevron, TRUE);
3047 
3048  return TRUE;
3049  }
3050  return FALSE;
3051 }
3052 
3053 static LRESULT
3055 {
3056  UINT htFlags;
3057  INT iHitBand;
3058  POINT ptMouseDown;
3059  ptMouseDown.x = (short)LOWORD(lParam);
3060  ptMouseDown.y = (short)HIWORD(lParam);
3061 
3062  REBAR_InternalHitTest(infoPtr, &ptMouseDown, &htFlags, &iHitBand);
3063 
3064  if (htFlags == RBHT_CHEVRON)
3065  {
3066  REBAR_PushChevron(infoPtr, iHitBand, 0);
3067  }
3068  else if (htFlags == RBHT_GRABBER || htFlags == RBHT_CAPTION)
3069  {
3070  REBAR_BAND *lpBand;
3071 
3072  TRACE("Starting drag\n");
3073 
3074  lpBand = REBAR_GetBand(infoPtr, iHitBand);
3075 
3076  SetCapture (infoPtr->hwndSelf);
3077  infoPtr->iGrabbedBand = iHitBand;
3078 
3079  /* save off the LOWORD and HIWORD of lParam as initial x,y */
3080  infoPtr->dragStart.x = (short)LOWORD(lParam);
3081  infoPtr->dragStart.y = (short)HIWORD(lParam);
3082  infoPtr->dragNow = infoPtr->dragStart;
3083  if (infoPtr->dwStyle & CCS_VERT)
3084  infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.left + REBAR_PRE_GRIPPER);
3085  else
3086  infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left + REBAR_PRE_GRIPPER);
3087  }
3088  return 0;
3089 }
3090 
3091 static LRESULT
3093 {
3094  if (infoPtr->iGrabbedBand >= 0)
3095  {
3096  NMHDR layout;
3097  RECT rect;
3098 
3099  infoPtr->dragStart.x = 0;
3100  infoPtr->dragStart.y = 0;
3101  infoPtr->dragNow = infoPtr->dragStart;
3102 
3103  ReleaseCapture ();
3104 
3105  if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
3107  REBAR_Notify_NMREBAR (infoPtr, infoPtr->iGrabbedBand, RBN_ENDDRAG);
3108  infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
3109  }
3110 
3111  infoPtr->iGrabbedBand = -1;
3112 
3113  GetClientRect(infoPtr->hwndSelf, &rect);
3114  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
3115  }
3116 
3117  return 0;
3118 }
3119 
3120 static LRESULT
3122 {
3123  if (infoPtr->ichevronhotBand >= 0)
3124  {
3125  REBAR_BAND *lpChevronBand = REBAR_GetBand(infoPtr, infoPtr->ichevronhotBand);
3126  if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
3127  {
3128  lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
3129  InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
3130  }
3131  }
3132  infoPtr->iOldBand = -1;
3133  infoPtr->ichevronhotBand = -2;
3134 
3135  return TRUE;
3136 }
3137 
3138 static LRESULT
3140 {
3141  REBAR_BAND *lpChevronBand;
3142  POINT ptMove;
3143 
3144  ptMove.x = (short)LOWORD(lParam);
3145  ptMove.y = (short)HIWORD(lParam);
3146 
3147  /* if we are currently dragging a band */
3148  if (infoPtr->iGrabbedBand >= 0)
3149  {
3150  REBAR_BAND *band;
3151  int yPtMove = (infoPtr->dwStyle & CCS_VERT ? ptMove.x : ptMove.y);
3152 
3153  if (GetCapture() != infoPtr->hwndSelf)
3154  ERR("We are dragging but haven't got capture?!?\n");
3155 
3156  band = REBAR_GetBand(infoPtr, infoPtr->iGrabbedBand);
3157 
3158  /* if mouse did not move much, exit */
3159  if ((abs(ptMove.x - infoPtr->dragNow.x) <= mindragx) &&
3160  (abs(ptMove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
3161 
3162  /* on first significant mouse movement, issue notify */
3163  if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
3164  if (REBAR_Notify_NMREBAR (infoPtr, -1, RBN_BEGINDRAG)) {
3165  /* Notify returned TRUE - abort drag */
3166  infoPtr->dragStart.x = 0;
3167  infoPtr->dragStart.y = 0;
3168  infoPtr->dragNow = infoPtr->dragStart;
3169  infoPtr->iGrabbedBand = -1;
3170  ReleaseCapture ();
3171  return 0;
3172  }
3173  infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
3174  }
3175 
3176  /* Test for valid drag case - must not be first band in row */
3177  if ((yPtMove < band->rcBand.top) ||
3178  (yPtMove > band->rcBand.bottom)) {
3179  REBAR_HandleUDDrag (infoPtr, &ptMove);
3180  }
3181  else {
3182  REBAR_HandleLRDrag (infoPtr, &ptMove);
3183  }
3184  }
3185  else
3186  {
3187  INT iHitBand;
3188  UINT htFlags;
3189  TRACKMOUSEEVENT trackinfo;
3190 
3191  REBAR_InternalHitTest(infoPtr, &ptMove, &htFlags, &iHitBand);
3192 
3193  if (infoPtr->iOldBand >= 0 && infoPtr->iOldBand == infoPtr->ichevronhotBand)
3194  {
3195  lpChevronBand = REBAR_GetBand(infoPtr, infoPtr->ichevronhotBand);
3196  if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
3197  {
3198  lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
3199  InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
3200  }
3201  infoPtr->ichevronhotBand = -2;
3202  }
3203 
3204  if (htFlags == RBHT_CHEVRON)
3205  {
3206  /* fill in the TRACKMOUSEEVENT struct */
3207  trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3208  trackinfo.dwFlags = TME_QUERY;
3209  trackinfo.hwndTrack = infoPtr->hwndSelf;
3210  trackinfo.dwHoverTime = 0;
3211 
3212  /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3213  _TrackMouseEvent(&trackinfo);
3214 
3215  /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
3216  if(!(trackinfo.dwFlags & TME_LEAVE))
3217  {
3218  trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3219 
3220  /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
3221  /* and can properly deactivate the hot chevron */
3222  _TrackMouseEvent(&trackinfo);
3223  }
3224 
3225  lpChevronBand = REBAR_GetBand(infoPtr, iHitBand);
3226  if (!(lpChevronBand->fDraw & DRAW_CHEVRONHOT))
3227  {
3228  lpChevronBand->fDraw |= DRAW_CHEVRONHOT;
3229  InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
3230  infoPtr->ichevronhotBand = iHitBand;
3231  }
3232  }
3233  infoPtr->iOldBand = iHitBand;
3234  }
3235 
3236  return 0;
3237 }
3238 
3239 
3240 static inline LRESULT
3242 {
3243  HTHEME theme;
3244 
3245  if (infoPtr->dwStyle & WS_BORDER) {
3246  rect->left = min(rect->left + GetSystemMetrics(SM_CXEDGE), rect->right);
3247  rect->right = max(rect->right - GetSystemMetrics(SM_CXEDGE), rect->left);
3248  rect->top = min(rect->top + GetSystemMetrics(SM_CYEDGE), rect->bottom);
3249  rect->bottom = max(rect->bottom - GetSystemMetrics(SM_CYEDGE), rect->top);
3250  }
3251  else if ((theme = GetWindowTheme (infoPtr->hwndSelf)))
3252  {
3253  /* FIXME: should use GetThemeInt */
3254 #ifdef __REACTOS__
3255  rect->top = (rect->top + 1 < rect->bottom) ? rect->top : rect->bottom;
3256 #else
3257  rect->top = min(rect->top + 1, rect->bottom);
3258 #endif
3259  }
3260  TRACE("new client=(%s)\n", wine_dbgstr_rect(rect));
3261  return 0;
3262 }
3263 
3264 
3265 static LRESULT
3267 {
3268  REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
3269  RECT wnrc1, clrc1;
3270  NONCLIENTMETRICSW ncm;
3271  HFONT tfont;
3272 
3273  if (infoPtr) {
3274  ERR("Strange info structure pointer *not* NULL\n");
3275  return FALSE;
3276  }
3277 
3278  if (TRACE_ON(rebar)) {
3279  GetWindowRect(hwnd, &wnrc1);
3280  GetClientRect(hwnd, &clrc1);
3281  TRACE("window=(%s) client=(%s) cs=(%d,%d %dx%d)\n",
3282  wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1),
3283  cs->x, cs->y, cs->cx, cs->cy);
3284  }
3285 
3286  /* allocate memory for info structure */
3287  infoPtr = Alloc (sizeof(REBAR_INFO));
3288  SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
3289 
3290  /* initialize info structure - initial values are 0 */
3291  infoPtr->clrBk = CLR_NONE;
3292  infoPtr->clrText = CLR_NONE;
3293  infoPtr->clrBtnText = comctl32_color.clrBtnText;
3294  infoPtr->clrBtnFace = comctl32_color.clrBtnFace;
3295  infoPtr->iOldBand = -1;
3296  infoPtr->ichevronhotBand = -2;
3297  infoPtr->iGrabbedBand = -1;
3298  infoPtr->hwndSelf = hwnd;
3299  infoPtr->DoRedraw = TRUE;
3300  infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW);
3301  infoPtr->hcurHorz = LoadCursorW (0, (LPWSTR)IDC_SIZEWE);
3302  infoPtr->hcurVert = LoadCursorW (0, (LPWSTR)IDC_SIZENS);
3303  infoPtr->hcurDrag = LoadCursorW (0, (LPWSTR)IDC_SIZE);
3304  infoPtr->fStatus = 0;
3305  infoPtr->hFont = GetStockObject (SYSTEM_FONT);
3306  infoPtr->bands = DPA_Create(8);
3307 
3308  /* issue WM_NOTIFYFORMAT to get unicode status of parent */
3309  REBAR_NotifyFormat(infoPtr, NF_REQUERY);
3310 
3311  /* Stow away the original style */
3312  infoPtr->orgStyle = cs->style;
3313  /* add necessary styles to the requested styles */
3314  infoPtr->dwStyle = cs->style | WS_VISIBLE;
3315  if ((infoPtr->dwStyle & CCS_LAYOUT_MASK) == 0)
3316  infoPtr->dwStyle |= CCS_TOP;
3317  SetWindowLongW (hwnd, GWL_STYLE, infoPtr->dwStyle);
3318 
3319  /* get font handle for Caption Font */
3320  ncm.cbSize = sizeof(ncm);
3321  SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
3322  /* if the font is bold, set to normal */
3323  if (ncm.lfCaptionFont.lfWeight > FW_NORMAL) {
3324  ncm.lfCaptionFont.lfWeight = FW_NORMAL;
3325  }
3326  tfont = CreateFontIndirectW (&ncm.lfCaptionFont);
3327  if (tfont) {
3328  infoPtr->hFont = infoPtr->hDefaultFont = tfont;
3329  }
3330 
3331  return TRUE;
3332 }
3333 
3334 
3335 static LRESULT
3337 {
3338  NMMOUSE nmmouse;
3339  POINT clpt;
3340  INT i;
3341  UINT scrap;
3342  LRESULT ret = HTCLIENT;
3343 
3344  /*
3345  * Differences from doc at MSDN (as observed with version 4.71 of
3346  * comctl32.dll
3347  * 1. doc says nmmouse.pt is in screen coord, trace shows client coord.
3348  * 2. if band is not identified .dwItemSpec is 0xffffffff.
3349  * 3. native always seems to return HTCLIENT if notify return is 0.
3350  */
3351 
3352  clpt.x = (short)LOWORD(lParam);
3353  clpt.y = (short)HIWORD(lParam);
3354  ScreenToClient (infoPtr->hwndSelf, &clpt);
3355  REBAR_InternalHitTest (infoPtr, &clpt, &scrap,
3356  (INT *)&nmmouse.dwItemSpec);
3357  nmmouse.dwItemData = 0;
3358  nmmouse.pt = clpt;
3359 #ifdef __REACTOS__
3360  nmmouse.dwHitInfo = scrap;
3361 #else
3362  nmmouse.dwHitInfo = 0;
3363 #endif
3364  if ((i = REBAR_Notify((NMHDR *) &nmmouse, infoPtr, NM_NCHITTEST))) {
3365  TRACE("notify changed return value from %ld to %d\n",
3366  ret, i);
3367  ret = (LRESULT) i;
3368  }
3369  TRACE("returning %ld, client point %s\n", ret, wine_dbgstr_point(&clpt));
3370  return ret;
3371 }
3372 
3373 
3374 static LRESULT
3375 REBAR_NCPaint (const REBAR_INFO *infoPtr)
3376 {
3377  RECT rcWindow;
3378  HDC hdc;
3379  HTHEME theme;
3380 
3381  if (infoPtr->dwStyle & WS_MINIMIZE)
3382  return 0; /* Nothing to do */
3383 
3384  if (infoPtr->dwStyle & WS_BORDER) {
3385 
3386  /* adjust rectangle and draw the necessary edge */
3387  if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
3388  return 0;
3389  GetWindowRect (infoPtr->hwndSelf, &rcWindow);
3390  OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3391  TRACE("rect (%s)\n", wine_dbgstr_rect(&rcWindow));
3392  DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
3393  ReleaseDC( infoPtr->hwndSelf, hdc );
3394  }
3395  else if ((theme = GetWindowTheme (infoPtr->hwndSelf)))
3396  {
3397  /* adjust rectangle and draw the necessary edge */
3398  if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
3399  return 0;
3400  GetWindowRect (infoPtr->hwndSelf, &rcWindow);
3401  OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
3402  TRACE("rect (%s)\n", wine_dbgstr_rect(&rcWindow));
3403  DrawThemeEdge (theme, hdc, 0, 0, &rcWindow, BDR_RAISEDINNER, BF_TOP, NULL);
3404  ReleaseDC( infoPtr->hwndSelf, hdc );
3405  }
3406 
3407  return 0;
3408 }
3409 
3410 
3411 static LRESULT
3413 {
3414  INT i;
3415 
3416  if (cmd == NF_REQUERY) {
3417  i = SendMessageW(REBAR_GetNotifyParent (infoPtr),
3418  WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY);
3419  if ((i != NFR_ANSI) && (i != NFR_UNICODE)) {
3420  ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", i);
3421  i = NFR_ANSI;
3422  }
3423  infoPtr->bUnicode = (i == NFR_UNICODE);
3424  return (LRESULT)i;
3425  }
3426  return (LRESULT)((infoPtr->bUnicode) ? NFR_UNICODE : NFR_ANSI);
3427 }
3428 
3429 
3430 static LRESULT
3431 REBAR_Paint (const REBAR_INFO *infoPtr, HDC hdc)
3432 {
3433  if (hdc) {
3434  TRACE("painting\n");
3435 #ifdef __REACTOS__
3436  REBAR_EraseBkGnd (infoPtr, hdc);
3437 #endif
3438  REBAR_Refresh (infoPtr, hdc);
3439  } else {
3440  PAINTSTRUCT ps;
3441  hdc = BeginPaint (infoPtr->hwndSelf, &ps);
3442  TRACE("painting (%s)\n", wine_dbgstr_rect(&ps.rcPaint));
3443  if (ps.fErase) {
3444  /* Erase area of paint if requested */
3445  REBAR_EraseBkGnd (infoPtr, hdc);
3446  }
3447  REBAR_Refresh (infoPtr, hdc);
3448  EndPaint (infoPtr->hwndSelf, &ps);
3449  }
3450 
3451  return 0;
3452 }
3453 
3454 
3455 static LRESULT
3457 {
3458  POINT pt;
3459  UINT flags;
3460 
3461  TRACE("code=0x%X id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
3462 
3463  GetCursorPos (&pt);
3464  ScreenToClient (infoPtr->hwndSelf, &pt);
3465 
3466  REBAR_InternalHitTest (infoPtr, &pt, &flags, NULL);
3467 
3468  if (flags == RBHT_GRABBER) {
3469  if ((infoPtr->dwStyle & CCS_VERT) &&
3470  !(infoPtr->dwStyle & RBS_VERTICALGRIPPER))
3471  SetCursor (infoPtr->hcurVert);
3472  else
3473  SetCursor (infoPtr->hcurHorz);
3474  }
3475  else if (flags != RBHT_CLIENT)
3476  SetCursor (infoPtr->hcurArrow);
3477 
3478  return 0;
3479 }
3480 
3481 
3482 static LRESULT
3484 {
3485  REBAR_BAND *lpBand;
3486  UINT i;
3487 
3488  infoPtr->hFont = font;
3489 
3490  /* revalidate all bands to change sizes of text in headers of bands */
3491  for (i=0; i<infoPtr->uNumBands; i++) {
3492  lpBand = REBAR_GetBand(infoPtr, i);
3493  REBAR_ValidateBand (infoPtr, lpBand);
3494  }
3495 
3496  REBAR_Layout(infoPtr);
3497  return 0;
3498 }
3499 
3500 
3501 /*****************************************************
3502  *
3503  * Handles the WM_SETREDRAW message.
3504  *
3505  * Documentation:
3506  * According to testing V4.71 of COMCTL32 returns the
3507  * *previous* status of the redraw flag (either 0 or -1)
3508  * instead of the MSDN documented value of 0 if handled
3509  *
3510  *****************************************************/
3511 static inline LRESULT
3513 {
3514  BOOL oldredraw = infoPtr->DoRedraw;
3515 
3516  TRACE("set to %s, fStatus=%08x\n",
3517  (redraw) ? "TRUE" : "FALSE", infoPtr->fStatus);
3518  infoPtr->DoRedraw = redraw;
3519  if (redraw) {
3520  if (infoPtr->fStatus & BAND_NEEDS_REDRAW) {
3521  REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
3522  REBAR_ForceResize (infoPtr);
3523  InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
3524  }
3525  infoPtr->fStatus &= ~BAND_NEEDS_REDRAW;
3526  }
3527  return (oldredraw) ? -1 : 0;
3528 }
3529 
3530 
3531 static LRESULT
3533 {
3534  TRACE("wParam=%lx, lParam=%lx\n", wParam, lParam);
3535 
3536  /* avoid _Layout resize recursion (but it shouldn't be infinite and it seems Windows does recurse) */
3537  if (infoPtr->fStatus & SELF_RESIZE) {
3538  infoPtr->fStatus &= ~SELF_RESIZE;
3539  TRACE("SELF_RESIZE was set, reset, fStatus=%08x lparam=%08lx\n",
3540  infoPtr->fStatus, lParam);
3541  return 0;
3542  }
3543 
3544  if (infoPtr->dwStyle & RBS_AUTOSIZE)
3545  REBAR_AutoSize(infoPtr, TRUE);
3546  else
3547  REBAR_Layout(infoPtr);
3548 
3549  return 0;
3550 }
3551 
3552 
3553 static LRESULT
3554 REBAR_StyleChanged (REBAR_INFO *infoPtr, INT nType, const STYLESTRUCT *lpStyle)
3555 {
3556  TRACE("current style=%08x, styleOld=%08x, style being set to=%08x\n",
3557  infoPtr->dwStyle, lpStyle->styleOld, lpStyle->styleNew);
3558  if (nType == GWL_STYLE)
3559  {
3560  infoPtr->orgStyle = infoPtr->dwStyle = lpStyle->styleNew;
3561  if (GetWindowTheme (infoPtr->hwndSelf))
3562  infoPtr->dwStyle &= ~WS_BORDER;
3563  /* maybe it should be COMMON_STYLES like in toolbar */
3564  if ((lpStyle->styleNew ^ lpStyle->styleOld) & CCS_VERT)
3565  REBAR_Layout(infoPtr);
3566  }
3567  return FALSE;
3568 }
3569 
3570 /* update theme after a WM_THEMECHANGED message */
3572 {
3573  HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
3574  CloseThemeData (theme);
3575  theme = OpenThemeData (infoPtr->hwndSelf, themeClass);
3576  /* WS_BORDER disappears when theming is enabled and reappears when
3577  * disabled... */
3578  infoPtr->dwStyle &= ~WS_BORDER;
3579  infoPtr->dwStyle |= theme ? 0 : (infoPtr->orgStyle & WS_BORDER);
3580  return 0;
3581 }
3582 
3583 static LRESULT
3585 {
3586  LRESULT ret;
3587  RECT rc;
3588 
3590  wParam, lParam);
3591  GetWindowRect(infoPtr->hwndSelf, &rc);
3592  TRACE("hwnd %p new pos (%s)\n", infoPtr->hwndSelf, wine_dbgstr_rect(&rc));
3593  return ret;
3594 }
3595 
3596 
3597 static LRESULT WINAPI
3599 {
3600  REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
3601 
3602  TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n",
3603  hwnd, uMsg, wParam, lParam);
3604  if (!infoPtr && (uMsg != WM_NCCREATE))
3605  return DefWindowProcW (hwnd, uMsg, wParam, lParam);
3606  switch (uMsg)
3607  {
3608 /* case RB_BEGINDRAG: */
3609 
3610  case RB_DELETEBAND:
3611  return REBAR_DeleteBand (infoPtr, wParam);
3612 
3613 /* case RB_DRAGMOVE: */
3614 /* case RB_ENDDRAG: */
3615 
3616  case RB_GETBANDBORDERS:
3617  return REBAR_GetBandBorders (infoPtr, wParam, (LPRECT)lParam);
3618 
3619  case RB_GETBANDCOUNT:
3620  return REBAR_GetBandCount (infoPtr);
3621 
3622  case RB_GETBANDINFO_OLD:
3623  case RB_GETBANDINFOA:
3624  case RB_GETBANDINFOW:
3626  uMsg == RB_GETBANDINFOW);
3627  case RB_GETBARHEIGHT:
3628  return REBAR_GetBarHeight (infoPtr);
3629 
3630  case RB_GETBARINFO:
3631  return REBAR_GetBarInfo (infoPtr, (LPREBARINFO)lParam);
3632 
3633  case RB_GETBKCOLOR:
3634  return REBAR_GetBkColor (infoPtr);
3635 
3636 /* case RB_GETCOLORSCHEME: */
3637 /* case RB_GETDROPTARGET: */
3638 
3639  case RB_GETPALETTE:
3640  return REBAR_GetPalette (infoPtr);
3641 
3642  case RB_GETRECT:
3643  return REBAR_GetRect (infoPtr, wParam, (LPRECT)lParam);
3644 
3645  case RB_GETROWCOUNT:
3646  return REBAR_GetRowCount (infoPtr);
3647 
3648  case RB_GETROWHEIGHT:
3649  return REBAR_GetRowHeight (infoPtr, wParam);
3650 
3651  case RB_GETTEXTCOLOR:
3652  return REBAR_GetTextColor (infoPtr);
3653 
3654  case RB_GETTOOLTIPS:
3655  return REBAR_GetToolTips (infoPtr);
3656 
3657  case RB_GETUNICODEFORMAT:
3658  return REBAR_GetUnicodeFormat (infoPtr);
3659 
3660  case CCM_GETVERSION:
3661  return REBAR_GetVersion (infoPtr);
3662 
3663  case RB_HITTEST:
3664  return REBAR_HitTest (infoPtr, (LPRBHITTESTINFO)lParam);
3665 
3666  case RB_IDTOINDEX:
3667  return REBAR_IdToIndex (infoPtr, wParam);
3668 
3669  case RB_INSERTBANDA:
3670  case RB_INSERTBANDW:
3671  return REBAR_InsertBandT(infoPtr, wParam, (LPREBARBANDINFOW)lParam,
3672  uMsg == RB_INSERTBANDW);
3673  case RB_MAXIMIZEBAND:
3674  return REBAR_MaximizeBand (infoPtr, wParam, lParam);
3675 
3676  case RB_MINIMIZEBAND:
3677  return REBAR_MinimizeBand (infoPtr, wParam);
3678 
3679  case RB_MOVEBAND:
3680  return REBAR_MoveBand (infoPtr, wParam, lParam);
3681 
3682  case RB_PUSHCHEVRON:
3683  return REBAR_PushChevron (infoPtr, wParam, lParam);
3684 
3685  case RB_SETBANDINFOA:
3686  case RB_SETBANDINFOW:
3688  uMsg == RB_SETBANDINFOW);
3689  case RB_SETBARINFO:
3690  return REBAR_SetBarInfo (infoPtr, (LPREBARINFO)lParam);
3691 
3692  case RB_SETBKCOLOR:
3693  return REBAR_SetBkColor (infoPtr, lParam);
3694 
3695 /* case RB_SETCOLORSCHEME: */
3696 /* case RB_SETPALETTE: */
3697 
3698  case RB_SETPARENT:
3699  return REBAR_SetParent (infoPtr, (HWND)wParam);
3700 
3701  case RB_SETTEXTCOLOR:
3702  return REBAR_SetTextColor (infoPtr, lParam);
3703 
3704 /* case RB_SETTOOLTIPS: */
3705 
3706  case RB_SETUNICODEFORMAT:
3707  return REBAR_SetUnicodeFormat (infoPtr, wParam);
3708 
3709  case CCM_SETVERSION:
3710  return REBAR_SetVersion (infoPtr, (INT)wParam);
3711 
3712  case RB_SHOWBAND:
3713  return REBAR_ShowBand (infoPtr, wParam, lParam);
3714 
3715  case RB_SIZETORECT:
3716 #ifdef __REACTOS__
3717  return REBAR_SizeToRect (infoPtr, wParam, (LPRECT)lParam);
3718 #else
3719  return REBAR_SizeToRect (infoPtr, (LPCRECT)lParam);
3720 #endif
3721 
3722 
3723 /* Messages passed to parent */
3724  case WM_COMMAND:
3725  case WM_DRAWITEM:
3726  case WM_NOTIFY:
3727  case WM_MEASUREITEM:
3728  return SendMessageW(REBAR_GetNotifyParent (infoPtr), uMsg, wParam, lParam);
3729 
3730 
3731 /* case WM_CHARTOITEM: supported according to ControlSpy */
3732 
3733  case WM_CREATE:
3734  return REBAR_Create (infoPtr, (LPCREATESTRUCTW)lParam);
3735 
3736  case WM_DESTROY:
3737  return REBAR_Destroy (infoPtr);
3738 
3739  case WM_ERASEBKGND:
3740  return REBAR_EraseBkGnd (infoPtr, (HDC)wParam);
3741 
3742  case WM_GETFONT:
3743  return REBAR_GetFont (infoPtr);
3744 
3745 /* case WM_LBUTTONDBLCLK: supported according to ControlSpy */
3746 
3747  case WM_LBUTTONDOWN:
3748  return REBAR_LButtonDown (infoPtr, lParam);
3749 
3750  case WM_LBUTTONUP:
3751  return REBAR_LButtonUp (infoPtr);
3752 
3753  case WM_MOUSEMOVE:
3754  return REBAR_MouseMove (infoPtr, lParam);
3755 
3756  case WM_MOUSELEAVE:
3757  return REBAR_MouseLeave (infoPtr);
3758 
3759  case WM_NCCALCSIZE:
3760  return REBAR_NCCalcSize (infoPtr, (RECT*)lParam);
3761 
3762  case WM_NCCREATE:
3764 
3765  case WM_NCHITTEST:
3766  return REBAR_NCHitTest (infoPtr, lParam);
3767 
3768  case WM_NCPAINT:
3769  return REBAR_NCPaint (infoPtr);
3770 
3771  case WM_NOTIFYFORMAT:
3772  return REBAR_NotifyFormat (infoPtr, lParam);
3773 
3774  case WM_PRINTCLIENT:
3775  case WM_PAINT:
3776  return REBAR_Paint (infoPtr, (HDC)wParam);
3777 
3778 /* case WM_PALETTECHANGED: supported according to ControlSpy */
3779 /* case WM_QUERYNEWPALETTE:supported according to ControlSpy */
3780 /* case WM_RBUTTONDOWN: supported according to ControlSpy */
3781 /* case WM_RBUTTONUP: supported according to ControlSpy */
3782 
3783  case WM_SETCURSOR:
3784  return REBAR_SetCursor (infoPtr, lParam);
3785 
3786  case WM_SETFONT:
3787  return REBAR_SetFont (infoPtr, (HFONT)wParam);
3788 
3789  case WM_SETREDRAW:
3790  return REBAR_SetRedraw (infoPtr, wParam);
3791 
3792  case WM_SIZE:
3793  return REBAR_Size (infoPtr, wParam, lParam);
3794 
3795  case WM_STYLECHANGED:
3796  return REBAR_StyleChanged (infoPtr, wParam, (LPSTYLESTRUCT)lParam);
3797 
3798  case WM_THEMECHANGED:
3799  return theme_changed (infoPtr);
3800 
3801  case WM_SYSCOLORCHANGE:
3803 #ifdef __REACTOS__
3804  /* r51522 - Properly support WM_SYSCOLORCHANGE */
3807 #endif
3808  return 0;
3809 
3810 /* case WM_VKEYTOITEM: supported according to ControlSpy */
3811 /* case WM_WININICHANGE: */
3812 
3813  case WM_WINDOWPOSCHANGED:
3814  return REBAR_WindowPosChanged (infoPtr, wParam, lParam);
3815 
3816  default:
3817  if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
3818  ERR("unknown msg %04x wp=%08lx lp=%08lx\n",
3819  uMsg, wParam, lParam);
3820  return DefWindowProcW (hwnd, uMsg, wParam, lParam);
3821  }
3822 }
3823 
3824 
3825 VOID
3827 {
3828  WNDCLASSW wndClass;
3829 
3830  ZeroMemory (&wndClass, sizeof(WNDCLASSW));
3831  wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
3832  wndClass.lpfnWndProc = REBAR_WindowProc;
3833  wndClass.cbClsExtra = 0;
3834  wndClass.cbWndExtra = sizeof(REBAR_INFO *);
3835  wndClass.hCursor = 0;
3836  wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
3837 #if GLATESTING
3838  wndClass.hbrBackground = CreateSolidBrush(RGB(0,128,0));
3839 #endif
3840  wndClass.lpszClassName = REBARCLASSNAMEW;
3841 
3842  RegisterClassW (&wndClass);
3843 
3846 
3847 }
3848 
3849 
3850 VOID
3852 {
3854 }
static LRESULT REBAR_SetBandInfoT(REBAR_INFO *infoPtr, INT iBand, const REBARBANDINFOW *lprbbi, BOOL bUnicode)
Definition: rebar.c:2736
HGDIOBJ WINAPI GetStockObject(_In_ int)
#define IDC_SIZEWE
Definition: winuser.h:689
static VOID REBAR_ValidateBand(const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
Definition: rebar.c:1593
UINT wID
Definition: commctrl.h:1650
#define GRIPPER_HEIGHT
Definition: rebar.c:218
BOOL WINAPI ExtTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_ UINT options, _In_opt_ const RECT *lprect, _In_reads_opt_(c) LPCWSTR lpString, _In_ UINT c, _In_reads_opt_(c) const INT *lpDx)
static LRESULT REBAR_GetFont(const REBAR_INFO *infoPtr)
Definition: rebar.c:3016
UINT cyMinChild
Definition: rebar.c:107
static LRESULT REBAR_GetRowCount(const REBAR_INFO *infoPtr)
Definition: rebar.c:2424
#define abs(i)
Definition: fconv.c:206
static int first_visible(const REBAR_INFO *infoPtr)
Definition: rebar.c:1133
#define RB_GETBANDBORDERS
Definition: commctrl.h:1613
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
static LRESULT REBAR_MinimizeBand(const REBAR_INFO *infoPtr, INT iBand)
Definition: rebar.c:2635
UINT cyMinBand
Definition: rebar.c:121
#define BF_MIDDLE
Definition: winuser.h:468
BOOL WINAPI RedrawWindow(_In_opt_ HWND, _In_opt_ LPCRECT, _In_opt_ HRGN, _In_ UINT)
GLint GLint GLsizei width
Definition: gl.h:1546
COLORREF WINAPI GetBkColor(_In_ HDC)
Definition: dc.c:954
static HWND REBAR_GetNotifyParent(const REBAR_INFO *infoPtr)
Definition: rebar.c:502
HDC WINAPI GetDCEx(_In_opt_ HWND, _In_opt_ HRGN, _In_ DWORD)
static void update_min_band_height(const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
Definition: rebar.c:475
#define WM_SYSCOLORCHANGE
Definition: winuser.h:1608
#define max(a, b)
Definition: svc.c:63
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
HDWP WINAPI BeginDeferWindowPos(_In_ int)
static LRESULT REBAR_GetRowHeight(const REBAR_INFO *infoPtr, INT iRow)
Definition: rebar.c:2433
#define RB_SIZETORECT
Definition: commctrl.h:1594
INT iVersion
Definition: rebar.c:180
#define TRUE
Definition: types.h:120
RECT rcCapImage
Definition: rebar.c:130
#define RB_GETBKCOLOR
Definition: commctrl.h:1588
#define SELF_RESIZE
Definition: rebar.c:193
HPEN WINAPI CreatePen(_In_ int, _In_ int, _In_ COLORREF)
DWORD dwStyle
Definition: rebar.c:170
RECT rcChild
Definition: rebar.c:132
HDPA WINAPI DPA_Create(INT nGrow)
Definition: dpa.c:950
static LRESULT REBAR_StyleChanged(REBAR_INFO *infoPtr, INT nType, const STYLESTRUCT *lpStyle)
Definition: rebar.c:3554
#define COLOR_WINDOWFRAME
Definition: winuser.h:909
#define RBHT_CLIENT
Definition: commctrl.h:1689
#define RBBIM_CHILD
Definition: commctrl.h:1502
#define RBS_VARHEIGHT
Definition: commctrl.h:1467
_In_ int _Inout_ LPRECT lprc
Definition: winuser.h:4440
DWORD dwMask
Definition: commctrl.h:1647
#define SW_SHOWNOACTIVATE
Definition: winuser.h:768
long y
Definition: polytest.cpp:48
UINT style
Definition: winuser.h:3151
static const WCHAR themeClass[]
Definition: rebar.c:303
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
#define WM_LBUTTONDOWN
Definition: winuser.h:1758
static int REBAR_SetBandsHeight(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT yStart)
Definition: rebar.c:1304
#define RBBS_UNDOC_FIXEDHEADER
Definition: rebar.c:197
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
BOOL bUnicode
Definition: rebar.c:173
UINT uNumBands
Definition: rebar.c:162
BOOL WINAPI IsWindow(_In_opt_ HWND)
LPWSTR lpText
Definition: rebar.c:135
#define REBARSPACE(a)
Definition: rebar.c:245
HCURSOR hcurArrow
Definition: rebar.c:176
BOOL WINAPI DPA_Destroy(HDPA hdpa)
Definition: dpa.c:396
#define RB_GETROWHEIGHT
Definition: commctrl.h:1583
long x
Definition: polytest.cpp:48
#define HAS_IMAGE
Definition: rebar.c:144
#define CHEVRON_WIDTH
Definition: rebar.c:228
#define RBN_HEIGHTCHANGE
Definition: commctrl.h:1624
COLORREF clrBk
Definition: rebar.c:157
#define CDRF_NOTIFYPOSTPAINT
Definition: commctrl.h:270
HDC WINAPI GetDC(_In_opt_ HWND)
static int REBAR_ShrinkBandsRTL(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT cxShrink, BOOL bEnforce)
Definition: rebar.c:1207
Definition: mk_font.cpp:20
#define RBHT_CAPTION
Definition: commctrl.h:1688
#define RB_GETBARHEIGHT
Definition: commctrl.h:1604
Definition: ftp_var.h:139
INT cxEffective
Definition: rebar.c:118
UINT cyChild
Definition: rebar.c:111
#define RB_SETBANDINFOA
Definition: commctrl.h:1575
#define RBN_AUTOSIZE
Definition: commctrl.h:1627
#define pt(x, y)
Definition: drawing.c:79
#define SW_HIDE
Definition: winuser.h:762
HWND WINAPI SetParent(_In_ HWND, _In_opt_ HWND)
#define WM_NCCALCSIZE
Definition: winuser.h:1667
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
#define RB_GETBANDINFO_OLD
Definition: rebar.c:249
static LRESULT REBAR_GetTextColor(const REBAR_INFO *infoPtr)
Definition: rebar.c:2454
static LRESULT REBAR_InsertBandT(REBAR_INFO *infoPtr, INT iIndex, const REBARBANDINFOW *lprbbi, BOOL bUnicode)
Definition: rebar.c:2520
char CHAR
Definition: xmlstorage.h:175
#define RBBIM_HEADERSIZE
Definition: commctrl.h:1509
#define WARN(fmt,...)
Definition: debug.h:111
static VOID REBAR_SizeToHeight(REBAR_INFO *infoPtr, int height)
Definition: rebar.c:1496
#define REBAR_POST_IMAGE
Definition: rebar.c:212
UINT uCDret
Definition: rebar.c:127
HRESULT WINAPI DrawThemeEdge(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pDestRect, UINT uEdge, UINT uFlags, RECT *pContentRect)
Definition: draw.c:1342
static HDC
Definition: imagelist.c:92
#define WM_SETREDRAW
Definition: winuser.h:1598
UINT cx
Definition: rebar.c:108
#define RBBS_BREAK
Definition: commctrl.h:1485
INT iGrabbedBand
Definition: rebar.c:186
static CHAR * REBAR_FmtMask(UINT mask)
Definition: rebar.c:323
BOOL WINAPI UpdateWindow(_In_ HWND)
UINT cyHeader
Definition: rebar.c:119
#define BF_BOTTOM
Definition: winuser.h:457
GLdouble n
Definition: glext.h:7729
HWND hwndChild
Definition: rebar.c:105
LONG top
Definition: windef.h:307
static UINT
Definition: rebar.c:37
#define RBBIM_ID
Definition: commctrl.h:1506
static void REBAR_HandleUDDrag(REBAR_INFO *infoPtr, const POINT *ptsmove)
Definition: rebar.c:2110
static LRESULT REBAR_MouseLeave(REBAR_INFO *infoPtr)
Definition: rebar.c:3121
#define DCX_USESTYLE
Definition: GetDCEx.c:10
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
#define REBAR_PRE_GRIPPER
Definition: rebar.c:221
#define CDDS_ITEMPREPAINT
Definition: commctrl.h:281
static HTHEME(WINAPI *pOpenThemeDataEx)(HWND
#define assert(x)
Definition: debug.h:53
HWND hwndSelf
Definition: rebar.c:164
#define ZeroMemory
Definition: winbase.h:1642
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
#define SM_CXEDGE
Definition: winuser.h:998
#define HWND_TOP
Definition: winuser.h:1193
BOOL WINAPI LineTo(_In_ HDC, _In_ int, _In_ int)
static LRESULT REBAR_Paint(const REBAR_INFO *infoPtr, HDC hdc)
Definition: rebar.c:3431
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
int cbClsExtra
Definition: winuser.h:3153
WINE_DEFAULT_DEBUG_CHANNEL(rebar)
static LRESULT REBAR_GetBkColor(const REBAR_INFO *infoPtr)
Definition: rebar.c:2377
#define RB_GETBANDINFOW
Definition: commctrl.h:1605
#define WM_NCHITTEST
Definition: winuser.h:1668
static LRESULT REBAR_SetUnicodeFormat(REBAR_INFO *infoPtr, BOOL unicode)
Definition: rebar.c:2867
UINT_PTR WPARAM
Definition: windef.h:207
COLORREF clrBtnText
Definition: comctl32.h:160
#define CCS_LAYOUT_MASK
Definition: rebar.c:140
BOOL WINAPI Str_SetPtrW(LPWSTR *lppDest, LPCWSTR lpSrc)
Definition: string.c:236
BOOL WINAPI ImageList_Draw(HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle)
Definition: imagelist.c:1228
LONG left
Definition: windef.h:306
#define SWP_NOZORDER
Definition: winuser.h:1232
SIZE calcSize
Definition: rebar.c:172
HICON HCURSOR
Definition: windef.h:299
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define RBIM_IMAGELIST
Definition: commctrl.h:1464
RECT rcGripper
Definition: rebar.c:129
static void REBAR_DrawChevron(HDC hdc, INT left, INT top, INT colorRef)
Definition: rebar.c:482
COLORREF clrBtnFace
Definition: rebar.c:160
static LRESULT REBAR_SetVersion(REBAR_INFO *infoPtr, INT iVersion)
Definition: rebar.c:2882
char * LPSTR
Definition: xmlstorage.h:182
#define CDRF_SKIPDEFAULT
Definition: commctrl.h:266
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:2635
LONG right
Definition: windef.h:308
static INT REBAR_Notify_NMREBAR(const REBAR_INFO *infoPtr, UINT uBand, UINT code)
Definition: rebar.c:532
#define lstrlenW
Definition: compat.h:415
#define WM_NCCREATE
Definition: winuser.h:1665
BOOL WINAPI DestroyWindow(_In_ HWND)
#define RBBIM_LPARAM
Definition: commctrl.h:1508
HRESULT WINAPI DrawThemeBackground(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect)
Definition: draw.c:128
int32_t INT
Definition: typedefs.h:56
static UINT REBAR_CommonSetupBand(HWND hwnd, const REBARBANDINFOW *lprbbi, REBAR_BAND *lpBand)
Definition: rebar.c:1707
COLORREF clrFore
Definition: rebar.c:102
#define RB_SETPARENT
Definition: commctrl.h:1576
DWORD WINAPI GetSysColor(_In_ int)
& rect
Definition: startmenu.cpp:1413
WPARAM wParam
Definition: combotst.c:138
#define RBBIM_IMAGE
Definition: commctrl.h:1501
RECT rcChevron
Definition: rebar.c:133
UINT uBand
Definition: commctrl.h:1648
#define WM_PRINTCLIENT
Definition: richedit.h:70
COLORREF clrBack
Definition: rebar.c:103
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define DRAW_CHEVRONPUSHED
Definition: rebar.c:152
static UINT mindragy
Definition: rebar.c:271
#define DCX_WINDOW
Definition: winuser.h:2095
#define IDC_SIZENS
Definition: winuser.h:690
#define CCS_VERT
Definition: commctrl.h:2245
DWORD_PTR dwItemSpec
Definition: commctrl.h:160
static int REBAR_SizeChildrenToHeight(const REBAR_INFO *infoPtr, int iBeginBand, int iEndBand, int extra, BOOL *fChanged)
Definition: rebar.c:1465
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:656
#define RBS_BANDBORDERS
Definition: commctrl.h:1468
BOOL DoRedraw
Definition: rebar.c:174
#define RBN_LAYOUTCHANGED
Definition: commctrl.h:1626
#define RBNM_LPARAM
Definition: commctrl.h:1656
LPARAM lParam
Definition: rebar.c:115
int WINAPI GetClassNameW(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, _In_ int nMaxCount)
#define REBARBANDINFOW_V6_SIZE
Definition: commctrl.h:1538
HFONT hDefaultFont
Definition: rebar.c:167
UINT code
Definition: winuser.h:3134
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:975
#define WM_NCPAINT
Definition: winuser.h:1669
#define REBARCLASSNAMEW
Definition: commctrl.h:1459
UINT cxMinChild
Definition: rebar.c:106
int WINAPI GetDlgCtrlID(_In_ HWND)
BOOL WINAPI MoveToEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
COLORREF clrText
Definition: rebar.c:158
BOOL WINAPI IsThemeBackgroundPartiallyTransparent(HTHEME hTheme, int iPartId, int iStateId)
Definition: draw.c:1883
INT Str_GetPtrWtoA(LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen) DECLSPEC_HIDDEN
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
#define RBBIM_STYLE
Definition: commctrl.h:1498
#define BF_RECT
Definition: winuser.h:462
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
#define PS_SOLID
Definition: wingdi.h:585
#define RBBIM_SIZE
Definition: commctrl.h:1504
#define CCS_NODIVIDER
Definition: commctrl.h:2244
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1032
uint32_t cs
Definition: isohybrid.c:75
#define RB_GETRECT
Definition: commctrl.h:1578
UINT fStatus
Definition: rebar.c:125
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static LRESULT REBAR_GetToolTips(const REBAR_INFO *infoPtr)
Definition: rebar.c:2463
#define RB_GETBANDINFOA
Definition: commctrl.h:1606
INT iImage
Definition: rebar.c:104
GLenum GLint GLuint mask
Definition: glext.h:6028
#define RB_SETBKCOLOR
Definition: commctrl.h:1587
#define REBAR_GetInfoPtr(wndPtr)
Definition: rebar.c:256
#define NM_NCHITTEST
Definition: commctrl.h:139
#define ETO_OPAQUE
Definition: wingdi.h:646
#define WS_MINIMIZE
Definition: pedump.c:622
#define RB_MINIMIZEBAND
Definition: commctrl.h:1610
#define REBAR_NO_CHILD_HEIGHT
Definition: rebar.c:238
COLORREF clrBack
Definition: commctrl.h:1545
unsigned int BOOL
Definition: ntddk_ex.h:94
#define RB_GETBANDCOUNT
Definition: commctrl.h:1581
#define RBN_DELETINGBAND
Definition: commctrl.h:1630
static LRESULT REBAR_GetBandBorders(const REBAR_INFO *infoPtr, UINT uBand, RECT *lpRect)
Definition: rebar.c:2222
#define DRAW_CHEVRONHOT
Definition: rebar.c:151
#define WM_SETCURSOR
Definition: winuser.h:1618
LONG WINAPI SetWindowLongW(_In_ HWND, _In_ int, _In_ LONG)
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
#define NTF_INVALIDATE
Definition: rebar.c:153
BOOL WINAPI DrawEdge(_In_ HDC, _Inout_ LPRECT, _In_ UINT, _In_ UINT)
UINT_PTR idFrom
Definition: winuser.h:3133
COLORREF clrFore
Definition: commctrl.h:1544
static LRESULT REBAR_SetCursor(const REBAR_INFO *infoPtr, LPARAM lParam)
Definition: rebar.c:3456
static LRESULT REBAR_LButtonDown(REBAR_INFO *infoPtr, LPARAM lParam)
Definition: rebar.c:3054
BOOL WINAPI EndDeferWindowPos(_In_ HDWP)
#define debugstr_w
Definition: kernel32.h:32
WNDPROC lpfnWndProc
Definition: winuser.h:3152
HWND WINAPI GetCapture(void)
Definition: message.c:2879
#define WM_MOUSELEAVE
Definition: commctrl.h:4971
static VOID REBAR_MoveChildWindows(const REBAR_INFO *infoPtr, UINT start, UINT endplus)
Definition: rebar.c:1019
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define FIXME(fmt,...)
Definition: debug.h:110
#define RBN_BEGINDRAG
Definition: commctrl.h:1628
static void REBAR_HandleLRDrag(REBAR_INFO *infoPtr, const POINT *ptsmove)
Definition: rebar.c:2043
UINT fStyle
Definition: rebar.c:100
#define TRANSPARENT
Definition: wingdi.h:949
COLORREF clrBtnText
Definition: rebar.c:159
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:581
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)