ReactOS  0.4.15-dev-2361-g32428a3
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:956
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
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
#define RGB(r, g, b)
Definition: precomp.h:62
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 TRUE
Definition: types.h:120
#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:112
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:31
#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:1499
#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:1664
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:167
#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:609
#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:58
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:814
#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:977
#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:1034
uint32_t cs
Definition: isohybrid.c:75
#define RB_GETRECT
Definition: commctrl.h:1578
UINT fStatus
Definition: rebar.c:125
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 FALSE
Definition: types.h:117
#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:2880
#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:111
#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)
#define RB_INSERTBANDA
Definition: commctrl.h:1571
UINT cyIntegral
Definition: rebar.c:113