ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rebar.c
Go to the documentation of this file.
00001 /*
00002  * Rebar control
00003  *
00004  * Copyright 1998, 1999 Eric Kohl
00005  * Copyright 2007, 2008 Mikolaj Zalewski
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  * NOTES
00022  *
00023  * This code was audited for completeness against the documented features
00024  * of Comctl32.dll version 6.0 on Oct. 19, 2004, by Robert Shearman.
00025  * 
00026  * Unless otherwise noted, we believe this code to be complete, as per
00027  * the specification mentioned above.
00028  * If you discover missing features or bugs please note them below.
00029  *
00030  * TODO
00031  *   Styles:
00032  *   - RBS_DBLCLKTOGGLE
00033  *   - RBS_FIXEDORDER
00034  *   - RBS_REGISTERDROP
00035  *   - RBS_TOOLTIPS
00036  *   Messages:
00037  *   - RB_BEGINDRAG
00038  *   - RB_DRAGMOVE
00039  *   - RB_ENDDRAG
00040  *   - RB_GETBANDMARGINS
00041  *   - RB_GETCOLORSCHEME
00042  *   - RB_GETDROPTARGET
00043  *   - RB_GETPALETTE
00044  *   - RB_SETCOLORSCHEME
00045  *   - RB_SETPALETTE
00046  *   - RB_SETTOOLTIPS
00047  *   - WM_CHARTOITEM
00048  *   - WM_LBUTTONDBLCLK
00049  *   - WM_MEASUREITEM
00050  *   - WM_PALETTECHANGED
00051  *   - WM_QUERYNEWPALETTE
00052  *   - WM_RBUTTONDOWN
00053  *   - WM_RBUTTONUP
00054  *   - WM_VKEYTOITEM
00055  *   - WM_WININICHANGE
00056  *   Notifications:
00057  *   - NM_HCHITTEST
00058  *   - NM_RELEASEDCAPTURE
00059  *   - RBN_AUTOBREAK
00060  *   - RBN_GETOBJECT
00061  *   - RBN_MINMAX
00062  *   Band styles:
00063  *   - RBBS_FIXEDBMP
00064  *   Native uses (on each draw!!) SM_CYBORDER (or SM_CXBORDER for CCS_VERT)
00065  *   to set the size of the separator width (the value SEP_WIDTH_SIZE
00066  *   in here). Should be fixed!!
00067  */
00068 
00069 /*
00070  * Testing: set to 1 to make background brush *always* green
00071  */
00072 #define GLATESTING 0
00073 
00074 /*
00075  * 3. REBAR_MoveChildWindows should have a loop because more than
00076  *    one pass (together with the RBN_CHILDSIZEs) is made on
00077  *    at least RB_INSERTBAND
00078  */
00079 
00080 #include <assert.h>
00081 #include <stdarg.h>
00082 #include <stdlib.h>
00083 #include <string.h>
00084 
00085 #include "windef.h"
00086 #include "winbase.h"
00087 #include "wingdi.h"
00088 #include "wine/unicode.h"
00089 #include "winuser.h"
00090 #include "winnls.h"
00091 #include "commctrl.h"
00092 #include "comctl32.h"
00093 #include "uxtheme.h"
00094 #include "vssym32.h"
00095 #include "wine/debug.h"
00096 
00097 WINE_DEFAULT_DEBUG_CHANNEL(rebar);
00098 
00099 typedef struct
00100 {
00101     UINT    fStyle;
00102     UINT    fMask;
00103     COLORREF  clrFore;
00104     COLORREF  clrBack;
00105     INT     iImage;
00106     HWND    hwndChild;
00107     UINT    cxMinChild;     /* valid if _CHILDSIZE */
00108     UINT    cyMinChild;     /* valid if _CHILDSIZE */
00109     UINT    cx;             /* valid if _SIZE */
00110     HBITMAP hbmBack;
00111     UINT    wID;
00112     UINT    cyChild;        /* valid if _CHILDSIZE */
00113     UINT    cyMaxChild;     /* valid if _CHILDSIZE */
00114     UINT    cyIntegral;     /* valid if _CHILDSIZE */
00115     UINT    cxIdeal;
00116     LPARAM    lParam;
00117     UINT    cxHeader;
00118 
00119     INT     cxEffective;    /* current cx for band */
00120     UINT    cyHeader;       /* the height of the header */
00121     UINT    cxMinBand;      /* minimum cx for band */
00122     UINT    cyMinBand;      /* minimum cy for band */
00123 
00124     UINT    cyRowSoFar;     /* for RBS_VARHEIGHT - the height of the row if it would break on this band (set by _Layout) */
00125     INT     iRow;           /* zero-based index of the row this band assigned to */
00126     UINT    fStatus;        /* status flags, reset only by _Validate */
00127     UINT    fDraw;          /* drawing flags, reset only by _Layout */
00128     UINT    uCDret;         /* last return from NM_CUSTOMDRAW */
00129     RECT    rcBand;         /* calculated band rectangle - coordinates swapped for CCS_VERT */
00130     RECT    rcGripper;      /* calculated gripper rectangle */
00131     RECT    rcCapImage;     /* calculated caption image rectangle */
00132     RECT    rcCapText;      /* calculated caption text rectangle */
00133     RECT    rcChild;        /* calculated child rectangle */
00134     RECT    rcChevron;      /* calculated chevron rectangle */
00135 
00136     LPWSTR    lpText;
00137     HWND    hwndPrevParent;
00138 } REBAR_BAND;
00139 
00140 /* fStatus flags */
00141 #define HAS_GRIPPER    0x00000001
00142 #define HAS_IMAGE      0x00000002
00143 #define HAS_TEXT       0x00000004
00144 
00145 /* fDraw flags */
00146 #define DRAW_GRIPPER    0x00000001
00147 #define DRAW_IMAGE      0x00000002
00148 #define DRAW_TEXT       0x00000004
00149 #define DRAW_CHEVRONHOT 0x00000040
00150 #define DRAW_CHEVRONPUSHED 0x00000080
00151 #define NTF_INVALIDATE  0x01000000
00152 
00153 typedef struct
00154 {
00155     COLORREF   clrBk;       /* background color */
00156     COLORREF   clrText;     /* text color */
00157     COLORREF   clrBtnText;  /* system color for BTNTEXT */
00158     COLORREF   clrBtnFace;  /* system color for BTNFACE */
00159     HIMAGELIST himl;        /* handle to imagelist */
00160     UINT     uNumBands;   /* # of bands in rebar (first=0, last=uNumBands-1 */
00161     UINT     uNumRows;    /* # of rows of bands (first=1, last=uNumRows */
00162     HWND     hwndSelf;    /* handle of REBAR window itself */
00163     HWND     hwndToolTip; /* handle to the tool tip control */
00164     HWND     hwndNotify;  /* notification window (parent) */
00165     HFONT    hDefaultFont;
00166     HFONT    hFont;       /* handle to the rebar's font */
00167     SIZE     imageSize;   /* image size (image list) */
00168     DWORD    dwStyle;     /* window style */
00169     DWORD    orgStyle;    /* original style (dwStyle may change) */
00170     SIZE     calcSize;    /* calculated rebar size - coordinates swapped for CCS_VERT */
00171     BOOL     bUnicode;    /* TRUE if parent wants notify in W format */
00172     BOOL     DoRedraw;    /* TRUE to actually draw bands */
00173     UINT     fStatus;     /* Status flags (see below)  */
00174     HCURSOR  hcurArrow;   /* handle to the arrow cursor */
00175     HCURSOR  hcurHorz;    /* handle to the EW cursor */
00176     HCURSOR  hcurVert;    /* handle to the NS cursor */
00177     HCURSOR  hcurDrag;    /* handle to the drag cursor */
00178     INT      iVersion;    /* version number */
00179     POINT    dragStart;   /* x,y of button down */
00180     POINT    dragNow;     /* x,y of this MouseMove */
00181     INT      iOldBand;    /* last band that had the mouse cursor over it */
00182     INT      ihitoffset;  /* offset of hotspot from gripper.left */
00183     INT      ichevronhotBand; /* last band that had a hot chevron */
00184     INT      iGrabbedBand;/* band number of band whose gripper was grabbed */
00185 
00186     HDPA     bands;       /* pointer to the array of rebar bands */
00187 } REBAR_INFO;
00188 
00189 /* fStatus flags */
00190 #define BEGIN_DRAG_ISSUED   0x00000001
00191 #define SELF_RESIZE         0x00000002
00192 #define BAND_NEEDS_REDRAW   0x00000020
00193 
00194 /* used by Windows to mark that the header size has been set by the user and shouldn't be changed */
00195 #define RBBS_UNDOC_FIXEDHEADER 0x40000000
00196 
00197 /* ----   REBAR layout constants. Mostly determined by        ---- */
00198 /* ----   experiment on WIN 98.                               ---- */
00199 
00200 /* Width (or height) of separators between bands (either horz. or  */
00201 /* vert.). True only if RBS_BANDBORDERS is set                     */
00202 #define SEP_WIDTH_SIZE  2
00203 #define SEP_WIDTH       ((infoPtr->dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
00204 
00205 /* Blank (background color) space between Gripper (if present)     */
00206 /* and next item (image, text, or window). Always present          */
00207 #define REBAR_ALWAYS_SPACE  4
00208 
00209 /* Blank (background color) space after Image (if present).        */
00210 #define REBAR_POST_IMAGE  2
00211 
00212 /* Blank (background color) space after Text (if present).         */
00213 #define REBAR_POST_TEXT  4
00214 
00215 /* Height of vertical gripper in a CCS_VERT rebar.                 */
00216 #define GRIPPER_HEIGHT  16
00217 
00218 /* Blank (background color) space before Gripper (if present).     */
00219 #define REBAR_PRE_GRIPPER   2
00220 
00221 /* Width (of normal vertical gripper) or height (of horz. gripper) */
00222 /* if present.                                                     */
00223 #define GRIPPER_WIDTH  3
00224 
00225 /* Width of the chevron button if present */
00226 #define CHEVRON_WIDTH  10
00227 
00228 /* the gap between the child and the next band */
00229 #define REBAR_POST_CHILD 4
00230 
00231 /* Height of divider for Rebar if not disabled (CCS_NODIVIDER)     */
00232 /* either top or bottom                                            */
00233 #define REBAR_DIVIDER  2
00234 
00235 /* height of a rebar without a child */
00236 #define REBAR_NO_CHILD_HEIGHT 4
00237 
00238 /* minimum vertical height of a normal bar                        */
00239 /*   or minimum width of a CCS_VERT bar - from experiment on Win2k */
00240 #define REBAR_MINSIZE  23
00241 
00242 /* This is the increment that is used over the band height         */
00243 #define REBARSPACE(a)     ((a->fStyle & RBBS_CHILDEDGE) ? 2*REBAR_DIVIDER : 0)
00244 
00245 /* ----   End of REBAR layout constants.                      ---- */
00246 
00247 #define RB_GETBANDINFO_OLD (WM_USER+5) /* obsoleted after IE3, but we have to support it anyway */
00248 
00249 /*  The following define determines if a given band is hidden      */
00250 #define HIDDENBAND(a)  (((a)->fStyle & RBBS_HIDDEN) ||   \
00251                         ((infoPtr->dwStyle & CCS_VERT) &&         \
00252                          ((a)->fStyle & RBBS_NOVERT)))
00253 
00254 #define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongPtrW (hwnd, 0))
00255 
00256 static LRESULT REBAR_NotifyFormat(REBAR_INFO *infoPtr, LPARAM lParam);
00257 static void REBAR_AutoSize(REBAR_INFO *infoPtr, BOOL needsLayout);
00258 
00259 /* no index check here */
00260 static inline REBAR_BAND* REBAR_GetBand(const REBAR_INFO *infoPtr, INT i)
00261 {
00262     assert(i >= 0 && i < infoPtr->uNumBands);
00263     return DPA_GetPtr(infoPtr->bands, i);
00264 }
00265 
00266 /* "constant values" retrieved when DLL was initialized    */
00267 /* FIXME we do this when the classes are registered.       */
00268 static UINT mindragx = 0;
00269 static UINT mindragy = 0;
00270 
00271 static const char * const band_stylename[] = {
00272     "RBBS_BREAK",              /* 0001 */
00273     "RBBS_FIXEDSIZE",          /* 0002 */
00274     "RBBS_CHILDEDGE",          /* 0004 */
00275     "RBBS_HIDDEN",             /* 0008 */
00276     "RBBS_NOVERT",             /* 0010 */
00277     "RBBS_FIXEDBMP",           /* 0020 */
00278     "RBBS_VARIABLEHEIGHT",     /* 0040 */
00279     "RBBS_GRIPPERALWAYS",      /* 0080 */
00280     "RBBS_NOGRIPPER",          /* 0100 */
00281     NULL };
00282 
00283 static const char * const band_maskname[] = {
00284     "RBBIM_STYLE",         /*    0x00000001 */
00285     "RBBIM_COLORS",        /*    0x00000002 */
00286     "RBBIM_TEXT",          /*    0x00000004 */
00287     "RBBIM_IMAGE",         /*    0x00000008 */
00288     "RBBIM_CHILD",         /*    0x00000010 */
00289     "RBBIM_CHILDSIZE",     /*    0x00000020 */
00290     "RBBIM_SIZE",          /*    0x00000040 */
00291     "RBBIM_BACKGROUND",    /*    0x00000080 */
00292     "RBBIM_ID",            /*    0x00000100 */
00293     "RBBIM_IDEALSIZE",     /*    0x00000200 */
00294     "RBBIM_LPARAM",        /*    0x00000400 */
00295     "RBBIM_HEADERSIZE",    /*    0x00000800 */
00296     NULL };
00297 
00298 
00299 static CHAR line[200];
00300 
00301 static const WCHAR themeClass[] = { 'R','e','b','a','r',0 };
00302 
00303 static CHAR *
00304 REBAR_FmtStyle( UINT style)
00305 {
00306     INT i = 0;
00307 
00308     *line = 0;
00309     while (band_stylename[i]) {
00310     if (style & (1<<i)) {
00311         if (*line != 0) strcat(line, " | ");
00312         strcat(line, band_stylename[i]);
00313     }
00314     i++;
00315     }
00316     return line;
00317 }
00318 
00319 
00320 static CHAR *
00321 REBAR_FmtMask( UINT mask)
00322 {
00323     INT i = 0;
00324 
00325     *line = 0;
00326     while (band_maskname[i]) {
00327     if (mask & (1<<i)) {
00328         if (*line != 0) strcat(line, " | ");
00329         strcat(line, band_maskname[i]);
00330     }
00331     i++;
00332     }
00333     return line;
00334 }
00335 
00336 
00337 static VOID
00338 REBAR_DumpBandInfo(const REBARBANDINFOW *pB)
00339 {
00340     if( !TRACE_ON(rebar) ) return;
00341     TRACE("band info: ");
00342     if (pB->fMask & RBBIM_ID)
00343         TRACE("ID=%u, ", pB->wID);
00344     TRACE("size=%u, child=%p", pB->cbSize, pB->hwndChild);
00345     if (pB->fMask & RBBIM_COLORS)
00346         TRACE(", clrF=0x%06x, clrB=0x%06x", pB->clrFore, pB->clrBack);
00347     TRACE("\n");
00348 
00349     TRACE("band info: mask=0x%08x (%s)\n", pB->fMask, REBAR_FmtMask(pB->fMask));
00350     if (pB->fMask & RBBIM_STYLE)
00351     TRACE("band info: style=0x%08x (%s)\n", pB->fStyle, REBAR_FmtStyle(pB->fStyle));
00352     if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_HEADERSIZE | RBBIM_LPARAM )) {
00353     TRACE("band info:");
00354     if (pB->fMask & RBBIM_SIZE)
00355         TRACE(" cx=%u", pB->cx);
00356     if (pB->fMask & RBBIM_IDEALSIZE)
00357         TRACE(" xIdeal=%u", pB->cxIdeal);
00358     if (pB->fMask & RBBIM_HEADERSIZE)
00359         TRACE(" xHeader=%u", pB->cxHeader);
00360     if (pB->fMask & RBBIM_LPARAM)
00361         TRACE(" lParam=0x%08lx", pB->lParam);
00362     TRACE("\n");
00363     }
00364     if (pB->fMask & RBBIM_CHILDSIZE)
00365     TRACE("band info: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
00366           pB->cxMinChild,
00367           pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
00368 }
00369 
00370 static VOID
00371 REBAR_DumpBand (const REBAR_INFO *iP)
00372 {
00373     REBAR_BAND *pB;
00374     UINT i;
00375 
00376     if(! TRACE_ON(rebar) ) return;
00377 
00378     TRACE("hwnd=%p: color=%08x/%08x, bands=%u, rows=%u, cSize=%d,%d\n",
00379       iP->hwndSelf, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
00380       iP->calcSize.cx, iP->calcSize.cy);
00381     TRACE("hwnd=%p: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, iGrabbedBand=%d\n",
00382       iP->hwndSelf, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
00383       iP->dragNow.x, iP->dragNow.y,
00384       iP->iGrabbedBand);
00385     TRACE("hwnd=%p: style=%08x, notify in Unicode=%s, redraw=%s\n",
00386           iP->hwndSelf, iP->dwStyle, (iP->bUnicode)?"TRUE":"FALSE",
00387           (iP->DoRedraw)?"TRUE":"FALSE");
00388     for (i = 0; i < iP->uNumBands; i++) {
00389     pB = REBAR_GetBand(iP, i);
00390     TRACE("band # %u:", i);
00391     if (pB->fMask & RBBIM_ID)
00392         TRACE(" ID=%u", pB->wID);
00393     if (pB->fMask & RBBIM_CHILD)
00394         TRACE(" child=%p", pB->hwndChild);
00395     if (pB->fMask & RBBIM_COLORS)
00396             TRACE(" clrF=0x%06x clrB=0x%06x", pB->clrFore, pB->clrBack);
00397     TRACE("\n");
00398     TRACE("band # %u: mask=0x%08x (%s)\n", i, pB->fMask, REBAR_FmtMask(pB->fMask));
00399     if (pB->fMask & RBBIM_STYLE)
00400         TRACE("band # %u: style=0x%08x (%s)\n",
00401           i, pB->fStyle, REBAR_FmtStyle(pB->fStyle));
00402     TRACE("band # %u: xHeader=%u",
00403           i, pB->cxHeader);
00404     if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_LPARAM )) {
00405         if (pB->fMask & RBBIM_SIZE)
00406         TRACE(" cx=%u", pB->cx);
00407         if (pB->fMask & RBBIM_IDEALSIZE)
00408         TRACE(" xIdeal=%u", pB->cxIdeal);
00409         if (pB->fMask & RBBIM_LPARAM)
00410         TRACE(" lParam=0x%08lx", pB->lParam);
00411     }
00412     TRACE("\n");
00413     if (RBBIM_CHILDSIZE)
00414         TRACE("band # %u: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
00415           i, pB->cxMinChild, pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
00416     if (pB->fMask & RBBIM_TEXT)
00417         TRACE("band # %u: text=%s\n",
00418           i, (pB->lpText) ? debugstr_w(pB->lpText) : "(null)");
00419         TRACE("band # %u: cxMinBand=%u, cxEffective=%u, cyMinBand=%u\n",
00420               i, pB->cxMinBand, pB->cxEffective, pB->cyMinBand);
00421         TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%s), Grip=(%s)\n",
00422               i, pB->fStatus, pB->fDraw, wine_dbgstr_rect(&pB->rcBand),
00423               wine_dbgstr_rect(&pB->rcGripper));
00424         TRACE("band # %u: Img=(%s), Txt=(%s), Child=(%s)\n",
00425               i, wine_dbgstr_rect(&pB->rcCapImage),
00426               wine_dbgstr_rect(&pB->rcCapText), wine_dbgstr_rect(&pB->rcChild));
00427     }
00428 
00429 }
00430 
00431 /* dest can be equal to src */
00432 static void translate_rect(const REBAR_INFO *infoPtr, RECT *dest, const RECT *src)
00433 {
00434     if (infoPtr->dwStyle & CCS_VERT) {
00435         int tmp;
00436         tmp = src->left;
00437         dest->left = src->top;
00438         dest->top = tmp;
00439         
00440         tmp = src->right;
00441         dest->right = src->bottom;
00442         dest->bottom = tmp;
00443     } else {
00444         *dest = *src;
00445     }
00446 }
00447 
00448 static int get_rect_cx(const REBAR_INFO *infoPtr, const RECT *lpRect)
00449 {
00450     if (infoPtr->dwStyle & CCS_VERT)
00451         return lpRect->bottom - lpRect->top;
00452     return lpRect->right - lpRect->left;
00453 }
00454 
00455 static int get_rect_cy(const REBAR_INFO *infoPtr, const RECT *lpRect)
00456 {
00457     if (infoPtr->dwStyle & CCS_VERT)
00458         return lpRect->right - lpRect->left;
00459     return lpRect->bottom - lpRect->top;
00460 }
00461 
00462 static int round_child_height(const REBAR_BAND *lpBand, int cyHeight)
00463 {
00464     int cy = 0;
00465     if (lpBand->cyIntegral == 0)
00466         return cyHeight;
00467     cy = max(cyHeight - (int)lpBand->cyMinChild, 0);
00468     cy = lpBand->cyMinChild + (cy/lpBand->cyIntegral) * lpBand->cyIntegral;
00469     cy = min(cy, lpBand->cyMaxChild);
00470     return cy;
00471 }
00472 
00473 static void update_min_band_height(const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
00474 {
00475     lpBand->cyMinBand = max(lpBand->cyHeader,
00476         (lpBand->hwndChild ? lpBand->cyChild + REBARSPACE(lpBand) : REBAR_NO_CHILD_HEIGHT));
00477 }
00478 
00479 static void
00480 REBAR_DrawChevron (HDC hdc, INT left, INT top, INT colorRef)
00481 {
00482     INT x, y;
00483     HPEN hPen, hOldPen;
00484 
00485     if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return;
00486     hOldPen = SelectObject ( hdc, hPen );
00487     x = left + 2;
00488     y = top;
00489     MoveToEx (hdc, x, y, NULL);
00490     LineTo (hdc, x+5, y++); x++;
00491     MoveToEx (hdc, x, y, NULL);
00492     LineTo (hdc, x+3, y++); x++;
00493     MoveToEx (hdc, x, y, NULL);
00494     LineTo (hdc, x+1, y);
00495     SelectObject( hdc, hOldPen );
00496     DeleteObject( hPen );
00497 }
00498 
00499 static HWND
00500 REBAR_GetNotifyParent (const REBAR_INFO *infoPtr)
00501 {
00502     HWND parent, owner;
00503 
00504     parent = infoPtr->hwndNotify;
00505     if (!parent) {
00506         parent = GetParent (infoPtr->hwndSelf);
00507     owner = GetWindow (infoPtr->hwndSelf, GW_OWNER);
00508     if (owner) parent = owner;
00509     }
00510     return parent;
00511 }
00512 
00513 
00514 static INT
00515 REBAR_Notify (NMHDR *nmhdr, const REBAR_INFO *infoPtr, UINT code)
00516 {
00517     HWND parent;
00518 
00519     parent = REBAR_GetNotifyParent (infoPtr);
00520     nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
00521     nmhdr->hwndFrom = infoPtr->hwndSelf;
00522     nmhdr->code = code;
00523 
00524     TRACE("window %p, code=%08x, via %s\n", parent, code, (infoPtr->bUnicode)?"Unicode":"ANSI");
00525 
00526     return SendMessageW(parent, WM_NOTIFY, nmhdr->idFrom, (LPARAM)nmhdr);
00527 }
00528 
00529 static INT
00530 REBAR_Notify_NMREBAR (const REBAR_INFO *infoPtr, UINT uBand, UINT code)
00531 {
00532     NMREBAR notify_rebar;
00533 
00534     notify_rebar.dwMask = 0;
00535     if (uBand != -1) {
00536     REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, uBand);
00537 
00538     if (lpBand->fMask & RBBIM_ID) {
00539         notify_rebar.dwMask |= RBNM_ID;
00540         notify_rebar.wID = lpBand->wID;
00541     }
00542     if (lpBand->fMask & RBBIM_LPARAM) {
00543         notify_rebar.dwMask |= RBNM_LPARAM;
00544         notify_rebar.lParam = lpBand->lParam;
00545     }
00546     if (lpBand->fMask & RBBIM_STYLE) {
00547         notify_rebar.dwMask |= RBNM_STYLE;
00548         notify_rebar.fStyle = lpBand->fStyle;
00549     }
00550     }
00551     notify_rebar.uBand = uBand;
00552     return REBAR_Notify ((NMHDR *)&notify_rebar, infoPtr, code);
00553 }
00554 
00555 static VOID
00556 REBAR_DrawBand (HDC hdc, const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
00557 {
00558     HFONT hOldFont = 0;
00559     INT oldBkMode = 0;
00560     NMCUSTOMDRAW nmcd;
00561     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
00562     RECT rcBand;
00563 
00564     translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
00565 
00566     if (lpBand->fDraw & DRAW_TEXT) {
00567     hOldFont = SelectObject (hdc, infoPtr->hFont);
00568     oldBkMode = SetBkMode (hdc, TRANSPARENT);
00569     }
00570 
00571     /* should test for CDRF_NOTIFYITEMDRAW here */
00572     nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
00573     nmcd.hdc = hdc;
00574     nmcd.rc = rcBand;
00575     nmcd.rc.right = lpBand->rcCapText.right;
00576     nmcd.rc.bottom = lpBand->rcCapText.bottom;
00577     nmcd.dwItemSpec = lpBand->wID;
00578     nmcd.uItemState = 0;
00579     nmcd.lItemlParam = lpBand->lParam;
00580     lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
00581     if (lpBand->uCDret == CDRF_SKIPDEFAULT) {
00582     if (oldBkMode != TRANSPARENT)
00583         SetBkMode (hdc, oldBkMode);
00584     SelectObject (hdc, hOldFont);
00585     return;
00586     }
00587 
00588     /* draw gripper */
00589     if (lpBand->fDraw & DRAW_GRIPPER)
00590     {
00591         if (theme)
00592         {
00593             RECT rcGripper = lpBand->rcGripper;
00594             int partId = (infoPtr->dwStyle & CCS_VERT) ? RP_GRIPPERVERT : RP_GRIPPER;
00595             GetThemeBackgroundExtent (theme, hdc, partId, 0, &rcGripper, &rcGripper);
00596             OffsetRect (&rcGripper, lpBand->rcGripper.left - rcGripper.left,
00597                 lpBand->rcGripper.top - rcGripper.top);
00598             DrawThemeBackground (theme, hdc, partId, 0, &rcGripper, NULL);
00599         }
00600         else
00601             DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
00602     }
00603 
00604     /* draw caption image */
00605     if (lpBand->fDraw & DRAW_IMAGE) {
00606     POINT pt;
00607 
00608     /* center image */
00609     pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
00610     pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;
00611 
00612     ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
00613             pt.x, pt.y,
00614             ILD_TRANSPARENT);
00615     }
00616 
00617     /* draw caption text */
00618     if (lpBand->fDraw & DRAW_TEXT) {
00619     /* need to handle CDRF_NEWFONT here */
00620     INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
00621     COLORREF oldcolor = CLR_NONE;
00622     COLORREF new;
00623     if (lpBand->clrFore != CLR_NONE) {
00624         new = (lpBand->clrFore == CLR_DEFAULT) ? infoPtr->clrBtnText :
00625             lpBand->clrFore;
00626         oldcolor = SetTextColor (hdc, new);
00627     }
00628     DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
00629            DT_CENTER | DT_VCENTER | DT_SINGLELINE);
00630     if (oldBkMode != TRANSPARENT)
00631         SetBkMode (hdc, oldBkMode);
00632     if (lpBand->clrFore != CLR_NONE)
00633         SetTextColor (hdc, oldcolor);
00634     SelectObject (hdc, hOldFont);
00635     }
00636 
00637     if (!IsRectEmpty(&lpBand->rcChevron))
00638     {
00639         if (theme)
00640         {
00641             int stateId; 
00642             if (lpBand->fDraw & DRAW_CHEVRONPUSHED)
00643                 stateId = CHEVS_PRESSED;
00644             else if (lpBand->fDraw & DRAW_CHEVRONHOT)
00645                 stateId = CHEVS_HOT;
00646             else
00647                 stateId = CHEVS_NORMAL;
00648             DrawThemeBackground (theme, hdc, RP_CHEVRON, stateId, &lpBand->rcChevron, NULL);
00649         }
00650         else
00651         {
00652             if (lpBand->fDraw & DRAW_CHEVRONPUSHED)
00653             {
00654                 DrawEdge(hdc, &lpBand->rcChevron, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE);
00655                 REBAR_DrawChevron(hdc, lpBand->rcChevron.left+1, lpBand->rcChevron.top + 11, COLOR_WINDOWFRAME);
00656             }
00657             else if (lpBand->fDraw & DRAW_CHEVRONHOT)
00658             {
00659                 DrawEdge(hdc, &lpBand->rcChevron, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
00660                 REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME);
00661             }
00662             else
00663                 REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME);
00664         }
00665     }
00666 
00667     if (lpBand->uCDret == (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW)) {
00668     nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
00669     nmcd.hdc = hdc;
00670     nmcd.rc = rcBand;
00671     nmcd.rc.right = lpBand->rcCapText.right;
00672     nmcd.rc.bottom = lpBand->rcCapText.bottom;
00673     nmcd.dwItemSpec = lpBand->wID;
00674     nmcd.uItemState = 0;
00675     nmcd.lItemlParam = lpBand->lParam;
00676     lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
00677     }
00678 }
00679 
00680 
00681 static VOID
00682 REBAR_Refresh (const REBAR_INFO *infoPtr, HDC hdc)
00683 {
00684     REBAR_BAND *lpBand;
00685     UINT i;
00686 
00687     if (!infoPtr->DoRedraw) return;
00688 
00689     for (i = 0; i < infoPtr->uNumBands; i++) {
00690     lpBand = REBAR_GetBand(infoPtr, i);
00691 
00692     if (HIDDENBAND(lpBand)) continue;
00693 
00694     /* now draw the band */
00695     TRACE("[%p] drawing band %i, flags=%08x\n",
00696           infoPtr->hwndSelf, i, lpBand->fDraw);
00697     REBAR_DrawBand (hdc, infoPtr, lpBand);
00698     }
00699 }
00700 
00701 
00702 static void
00703 REBAR_CalcHorzBand (const REBAR_INFO *infoPtr, UINT rstart, UINT rend)
00704      /* Function: this routine initializes all the rectangles in */
00705      /*  each band in a row to fit in the adjusted rcBand rect.  */
00706      /* *** Supports only Horizontal bars. ***                   */
00707 {
00708     REBAR_BAND *lpBand;
00709     UINT i, xoff;
00710     RECT work;
00711 
00712     for(i=rstart; i<rend; i++){
00713       lpBand = REBAR_GetBand(infoPtr, i);
00714       if (HIDDENBAND(lpBand)) {
00715           SetRect (&lpBand->rcChild,
00716            lpBand->rcBand.right, lpBand->rcBand.top,
00717            lpBand->rcBand.right, lpBand->rcBand.bottom);
00718       continue;
00719       }
00720 
00721       /* set initial gripper rectangle */
00722       SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
00723            lpBand->rcBand.left, lpBand->rcBand.bottom);
00724 
00725       /* calculate gripper rectangle */
00726       if ( lpBand->fStatus & HAS_GRIPPER) {
00727       lpBand->fDraw |= DRAW_GRIPPER;
00728       lpBand->rcGripper.left   += REBAR_PRE_GRIPPER;
00729       lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
00730       lpBand->rcGripper.top    += 2;
00731       lpBand->rcGripper.bottom -= 2;
00732 
00733       SetRect (&lpBand->rcCapImage,
00734            lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.top,
00735            lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.bottom);
00736       }
00737       else {  /* no gripper will be drawn */
00738       xoff = 0;
00739       if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
00740           /* if no gripper but either image or text, then leave space */
00741           xoff = REBAR_ALWAYS_SPACE;
00742       SetRect (&lpBand->rcCapImage,
00743            lpBand->rcBand.left+xoff, lpBand->rcBand.top,
00744            lpBand->rcBand.left+xoff, lpBand->rcBand.bottom);
00745       }
00746 
00747       /* image is visible */
00748       if (lpBand->fStatus & HAS_IMAGE) {
00749       lpBand->fDraw |= DRAW_IMAGE;
00750       lpBand->rcCapImage.right  += infoPtr->imageSize.cx;
00751       lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
00752 
00753       /* set initial caption text rectangle */
00754       SetRect (&lpBand->rcCapText,
00755            lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1,
00756            lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
00757       }
00758       else {
00759       /* set initial caption text rectangle */
00760       SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1,
00761            lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
00762       }
00763 
00764       /* text is visible */
00765       if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
00766       lpBand->fDraw |= DRAW_TEXT;
00767       lpBand->rcCapText.right = max(lpBand->rcCapText.left,
00768                     lpBand->rcCapText.right-REBAR_POST_TEXT);
00769       }
00770 
00771       /* set initial child window rectangle if there is a child */
00772       if (lpBand->hwndChild) {
00773 
00774           lpBand->rcChild.left  = lpBand->rcBand.left + lpBand->cxHeader;
00775           lpBand->rcChild.right = lpBand->rcBand.right - REBAR_POST_CHILD;
00776 
00777           if (lpBand->cyChild > 0) {
00778 
00779               UINT yoff = (lpBand->rcBand.bottom - lpBand->rcBand.top - lpBand->cyChild) / 2;
00780 
00781               /* center child if height is known */
00782               lpBand->rcChild.top = lpBand->rcBand.top + yoff;
00783               lpBand->rcChild.bottom = lpBand->rcBand.top + yoff + lpBand->cyChild;
00784           }
00785           else {
00786               lpBand->rcChild.top = lpBand->rcBand.top;
00787               lpBand->rcChild.bottom = lpBand->rcBand.bottom;
00788           }
00789 
00790       if ((lpBand->fStyle & RBBS_USECHEVRON) && (lpBand->rcChild.right - lpBand->rcChild.left < lpBand->cxIdeal))
00791       {
00792           lpBand->rcChild.right -= CHEVRON_WIDTH;
00793           SetRect(&lpBand->rcChevron, lpBand->rcChild.right,
00794                   lpBand->rcChild.top, lpBand->rcChild.right + CHEVRON_WIDTH,
00795                   lpBand->rcChild.bottom);
00796       }
00797       }
00798       else {
00799           SetRect (&lpBand->rcChild,
00800            lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
00801            lpBand->rcBand.right, lpBand->rcBand.bottom);
00802       }
00803 
00804       /* flag if notify required and invalidate rectangle */
00805       if (lpBand->fDraw & NTF_INVALIDATE) {
00806           TRACE("invalidating (%d,%d)-(%d,%d)\n",
00807         lpBand->rcBand.left,
00808         lpBand->rcBand.top,
00809         lpBand->rcBand.right + SEP_WIDTH,
00810         lpBand->rcBand.bottom + SEP_WIDTH);
00811       lpBand->fDraw &= ~NTF_INVALIDATE;
00812       work = lpBand->rcBand;
00813       work.right += SEP_WIDTH;
00814       work.bottom += SEP_WIDTH;
00815       InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
00816       if (lpBand->hwndChild) InvalidateRect(lpBand->hwndChild, NULL, TRUE);
00817       }
00818 
00819     }
00820 
00821 }
00822 
00823 
00824 static VOID
00825 REBAR_CalcVertBand (const REBAR_INFO *infoPtr, UINT rstart, UINT rend)
00826      /* Function: this routine initializes all the rectangles in */
00827      /*  each band in a row to fit in the adjusted rcBand rect.  */
00828      /* *** Supports only Vertical bars. ***                     */
00829 {
00830     REBAR_BAND *lpBand;
00831     UINT i, xoff;
00832     RECT work;
00833 
00834     for(i=rstart; i<rend; i++){
00835         RECT rcBand;
00836         lpBand = REBAR_GetBand(infoPtr, i);
00837     if (HIDDENBAND(lpBand)) continue;
00838 
00839         translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
00840 
00841         /* set initial gripper rectangle */
00842     SetRect (&lpBand->rcGripper, rcBand.left, rcBand.top, rcBand.right, rcBand.top);
00843 
00844     /* calculate gripper rectangle */
00845     if (lpBand->fStatus & HAS_GRIPPER) {
00846         lpBand->fDraw |= DRAW_GRIPPER;
00847 
00848         if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) {
00849         /*  vertical gripper  */
00850         lpBand->rcGripper.left   += 3;
00851         lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
00852         lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
00853         lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
00854 
00855         /* initialize Caption image rectangle  */
00856         SetRect (&lpBand->rcCapImage, rcBand.left,
00857              lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
00858              rcBand.right,
00859              lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
00860         }
00861         else {
00862         /*  horizontal gripper  */
00863         lpBand->rcGripper.left   += 2;
00864         lpBand->rcGripper.right  -= 2;
00865         lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
00866         lpBand->rcGripper.bottom  = lpBand->rcGripper.top + GRIPPER_WIDTH;
00867 
00868         /* initialize Caption image rectangle  */
00869         SetRect (&lpBand->rcCapImage, rcBand.left,
00870              lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
00871              rcBand.right,
00872              lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
00873         }
00874     }
00875     else {  /* no gripper will be drawn */
00876         xoff = 0;
00877         if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
00878         /* if no gripper but either image or text, then leave space */
00879         xoff = REBAR_ALWAYS_SPACE;
00880         /* initialize Caption image rectangle  */
00881         SetRect (&lpBand->rcCapImage,
00882                       rcBand.left, rcBand.top+xoff,
00883                       rcBand.right, rcBand.top+xoff);
00884     }
00885 
00886     /* image is visible */
00887     if (lpBand->fStatus & HAS_IMAGE) {
00888         lpBand->fDraw |= DRAW_IMAGE;
00889 
00890         lpBand->rcCapImage.right  = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
00891         lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;
00892 
00893         /* set initial caption text rectangle */
00894         SetRect (&lpBand->rcCapText,
00895              rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
00896              rcBand.right, rcBand.top+lpBand->cxHeader);
00897     }
00898     else {
00899         /* set initial caption text rectangle */
00900         SetRect (&lpBand->rcCapText,
00901              rcBand.left, lpBand->rcCapImage.bottom,
00902              rcBand.right, rcBand.top+lpBand->cxHeader);
00903     }
00904 
00905     /* text is visible */
00906     if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
00907         lpBand->fDraw |= DRAW_TEXT;
00908         lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
00909                        lpBand->rcCapText.bottom);
00910     }
00911 
00912     /* set initial child window rectangle if there is a child */
00913     if (lpBand->hwndChild) {
00914             int cxBand = rcBand.right - rcBand.left;
00915             xoff = (cxBand - lpBand->cyChild) / 2;
00916         SetRect (&lpBand->rcChild,
00917              rcBand.left + xoff,                   rcBand.top + lpBand->cxHeader,
00918                      rcBand.left + xoff + lpBand->cyChild, rcBand.bottom - REBAR_POST_CHILD);
00919     }
00920     else {
00921         SetRect (&lpBand->rcChild,
00922              rcBand.left, rcBand.top+lpBand->cxHeader,
00923              rcBand.right, rcBand.bottom);
00924     }
00925 
00926     if (lpBand->fDraw & NTF_INVALIDATE) {
00927             TRACE("invalidating (%d,%d)-(%d,%d)\n",
00928                   rcBand.left,
00929                   rcBand.top,
00930                   rcBand.right + SEP_WIDTH,
00931                   rcBand.bottom + SEP_WIDTH);
00932         lpBand->fDraw &= ~NTF_INVALIDATE;
00933         work = rcBand;
00934         work.bottom += SEP_WIDTH;
00935         work.right += SEP_WIDTH;
00936         InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
00937         if (lpBand->hwndChild) InvalidateRect(lpBand->hwndChild, NULL, TRUE);
00938     }
00939 
00940     }
00941 }
00942 
00943 
00944 static VOID
00945 REBAR_ForceResize (REBAR_INFO *infoPtr)
00946      /* Function: This changes the size of the REBAR window to that */
00947      /*  calculated by REBAR_Layout.                                */
00948 {
00949     INT x, y, width, height;
00950     INT xedge = 0, yedge = 0;
00951     RECT rcSelf;
00952 
00953     TRACE("new size [%d x %d]\n", infoPtr->calcSize.cx, infoPtr->calcSize.cy);
00954 
00955     if (infoPtr->dwStyle & CCS_NORESIZE)
00956         return;
00957 
00958     if (infoPtr->dwStyle & WS_BORDER)
00959     {
00960         xedge = GetSystemMetrics(SM_CXEDGE);
00961         yedge = GetSystemMetrics(SM_CYEDGE);
00962         /* swap for CCS_VERT? */
00963     }
00964 
00965     /* compute rebar window rect in parent client coordinates */
00966     GetWindowRect(infoPtr->hwndSelf, &rcSelf);
00967     MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->hwndSelf), (LPPOINT)&rcSelf, 2);
00968     translate_rect(infoPtr, &rcSelf, &rcSelf);
00969 
00970     height = infoPtr->calcSize.cy + 2*yedge;
00971     if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) {
00972         RECT rcParent;
00973 
00974         x = -xedge;
00975         width = infoPtr->calcSize.cx + 2*xedge;
00976         y = 0; /* quiet compiler warning */
00977         switch ( infoPtr->dwStyle & CCS_LAYOUT_MASK) {
00978             case 0:     /* shouldn't happen - see NCCreate */
00979             case CCS_TOP:
00980                 y = ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER) - yedge;
00981                 break;
00982             case CCS_NOMOVEY:
00983                 y = rcSelf.top;
00984                 break;
00985             case CCS_BOTTOM:
00986                 GetClientRect(GetParent(infoPtr->hwndSelf), &rcParent);
00987                 translate_rect(infoPtr, &rcParent, &rcParent);
00988                 y = rcParent.bottom - infoPtr->calcSize.cy - yedge;
00989                 break;
00990     }
00991     }
00992     else {
00993     x = rcSelf.left;
00994     /* As on Windows if the CCS_NODIVIDER is not present the control will move
00995      * 2 pixel down after every layout */
00996     y = rcSelf.top + ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
00997     width = rcSelf.right - rcSelf.left;
00998     }
00999 
01000     TRACE("hwnd %p, style=%08x, setting at (%d,%d) for (%d,%d)\n",
01001     infoPtr->hwndSelf, infoPtr->dwStyle, x, y, width, height);
01002 
01003     /* Set flag to ignore next WM_SIZE message and resize the window */
01004     infoPtr->fStatus |= SELF_RESIZE;
01005     if ((infoPtr->dwStyle & CCS_VERT) == 0)
01006         SetWindowPos(infoPtr->hwndSelf, 0, x, y, width, height, SWP_NOZORDER);
01007     else
01008         SetWindowPos(infoPtr->hwndSelf, 0, y, x, height, width, SWP_NOZORDER);
01009     infoPtr->fStatus &= ~SELF_RESIZE;
01010 }
01011 
01012 
01013 static VOID
01014 REBAR_MoveChildWindows (const REBAR_INFO *infoPtr, UINT start, UINT endplus)
01015 {
01016     static const WCHAR strComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
01017     REBAR_BAND *lpBand;
01018     WCHAR szClassName[40];
01019     UINT i;
01020     NMREBARCHILDSIZE  rbcz;
01021     HDWP deferpos;
01022 
01023     if (!(deferpos = BeginDeferWindowPos(infoPtr->uNumBands)))
01024         ERR("BeginDeferWindowPos returned NULL\n");
01025 
01026     for (i = start; i < endplus; i++) {
01027     lpBand = REBAR_GetBand(infoPtr, i);
01028 
01029     if (HIDDENBAND(lpBand)) continue;
01030     if (lpBand->hwndChild) {
01031         TRACE("hwndChild = %p\n", lpBand->hwndChild);
01032 
01033         /* Always generate the RBN_CHILDSIZE even if child
01034            did not change */
01035         rbcz.uBand = i;
01036         rbcz.wID = lpBand->wID;
01037         rbcz.rcChild = lpBand->rcChild;
01038             translate_rect(infoPtr, &rbcz.rcBand, &lpBand->rcBand);
01039         if (infoPtr->dwStyle & CCS_VERT)
01040         rbcz.rcBand.top += lpBand->cxHeader;
01041         else
01042         rbcz.rcBand.left += lpBand->cxHeader;
01043         REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
01044         if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
01045         TRACE("Child rect changed by NOTIFY for band %u\n", i);
01046                 TRACE("    from (%s)  to (%s)\n",
01047                       wine_dbgstr_rect(&lpBand->rcChild),
01048                       wine_dbgstr_rect(&rbcz.rcChild));
01049         lpBand->rcChild = rbcz.rcChild;  /* *** ??? */
01050             }
01051 
01052         /* native (IE4 in "Favorites" frame **1) does:
01053          *   SetRect (&rc, -1, -1, -1, -1)
01054          *   EqualRect (&rc,band->rc???)
01055          *   if ret==0
01056          *     CopyRect (band->rc????, &rc)
01057          *     set flag outside of loop
01058          */
01059 
01060         GetClassNameW (lpBand->hwndChild, szClassName, sizeof(szClassName)/sizeof(szClassName[0]));
01061         if (!lstrcmpW (szClassName, strComboBox) ||
01062         !lstrcmpW (szClassName, WC_COMBOBOXEXW)) {
01063         INT nEditHeight, yPos;
01064         RECT rc;
01065 
01066         /* special placement code for combo or comboex box */
01067 
01068 
01069         /* get size of edit line */
01070         GetWindowRect (lpBand->hwndChild, &rc);
01071         nEditHeight = rc.bottom - rc.top;
01072         yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
01073 
01074         /* center combo box inside child area */
01075         TRACE("moving child (Combo(Ex)) %p to (%d,%d) for (%d,%d)\n",
01076               lpBand->hwndChild,
01077               lpBand->rcChild.left, yPos,
01078               lpBand->rcChild.right - lpBand->rcChild.left,
01079               nEditHeight);
01080         deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
01081                        lpBand->rcChild.left,
01082                        /*lpBand->rcChild.top*/ yPos,
01083                        lpBand->rcChild.right - lpBand->rcChild.left,
01084                        nEditHeight,
01085                        SWP_NOZORDER);
01086         if (!deferpos)
01087             ERR("DeferWindowPos returned NULL\n");
01088         }
01089         else {
01090         TRACE("moving child (Other) %p to (%d,%d) for (%d,%d)\n",
01091               lpBand->hwndChild,
01092               lpBand->rcChild.left, lpBand->rcChild.top,
01093               lpBand->rcChild.right - lpBand->rcChild.left,
01094               lpBand->rcChild.bottom - lpBand->rcChild.top);
01095         deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
01096                        lpBand->rcChild.left,
01097                        lpBand->rcChild.top,
01098                        lpBand->rcChild.right - lpBand->rcChild.left,
01099                        lpBand->rcChild.bottom - lpBand->rcChild.top,
01100                        SWP_NOZORDER);
01101         if (!deferpos)
01102             ERR("DeferWindowPos returned NULL\n");
01103         }
01104     }
01105     }
01106     if (!EndDeferWindowPos(deferpos))
01107         ERR("EndDeferWindowPos returned NULL\n");
01108 
01109     if (infoPtr->DoRedraw)
01110     UpdateWindow (infoPtr->hwndSelf);
01111 
01112     /* native (from **1 above) does:
01113      *      UpdateWindow(rebar)
01114      *      REBAR_ForceResize
01115      *      RBN_HEIGHTCHANGE if necessary
01116      *      if ret from any EqualRect was 0
01117      *         Goto "BeginDeferWindowPos"
01118      */
01119 
01120 }
01121 
01122 /* Returns the next visible band (the first visible band in [i+1; infoPtr->uNumBands) )
01123  * or infoPtr->uNumBands if none */
01124 static int next_visible(const REBAR_INFO *infoPtr, int i)
01125 {
01126     int n;
01127     for (n = i + 1; n < infoPtr->uNumBands; n++)
01128         if (!HIDDENBAND(REBAR_GetBand(infoPtr, n)))
01129             break;
01130     return n;
01131 }
01132 
01133 /* Returns the previous visible band (the last visible band in [0; i) )
01134  * or -1 if none */
01135 static int prev_visible(const REBAR_INFO *infoPtr, int i)
01136 {
01137     int n;
01138     for (n = i - 1; n >= 0; n--)
01139         if (!HIDDENBAND(REBAR_GetBand(infoPtr, n)))
01140             break;
01141     return n;
01142 }
01143 
01144 /* Returns the first visible band or infoPtr->uNumBands if none */
01145 static int first_visible(const REBAR_INFO *infoPtr)
01146 {
01147     return next_visible(infoPtr, -1); /* this works*/
01148 }
01149 
01150 /* Returns the first visible band for the given row (or iBand if none) */
01151 static int get_row_begin_for_band(const REBAR_INFO *infoPtr, INT iBand)
01152 {
01153     int iLastBand = iBand;
01154     int iRow = REBAR_GetBand(infoPtr, iBand)->iRow;
01155     while ((iBand = prev_visible(infoPtr, iBand)) >= 0) {
01156         if (REBAR_GetBand(infoPtr, iBand)->iRow != iRow)
01157             break;
01158         else
01159             iLastBand = iBand;
01160     }
01161     return iLastBand;
01162 }
01163 
01164 /* Returns the first visible band for the next row (or infoPtr->uNumBands if none) */
01165 static int get_row_end_for_band(const REBAR_INFO *infoPtr, INT iBand)
01166 {
01167     int iRow = REBAR_GetBand(infoPtr, iBand)->iRow;
01168     while ((iBand = next_visible(infoPtr, iBand)) < infoPtr->uNumBands)
01169         if (REBAR_GetBand(infoPtr, iBand)->iRow != iRow)
01170             break;
01171     return iBand;
01172 }
01173 
01174 /* Compute the rcBand.{left,right} from the cxEffective bands widths computed earlier.
01175  * iBeginBand must be visible */
01176 static void REBAR_SetRowRectsX(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand)
01177 {
01178     int xPos = 0, i;
01179     for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
01180     {
01181         REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
01182         if (lpBand->rcBand.left != xPos || lpBand->rcBand.right != xPos + lpBand->cxEffective) {
01183             lpBand->fDraw |= NTF_INVALIDATE;
01184             TRACE("Setting rect %d to %d,%d\n", i, xPos, xPos + lpBand->cxEffective);
01185             lpBand->rcBand.left = xPos;
01186             lpBand->rcBand.right = xPos + lpBand->cxEffective;
01187         }
01188         xPos += lpBand->cxEffective + SEP_WIDTH;
01189     }
01190 }
01191 
01192 /* The rationale of this function is probably as follows: if we have some space
01193  * to distribute we want to add it to a band on the right. However we don't want
01194  * to unminimize a minimized band so we search for a band that is big enough.
01195  * For some reason "big enough" is defined as bigger than the minimum size of the
01196  * first band in the row
01197  */
01198 static REBAR_BAND *REBAR_FindBandToGrow(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand)
01199 {
01200     INT cxMinFirstBand = 0, i;
01201 
01202     cxMinFirstBand = REBAR_GetBand(infoPtr, iBeginBand)->cxMinBand;
01203 
01204     for (i = prev_visible(infoPtr, iEndBand); i >= iBeginBand; i = prev_visible(infoPtr, i))
01205         if (REBAR_GetBand(infoPtr, i)->cxEffective > cxMinFirstBand &&
01206           !(REBAR_GetBand(infoPtr, i)->fStyle & RBBS_FIXEDSIZE))
01207             break;
01208 
01209     if (i < iBeginBand)
01210         for (i = prev_visible(infoPtr, iEndBand); i >= iBeginBand; i = prev_visible(infoPtr, i))
01211             if (REBAR_GetBand(infoPtr, i)->cxMinBand == cxMinFirstBand)
01212                 break;
01213 
01214     TRACE("Extra space for row [%d..%d) should be added to band %d\n", iBeginBand, iEndBand, i);
01215     return REBAR_GetBand(infoPtr, i);
01216 }
01217 
01218 /* Try to shrink the visible bands in [iBeginBand; iEndBand) by cxShrink, starting from the right */
01219 static int REBAR_ShrinkBandsRTL(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT cxShrink, BOOL bEnforce)
01220 {
01221     REBAR_BAND *lpBand;
01222     INT width, i;
01223 
01224     TRACE("Shrinking bands [%d..%d) by %d, right-to-left\n", iBeginBand, iEndBand, cxShrink);
01225     for (i = prev_visible(infoPtr, iEndBand); i >= iBeginBand; i = prev_visible(infoPtr, i))
01226     {
01227         lpBand = REBAR_GetBand(infoPtr, i);
01228 
01229         width = max(lpBand->cxEffective - cxShrink, (int)lpBand->cxMinBand);
01230         cxShrink -= lpBand->cxEffective - width;
01231         lpBand->cxEffective = width;
01232         if (bEnforce && lpBand->cx > lpBand->cxEffective)
01233             lpBand->cx = lpBand->cxEffective;
01234         if (cxShrink == 0)
01235             break;
01236     }
01237     return cxShrink;
01238 }
01239 
01240 
01241 /* Try to shrink the visible bands in [iBeginBand; iEndBand) by cxShrink, starting from the left.
01242  * iBeginBand must be visible */
01243 static int REBAR_ShrinkBandsLTR(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT cxShrink, BOOL bEnforce)
01244 {
01245     REBAR_BAND *lpBand;
01246     INT width, i;
01247 
01248     TRACE("Shrinking bands [%d..%d) by %d, left-to-right\n", iBeginBand, iEndBand, cxShrink);
01249     for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
01250     {
01251         lpBand = REBAR_GetBand(infoPtr, i);
01252 
01253         width = max(lpBand->cxEffective - cxShrink, (int)lpBand->cxMinBand);
01254         cxShrink -= lpBand->cxEffective - width;
01255         lpBand->cxEffective = width;
01256         if (bEnforce)
01257             lpBand->cx = lpBand->cxEffective;
01258         if (cxShrink == 0)
01259             break;
01260     }
01261     return cxShrink;
01262 }
01263 
01264 /* Tries to move a band to a given offset within a row. */
01265 static int REBAR_MoveBandToRowOffset(REBAR_INFO *infoPtr, INT iBand, INT iFirstBand,
01266     INT iLastBand, INT xOff, BOOL reorder)
01267 {
01268     REBAR_BAND *insertBand = REBAR_GetBand(infoPtr, iBand);
01269     int xPos = 0, i;
01270     const BOOL setBreak = REBAR_GetBand(infoPtr, iFirstBand)->fStyle & RBBS_BREAK;
01271 
01272     /* Find the band's new position */
01273     if(reorder)
01274     {
01275         /* Used during an LR band reorder drag */
01276         for (i = iFirstBand; i < iLastBand; i = next_visible(infoPtr, i))
01277         {
01278             if(xPos > xOff)
01279                 break;
01280             xPos += REBAR_GetBand(infoPtr, i)->cxEffective + SEP_WIDTH;
01281         }
01282     }
01283     else
01284     {
01285         /* Used during a UD band insertion drag */
01286         for (i = iFirstBand; i < iLastBand; i = next_visible(infoPtr, i))
01287         {
01288             const REBAR_BAND *band = REBAR_GetBand(infoPtr, i);
01289             if(xPos + band->cxMinBand / 2 > xOff)
01290                 break;
01291             xPos += band->cxEffective + SEP_WIDTH;
01292         }
01293     }
01294 
01295     /* Move the band to its new position */
01296     DPA_DeletePtr(infoPtr->bands, iBand);
01297     if(i > iBand)
01298         i--;
01299     DPA_InsertPtr(infoPtr->bands, i, insertBand);
01300 
01301     /* Ensure only the last band has the RBBS_BREAK flag set */
01302     insertBand->fStyle &= ~RBBS_BREAK;
01303     if(setBreak)
01304         REBAR_GetBand(infoPtr, iFirstBand)->fStyle |= RBBS_BREAK;
01305 
01306     /* Return the currently grabbed band */
01307     if(infoPtr->iGrabbedBand == iBand)
01308     {
01309         infoPtr->iGrabbedBand = i;
01310         return i;
01311     }
01312     else return -1;
01313 }
01314 
01315 /* Set the heights of the visible bands in [iBeginBand; iEndBand) to the max height. iBeginBand must be visible */
01316 static int REBAR_SetBandsHeight(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT yStart)
01317 {
01318     REBAR_BAND *lpBand;
01319     int yMaxHeight = 0;
01320     int yPos = yStart;
01321     int row = REBAR_GetBand(infoPtr, iBeginBand)->iRow;
01322     int i;
01323     for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
01324     {
01325         lpBand = REBAR_GetBand(infoPtr, i);
01326         lpBand->cyRowSoFar = yMaxHeight;
01327         yMaxHeight = max(yMaxHeight, lpBand->cyMinBand);
01328     }
01329     TRACE("Bands [%d; %d) height: %d\n", iBeginBand, iEndBand, yMaxHeight);
01330 
01331     for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
01332     {
01333         lpBand = REBAR_GetBand(infoPtr, i);
01334         /* we may be called for multiple rows if RBS_VARHEIGHT not set */
01335         if (lpBand->iRow != row) {
01336             yPos += yMaxHeight + SEP_WIDTH;
01337             row = lpBand->iRow;
01338         }
01339 
01340         if (lpBand->rcBand.top != yPos || lpBand->rcBand.bottom != yPos + yMaxHeight) {
01341             lpBand->fDraw |= NTF_INVALIDATE;
01342             lpBand->rcBand.top = yPos;
01343             lpBand->rcBand.bottom = yPos + yMaxHeight;
01344             TRACE("Band %d: %s\n", i, wine_dbgstr_rect(&lpBand->rcBand));
01345         }
01346     }
01347     return yPos + yMaxHeight;
01348 }
01349 
01350 /* Layout the row [iBeginBand; iEndBand). iBeginBand must be visible */
01351 static void REBAR_LayoutRow(const REBAR_INFO *infoPtr, int iBeginBand, int iEndBand, int cx, int *piRow, int *pyPos)
01352 {
01353     REBAR_BAND *lpBand;
01354     int i, extra;
01355     int width = 0;
01356 
01357     TRACE("Adjusting row [%d;%d). Width: %d\n", iBeginBand, iEndBand, cx);
01358     for (i = iBeginBand; i < iEndBand; i++)
01359         REBAR_GetBand(infoPtr, i)->iRow = *piRow;
01360 
01361     /* compute the extra space */
01362     for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
01363     {
01364         lpBand = REBAR_GetBand(infoPtr, i);
01365         if (i > iBeginBand)
01366             width += SEP_WIDTH;
01367         lpBand->cxEffective = max(lpBand->cxMinBand, lpBand->cx);
01368         width += lpBand->cxEffective;
01369     }
01370 
01371     extra = cx - width;
01372     TRACE("Extra space: %d\n", extra);
01373     if (extra < 0) {
01374         int ret = REBAR_ShrinkBandsRTL(infoPtr, iBeginBand, iEndBand, -extra, FALSE);
01375         if (ret > 0 && next_visible(infoPtr, iBeginBand) != iEndBand)  /* one band may be longer than expected... */
01376             ERR("Error layouting row %d - couldn't shrink for %d pixels (%d total shrink)\n", *piRow, ret, -extra);
01377     } else
01378     if (extra > 0) {
01379         lpBand = REBAR_FindBandToGrow(infoPtr, iBeginBand, iEndBand);
01380         lpBand->cxEffective += extra;
01381     }
01382 
01383     REBAR_SetRowRectsX(infoPtr, iBeginBand, iEndBand);
01384     if (infoPtr->dwStyle & RBS_VARHEIGHT)
01385     {
01386         if (*piRow > 0)
01387             *pyPos += SEP_WIDTH;
01388         *pyPos = REBAR_SetBandsHeight(infoPtr, iBeginBand, iEndBand, *pyPos);
01389     }
01390     (*piRow)++;
01391 }
01392 
01393 static VOID
01394 REBAR_Layout(REBAR_INFO *infoPtr)
01395 {
01396     REBAR_BAND *lpBand;
01397     RECT rcAdj;
01398     SIZE oldSize;
01399     INT adjcx, i;
01400     INT rowstart;
01401     INT row = 0;
01402     INT xMin, yPos;
01403 
01404     if (infoPtr->dwStyle & (CCS_NORESIZE | CCS_NOPARENTALIGN) || GetParent(infoPtr->hwndSelf) == NULL)
01405         GetClientRect(infoPtr->hwndSelf, &rcAdj);
01406     else
01407         GetClientRect(GetParent(infoPtr->hwndSelf), &rcAdj);
01408     TRACE("adjustment rect is (%s)\n", wine_dbgstr_rect(&rcAdj));
01409 
01410     adjcx = get_rect_cx(infoPtr, &rcAdj);
01411 
01412     if (infoPtr->uNumBands == 0) {
01413         TRACE("No bands - setting size to (0,%d), vert: %x\n", adjcx, infoPtr->dwStyle & CCS_VERT);
01414         infoPtr->calcSize.cx = adjcx;
01415         /* the calcSize.cy won't change for a 0 band rebar */
01416         infoPtr->uNumRows = 0;
01417         REBAR_ForceResize(infoPtr);
01418         return;
01419     }
01420 
01421     yPos = 0;
01422     xMin = 0;
01423     rowstart = first_visible(infoPtr);
01424     /* divide rows */
01425     for (i = rowstart; i < infoPtr->uNumBands; i = next_visible(infoPtr, i))
01426     {
01427         lpBand = REBAR_GetBand(infoPtr, i);
01428 
01429         if (i > rowstart && (lpBand->fStyle & RBBS_BREAK || xMin + lpBand->cxMinBand > adjcx)) {
01430             TRACE("%s break on band %d\n", (lpBand->fStyle & RBBS_BREAK ? "Hard" : "Soft"), i - 1);
01431             REBAR_LayoutRow(infoPtr, rowstart, i, adjcx, &row, &yPos);
01432             rowstart = i;
01433             xMin = 0;
01434         }
01435         else
01436             xMin += SEP_WIDTH;
01437 
01438         xMin += lpBand->cxMinBand;
01439     }
01440     if (rowstart < infoPtr->uNumBands)
01441         REBAR_LayoutRow(infoPtr, rowstart, infoPtr->uNumBands, adjcx, &row, &yPos);
01442 
01443     if (!(infoPtr->dwStyle & RBS_VARHEIGHT))
01444         yPos = REBAR_SetBandsHeight(infoPtr, first_visible(infoPtr), infoPtr->uNumBands, 0);
01445 
01446     infoPtr->uNumRows = row;
01447 
01448     if (infoPtr->dwStyle & CCS_VERT)
01449         REBAR_CalcVertBand(infoPtr, 0, infoPtr->uNumBands);
01450     else
01451         REBAR_CalcHorzBand(infoPtr, 0, infoPtr->uNumBands);
01452     /* now compute size of Rebar itself */
01453     oldSize = infoPtr->calcSize;
01454 
01455     infoPtr->calcSize.cx = adjcx;
01456     infoPtr->calcSize.cy = yPos;
01457     TRACE("calcsize size=(%d, %d), origheight=(%d,%d)\n",
01458             infoPtr->calcSize.cx, infoPtr->calcSize.cy,
01459         oldSize.cx, oldSize.cy);
01460 
01461     REBAR_DumpBand (infoPtr);
01462     REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
01463     REBAR_ForceResize (infoPtr);
01464 
01465     /* note: after a RBN_HEIGHTCHANGE native sends once again all the RBN_CHILDSIZE
01466      * and does another ForceResize */
01467     if (oldSize.cy != infoPtr->calcSize.cy)
01468     {
01469         NMHDR heightchange;
01470         REBAR_Notify(&heightchange, infoPtr, RBN_HEIGHTCHANGE);
01471         REBAR_AutoSize(infoPtr, FALSE);
01472     }
01473 }
01474 
01475 /* iBeginBand must be visible */
01476 static int
01477 REBAR_SizeChildrenToHeight(const REBAR_INFO *infoPtr, int iBeginBand, int iEndBand, int extra, BOOL *fChanged)
01478 {
01479     int cyBandsOld;
01480     int cyBandsNew = 0;
01481     int i;
01482 
01483     TRACE("[%d;%d) by %d\n", iBeginBand, iEndBand, extra);
01484 
01485     cyBandsOld = REBAR_GetBand(infoPtr, iBeginBand)->rcBand.bottom -
01486                  REBAR_GetBand(infoPtr, iBeginBand)->rcBand.top;
01487     for (i = iBeginBand; i < iEndBand; i = next_visible(infoPtr, i))
01488     {
01489         REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
01490         int cyMaxChild = cyBandsOld - REBARSPACE(lpBand) + extra;
01491         int cyChild = round_child_height(lpBand, cyMaxChild);
01492 
01493         if (lpBand->hwndChild && cyChild != lpBand->cyChild && (lpBand->fStyle & RBBS_VARIABLEHEIGHT))
01494         {
01495             TRACE("Resizing %d: %d -> %d [%d]\n", i, lpBand->cyChild, cyChild, lpBand->cyMaxChild);
01496             *fChanged = TRUE;
01497             lpBand->cyChild = cyChild;
01498             lpBand->fDraw |= NTF_INVALIDATE;
01499             update_min_band_height(infoPtr, lpBand);
01500         }
01501         cyBandsNew = max(cyBandsNew, lpBand->cyMinBand);
01502     }
01503     return cyBandsNew - cyBandsOld;
01504 }
01505 
01506 /* worker function for RB_SIZETORECT and RBS_AUTOSIZE */
01507 static VOID
01508 REBAR_SizeToHeight(REBAR_INFO *infoPtr, int height)
01509 {
01510     int extra = height - infoPtr->calcSize.cy;  /* may be negative */
01511     BOOL fChanged = FALSE;
01512     UINT uNumRows = infoPtr->uNumRows;
01513     int i;
01514 
01515     if (uNumRows == 0)  /* avoid division by 0 */
01516         return;
01517 
01518     /* That's not exactly what Windows does but should be similar */
01519 
01520     /* Pass one: break-up/glue rows */
01521     if (extra > 0)
01522     {
01523         for (i = prev_visible(infoPtr, infoPtr->uNumBands); i > 0; i = prev_visible(infoPtr, i))
01524         {
01525             REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
01526             int cyBreakExtra;  /* additional cy for the rebar after a RBBS_BREAK on this band */
01527 
01528             height = lpBand->rcBand.bottom - lpBand->rcBand.top;
01529 
01530             if (infoPtr->dwStyle & RBS_VARHEIGHT)
01531                 cyBreakExtra = lpBand->cyRowSoFar; /* 'height' => 'lpBand->cyRowSoFar' + 'height'*/
01532             else
01533                 cyBreakExtra = height;             /* 'height' => 'height' + 'height'*/
01534             cyBreakExtra += SEP_WIDTH;
01535 
01536             if (extra <= cyBreakExtra / 2)
01537                 break;
01538 
01539             if (!(lpBand->fStyle & RBBS_BREAK))
01540             {
01541                 TRACE("Adding break on band %d - extra %d -> %d\n", i, extra, extra - cyBreakExtra);
01542                 lpBand->fStyle |= RBBS_BREAK;
01543                 lpBand->fDraw |= NTF_INVALIDATE;
01544                 fChanged = TRUE;
01545                 extra -= cyBreakExtra;
01546                 uNumRows++;
01547                 /* temporary change for _SizeControlsToHeight. The true values will be computed in _Layout */
01548                 if (infoPtr->dwStyle & RBS_VARHEIGHT)
01549                     lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->cyMinBand;
01550             }
01551         }
01552     }
01553     /* TODO: else if (extra < 0) { try to remove some RBBS_BREAKs } */
01554 
01555     /* Pass two: increase/decrease control height */
01556     if (infoPtr->dwStyle & RBS_VARHEIGHT)
01557     {
01558         int i = first_visible(infoPtr);
01559         int iRow = 0;
01560         while (i < infoPtr->uNumBands)
01561         {
01562             REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, i);
01563             int extraForRow = extra / (int)(uNumRows - iRow);
01564             int rowEnd;
01565 
01566             /* we can't use get_row_end_for_band as we might have added RBBS_BREAK in the first phase */
01567             for (rowEnd = next_visible(infoPtr, i); rowEnd < infoPtr->uNumBands; rowEnd = next_visible(infoPtr, rowEnd))
01568                 if (REBAR_GetBand(infoPtr, rowEnd)->iRow != lpBand->iRow ||
01569                     REBAR_GetBand(infoPtr, rowEnd)->fStyle & RBBS_BREAK)
01570                     break;
01571 
01572             extra -= REBAR_SizeChildrenToHeight(infoPtr, i, rowEnd, extraForRow, &fChanged);
01573             TRACE("extra = %d\n", extra);
01574             i = rowEnd;
01575             iRow++;
01576         }
01577     }
01578     else
01579         REBAR_SizeChildrenToHeight(infoPtr, first_visible(infoPtr), infoPtr->uNumBands, extra / infoPtr->uNumRows, &fChanged);
01580 
01581     if (fChanged)
01582         REBAR_Layout(infoPtr);
01583 }
01584 
01585 static VOID
01586 REBAR_AutoSize(REBAR_INFO *infoPtr, BOOL needsLayout)
01587 {
01588     RECT rc, rcNew;
01589     NMRBAUTOSIZE autosize;
01590 
01591     if (needsLayout)
01592         REBAR_Layout(infoPtr);
01593     GetClientRect(infoPtr->hwndSelf, &rc);
01594     REBAR_SizeToHeight(infoPtr, get_rect_cy(infoPtr, &rc));
01595     GetClientRect(infoPtr->hwndSelf, &rcNew);
01596 
01597     GetClientRect(infoPtr->hwndSelf, &autosize.rcTarget);
01598     autosize.fChanged = (memcmp(&rc, &rcNew, sizeof(RECT)) == 0);
01599     autosize.rcTarget = rc;
01600     autosize.rcActual = rcNew;
01601     REBAR_Notify((NMHDR *)&autosize, infoPtr, RBN_AUTOSIZE);
01602 }
01603 
01604 static VOID
01605 REBAR_ValidateBand (const REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
01606      /* Function:  This routine evaluates the band specs supplied */
01607      /*  by the user and updates the following 5 fields in        */
01608      /*  the internal band structure: cxHeader, cyHeader, cxMinBand, cyMinBand, fStatus */
01609 {
01610     UINT header=0;
01611     UINT textheight=0, imageheight = 0;
01612     UINT i, nonfixed;
01613     REBAR_BAND *tBand;
01614 
01615     lpBand->fStatus = 0;
01616     lpBand->cxMinBand = 0;
01617     lpBand->cyMinBand = 0;
01618 
01619     /* Data coming in from users into the cx... and cy... fields   */
01620     /* may be bad, just garbage, because the user never clears     */
01621     /* the fields. RB_{SET|INSERT}BAND{A|W} just passes the data   */
01622     /* along if the fields exist in the input area. Here we must   */
01623     /* determine if the data is valid. I have no idea how MS does  */
01624     /* the validation, but it does because the RB_GETBANDINFO      */
01625     /* returns a 0 when I know the sample program passed in an     */
01626     /* address. Here I will use the algorithm that if the value    */
01627     /* is greater than 65535 then it is bad and replace it with    */
01628     /* a zero. Feel free to improve the algorithm.  -  GA 12/2000  */
01629     if (lpBand->cxMinChild > 65535) lpBand->cxMinChild = 0;
01630     if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0;
01631     if (lpBand->cx         > 65535) lpBand->cx         = 0;
01632     if (lpBand->cyChild    > 65535) lpBand->cyChild    = 0;
01633     if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0;
01634     if (lpBand->cxIdeal    > 65535) lpBand->cxIdeal    = 0;
01635     if (lpBand->cxHeader   > 65535) lpBand->cxHeader   = 0;
01636 
01637     /* TODO : we could try return to the caller if a value changed so that */
01638     /*        a REBAR_Layout is needed. Till now the caller should call it */
01639     /*        it always (we should also check what native does)            */
01640 
01641     /* Header is where the image, text and gripper exist  */
01642     /* in the band and precede the child window.          */
01643 
01644     /* count number of non-FIXEDSIZE and non-Hidden bands */
01645     nonfixed = 0;
01646     for (i=0; i<infoPtr->uNumBands; i++){
01647     tBand = REBAR_GetBand(infoPtr, i);
01648     if (!HIDDENBAND(tBand) && !(tBand->fStyle & RBBS_FIXEDSIZE))
01649         nonfixed++;
01650     }
01651 
01652     /* calculate gripper rectangle */
01653     if (  (!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
01654       ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
01655         ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (nonfixed > 1)))
01656        ) {
01657     lpBand->fStatus |= HAS_GRIPPER;
01658         if (infoPtr->dwStyle & CCS_VERT)
01659         if (infoPtr->dwStyle & RBS_VERTICALGRIPPER)
01660                 header += (GRIPPER_HEIGHT + REBAR_PRE_GRIPPER);
01661             else
01662             header += (GRIPPER_WIDTH + REBAR_PRE_GRIPPER);
01663         else
01664             header += (REBAR_PRE_GRIPPER + GRIPPER_WIDTH);
01665         /* Always have 4 pixels before anything else */
01666         header += REBAR_ALWAYS_SPACE;
01667     }
01668 
01669     /* image is visible */
01670     if (lpBand->iImage != -1 && (infoPtr->himl)) {
01671     lpBand->fStatus |= HAS_IMAGE;
01672         if (infoPtr->dwStyle & CCS_VERT) {
01673        header += (infoPtr->imageSize.cy + REBAR_POST_IMAGE);
01674            imageheight = infoPtr->imageSize.cx + 4;
01675     }
01676     else {
01677        header += (infoPtr->imageSize.cx + REBAR_POST_IMAGE);
01678            imageheight = infoPtr->imageSize.cy + 4;
01679     }
01680     }
01681 
01682     /* text is visible */
01683     if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText) &&
01684         !(lpBand->fStyle & RBBS_HIDETITLE)) {
01685     HDC hdc = GetDC (0);
01686     HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
01687     SIZE size;
01688 
01689     lpBand->fStatus |= HAS_TEXT;
01690     GetTextExtentPoint32W (hdc, lpBand->lpText,
01691                    lstrlenW (lpBand->lpText), &size);
01692     header += ((infoPtr->dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT));
01693     textheight = (infoPtr->dwStyle & CCS_VERT) ? 0 : size.cy;
01694 
01695     SelectObject (hdc, hOldFont);
01696     ReleaseDC (0, hdc);
01697     }
01698 
01699     /* if no gripper but either image or text, then leave space */
01700     if ((lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) &&
01701     !(lpBand->fStatus & HAS_GRIPPER)) {
01702     header += REBAR_ALWAYS_SPACE;
01703     }
01704 
01705     /* check if user overrode the header value */
01706     if (!(lpBand->fStyle & RBBS_UNDOC_FIXEDHEADER))
01707         lpBand->cxHeader = header;
01708     lpBand->cyHeader = max(textheight, imageheight);
01709 
01710     /* Now compute minimum size of child window */
01711     update_min_band_height(infoPtr, lpBand);       /* update lpBand->cyMinBand from cyHeader and cyChild*/
01712 
01713     lpBand->cxMinBand = lpBand->cxMinChild + lpBand->cxHeader + REBAR_POST_CHILD;
01714     if (lpBand->fStyle & RBBS_USECHEVRON && lpBand->cxMinChild < lpBand->cxIdeal)
01715         lpBand->cxMinBand += CHEVRON_WIDTH;
01716 }
01717 
01718 static UINT
01719 REBAR_CommonSetupBand(HWND hwnd, const REBARBANDINFOW *lprbbi, REBAR_BAND *lpBand)
01720      /* Function:  This routine copies the supplied values from   */
01721      /*  user input (lprbbi) to the internal band structure.      */
01722      /*  It returns the mask of what changed.   */
01723 {
01724     UINT uChanged = 0x0;
01725 
01726     lpBand->fMask |= lprbbi->fMask;
01727 
01728     if( (lprbbi->fMask & RBBIM_STYLE) &&
01729         (lpBand->fStyle != lprbbi->fStyle ) )
01730     {
01731     lpBand->fStyle = lprbbi->fStyle;
01732         uChanged |= RBBIM_STYLE;
01733     }
01734 
01735     if( (lprbbi->fMask & RBBIM_COLORS) &&
01736        ( ( lpBand->clrFore != lprbbi->clrFore ) ||
01737          ( lpBand->clrBack != lprbbi->clrBack ) ) )
01738     {
01739     lpBand->clrFore = lprbbi->clrFore;
01740     lpBand->clrBack = lprbbi->clrBack;
01741         uChanged |= RBBIM_COLORS;
01742     }
01743 
01744     if( (lprbbi->fMask & RBBIM_IMAGE) &&
01745        ( lpBand->iImage != lprbbi->iImage ) )
01746     {
01747     lpBand->iImage = lprbbi->iImage;
01748         uChanged |= RBBIM_IMAGE;
01749     }
01750 
01751     if( (lprbbi->fMask & RBBIM_CHILD) &&
01752        (lprbbi->hwndChild != lpBand->hwndChild ) )
01753     {
01754     if (lprbbi->hwndChild) {
01755         lpBand->hwndChild = lprbbi->hwndChild;
01756         lpBand->hwndPrevParent =
01757         SetParent (lpBand->hwndChild, hwnd);
01758         /* below in trace from WinRAR */
01759         ShowWindow(lpBand->hwndChild, SW_SHOWNOACTIVATE | SW_SHOWNORMAL);
01760         /* above in trace from WinRAR */
01761     }
01762     else {
01763         TRACE("child: %p  prev parent: %p\n",
01764            lpBand->hwndChild, lpBand->hwndPrevParent);
01765         lpBand->hwndChild = 0;
01766         lpBand->hwndPrevParent = 0;
01767     }
01768         uChanged |= RBBIM_CHILD;
01769     }
01770 
01771     if( (lprbbi->fMask & RBBIM_CHILDSIZE) &&
01772         ( (lpBand->cxMinChild != lprbbi->cxMinChild) ||
01773           (lpBand->cyMinChild != lprbbi->cyMinChild ) ||
01774           ( (lprbbi->cbSize >= REBARBANDINFOA_V6_SIZE && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) &&
01775             ( (lpBand->cyChild    != lprbbi->cyChild ) ||
01776               (lpBand->cyMaxChild != lprbbi->cyMaxChild ) ||
01777               (lpBand->cyIntegral != lprbbi->cyIntegral ) ) ) ||
01778           ( (lprbbi->cbSize < REBARBANDINFOA_V6_SIZE) &&
01779             ( (lpBand->cyChild || 
01780                lpBand->cyMaxChild || 
01781                lpBand->cyIntegral ) ) ) ) )
01782     {
01783     lpBand->cxMinChild = lprbbi->cxMinChild;
01784     lpBand->cyMinChild = lprbbi->cyMinChild;
01785         /* These fields where added in WIN32_IE == 0x400 and are set only for RBBS_VARIABLEHEIGHT bands */
01786         if (lprbbi->cbSize >= REBARBANDINFOA_V6_SIZE && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
01787         lpBand->cyMaxChild = lprbbi->cyMaxChild;
01788             lpBand->cyIntegral = lprbbi->cyIntegral;
01789 
01790             lpBand->cyChild = round_child_height(lpBand, lprbbi->cyChild);  /* make (cyChild - cyMinChild) a multiple of cyIntergral */
01791         }
01792     else {
01793         lpBand->cyChild    = lpBand->cyMinChild;
01794         lpBand->cyMaxChild = 0x7fffffff;
01795         lpBand->cyIntegral = 0;
01796     }
01797         uChanged |= RBBIM_CHILDSIZE;
01798     }
01799 
01800     if( (lprbbi->fMask & RBBIM_SIZE) &&
01801         (lpBand->cx != lprbbi->cx ) )
01802     {
01803     lpBand->cx = lprbbi->cx;
01804         uChanged |= RBBIM_SIZE;
01805     }
01806 
01807     if( (lprbbi->fMask & RBBIM_BACKGROUND) &&
01808        ( lpBand->hbmBack != lprbbi->hbmBack ) )
01809     {
01810     lpBand->hbmBack = lprbbi->hbmBack;
01811         uChanged |= RBBIM_BACKGROUND;
01812     }
01813 
01814     if( (lprbbi->fMask & RBBIM_ID) &&
01815         (lpBand->wID != lprbbi->wID ) )
01816     {
01817     lpBand->wID = lprbbi->wID;
01818         uChanged |= RBBIM_ID;
01819     }
01820 
01821     /* check for additional data */
01822     if (lprbbi->cbSize >= REBARBANDINFOA_V6_SIZE) {
01823     if( (lprbbi->fMask & RBBIM_IDEALSIZE) &&
01824             ( lpBand->cxIdeal != lprbbi->cxIdeal ) )
01825         {
01826         lpBand->cxIdeal = lprbbi->cxIdeal;
01827             uChanged |= RBBIM_IDEALSIZE;
01828         }
01829 
01830     if( (lprbbi->fMask & RBBIM_LPARAM) &&
01831             (lpBand->lParam != lprbbi->lParam ) )
01832         {
01833         lpBand->lParam = lprbbi->lParam;
01834             uChanged |= RBBIM_LPARAM;
01835         }
01836 
01837     if( (lprbbi->fMask & RBBIM_HEADERSIZE) &&
01838             (lpBand->cxHeader != lprbbi->cxHeader ) )
01839         {
01840         lpBand->cxHeader = lprbbi->cxHeader;
01841             lpBand->fStyle |= RBBS_UNDOC_FIXEDHEADER;
01842             uChanged |= RBBIM_HEADERSIZE;
01843         }
01844     }
01845 
01846     return uChanged;
01847 }
01848 
01849 static LRESULT REBAR_EraseBkGnd (const REBAR_INFO *infoPtr, HDC hdc)
01850      /* Function:  This erases the background rectangle by drawing  */
01851      /*  each band with its background color (or the default) and   */
01852      /*  draws each bands right separator if necessary. The row     */
01853      /*  separators are drawn on the first band of the next row.    */
01854 {
01855     REBAR_BAND *lpBand;
01856     UINT i;
01857     INT oldrow;
01858     RECT cr;
01859     COLORREF old = CLR_NONE, new;
01860     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
01861 
01862     GetClientRect (infoPtr->hwndSelf, &cr);
01863 
01864     oldrow = -1;
01865     for(i=0; i<infoPtr->uNumBands; i++) {
01866         RECT rcBand;
01867         lpBand = REBAR_GetBand(infoPtr, i);
01868     if (HIDDENBAND(lpBand)) continue;
01869         translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
01870 
01871     /* draw band separator between rows */
01872     if (lpBand->iRow != oldrow) {
01873         oldrow = lpBand->iRow;
01874         if (infoPtr->dwStyle & RBS_BANDBORDERS) {
01875         RECT rcRowSep;
01876         rcRowSep = rcBand;
01877         if (infoPtr->dwStyle & CCS_VERT) {
01878             rcRowSep.right += SEP_WIDTH_SIZE;
01879             rcRowSep.bottom = infoPtr->calcSize.cx;
01880                     if (theme)
01881                         DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_RIGHT, NULL);
01882                     else
01883                 DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
01884         }
01885         else {
01886             rcRowSep.bottom += SEP_WIDTH_SIZE;
01887             rcRowSep.right = infoPtr->calcSize.cx;
01888                     if (theme)
01889                         DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_BOTTOM, NULL);
01890                     else
01891                 DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
01892         }
01893                 TRACE ("drawing band separator bottom (%s)\n",
01894                        wine_dbgstr_rect(&rcRowSep));
01895         }
01896     }
01897 
01898     /* draw band separator between bands in a row */
01899         if (infoPtr->dwStyle & RBS_BANDBORDERS && lpBand->rcBand.left > 0) {
01900         RECT rcSep;
01901         rcSep = rcBand;
01902         if (infoPtr->dwStyle & CCS_VERT) {
01903                 rcSep.bottom = rcSep.top;
01904         rcSep.top -= SEP_WIDTH_SIZE;
01905                 if (theme)
01906                     DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_BOTTOM, NULL);
01907                 else
01908             DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
01909         }
01910         else {
01911                 rcSep.right = rcSep.left;
01912         rcSep.left -= SEP_WIDTH_SIZE;
01913                 if (theme)
01914                     DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_RIGHT, NULL);
01915                 else
01916             DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
01917         }
01918             TRACE("drawing band separator right (%s)\n",
01919                   wine_dbgstr_rect(&rcSep));
01920     }
01921 
01922     /* draw the actual background */
01923     if (lpBand->clrBack != CLR_NONE) {
01924         new = (lpBand->clrBack == CLR_DEFAULT) ? infoPtr->clrBtnFace :
01925             lpBand->clrBack;
01926 #if GLATESTING
01927         /* testing only - make background green to see it */
01928         new = RGB(0,128,0);
01929 #endif
01930     }
01931     else {
01932         /* In the absence of documentation for Rebar vs. CLR_NONE,
01933          * we will use the default BtnFace color. Note documentation
01934          * exists for Listview and Imagelist.
01935          */
01936         new = infoPtr->clrBtnFace;
01937 #if GLATESTING
01938         /* testing only - make background green to see it */
01939         new = RGB(0,128,0);
01940 #endif
01941     }
01942 
01943         if (theme)
01944         {
01945             /* When themed, the background color is ignored (but not a
01946              * background bitmap */
01947             DrawThemeBackground (theme, hdc, 0, 0, &cr, &rcBand);
01948         }
01949         else
01950         {
01951             old = SetBkColor (hdc, new);
01952             TRACE("%s background color=0x%06x, band %s\n",
01953                   (lpBand->clrBack == CLR_NONE) ? "none" :
01954                     ((lpBand->clrBack == CLR_DEFAULT) ? "dft" : ""),
01955                   GetBkColor(hdc), wine_dbgstr_rect(&rcBand));
01956             ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rcBand, NULL, 0, 0);
01957             if (lpBand->clrBack != CLR_NONE)
01958                 SetBkColor (hdc, old);
01959         }
01960     }
01961     return TRUE;
01962 }
01963 
01964 static void
01965 REBAR_InternalHitTest (const REBAR_INFO *infoPtr, const POINT *lpPt, UINT *pFlags, INT *pBand)
01966 {
01967     REBAR_BAND *lpBand;
01968     RECT rect;
01969     UINT  iCount;
01970 
01971     GetClientRect (infoPtr->hwndSelf, &rect);
01972 
01973     *pFlags = RBHT_NOWHERE;
01974     if (PtInRect (&rect, *lpPt))
01975     {
01976     if (infoPtr->uNumBands == 0) {
01977         *pFlags = RBHT_NOWHERE;
01978         if (pBand)
01979         *pBand = -1;
01980         TRACE("NOWHERE\n");
01981         return;
01982     }
01983     else {
01984         /* somewhere inside */
01985         for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
01986                 RECT rcBand;
01987         lpBand = REBAR_GetBand(infoPtr, iCount);
01988                 translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
01989                 if (HIDDENBAND(lpBand)) continue;
01990         if (PtInRect (&rcBand, *lpPt)) {
01991             if (pBand)
01992             *pBand = iCount;
01993             if (PtInRect (&lpBand->rcGripper, *lpPt)) {
01994             *pFlags = RBHT_GRABBER;
01995             TRACE("ON GRABBER %d\n", iCount);
01996             return;
01997             }
01998             else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
01999             *pFlags = RBHT_CAPTION;
02000             TRACE("ON CAPTION %d\n", iCount);
02001             return;
02002             }
02003             else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
02004             *pFlags = RBHT_CAPTION;
02005             TRACE("ON CAPTION %d\n", iCount);
02006             return;
02007             }
02008             else if (PtInRect (&lpBand->rcChild, *lpPt)) {
02009             *pFlags = RBHT_CLIENT;
02010             TRACE("ON CLIENT %d\n", iCount);
02011             return;
02012             }
02013             else if (PtInRect (&lpBand->rcChevron, *lpPt)) {
02014             *pFlags = RBHT_CHEVRON;
02015             TRACE("ON CHEVRON %d\n", iCount);
02016             return;
02017             }
02018             else {
02019             *pFlags = RBHT_NOWHERE;
02020             TRACE("NOWHERE %d\n", iCount);
02021             return;
02022             }
02023         }
02024         }
02025 
02026         *pFlags = RBHT_NOWHERE;
02027         if (pBand)
02028         *pBand = -1;
02029 
02030         TRACE("NOWHERE\n");
02031         return;
02032     }
02033     }
02034     else {
02035     *pFlags = RBHT_NOWHERE;
02036     if (pBand)
02037         *pBand = -1;
02038     TRACE("NOWHERE\n");
02039     return;
02040     }
02041 }
02042 
02043 static void
02044 REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
02045      /* Function:  This will implement the functionality of a     */
02046      /*  Gripper drag within a row. It will not implement "out-   */
02047      /*  of-row" drags. (They are detected and handled in         */
02048      /*  REBAR_MouseMove.)                                        */
02049 {
02050     REBAR_BAND *hitBand;
02051     INT iHitBand, iRowBegin, iRowEnd;
02052     INT movement, xBand, cxLeft = 0;
02053     BOOL shrunkBands = FALSE;
02054 
02055     iHitBand = infoPtr->iGrabbedBand;
02056     iRowBegin = get_row_begin_for_band(infoPtr, iHitBand);
02057     iRowEnd = get_row_end_for_band(infoPtr, iHitBand);
02058     hitBand = REBAR_GetBand(infoPtr, iHitBand);
02059 
02060     xBand = hitBand->rcBand.left;
02061     movement = (infoPtr->dwStyle&CCS_VERT ? ptsmove->y : ptsmove->x)
02062                     - (xBand + REBAR_PRE_GRIPPER - infoPtr->ihitoffset);
02063 
02064     /* Dragging the first band in a row cannot cause shrinking */
02065     if(iHitBand != iRowBegin)
02066     {
02067         if (movement < 0) {
02068             cxLeft = REBAR_ShrinkBandsRTL(infoPtr, iRowBegin, iHitBand, -movement, TRUE);
02069 
02070             if(cxLeft < -movement)
02071             {
02072                 hitBand->cxEffective += -movement - cxLeft;
02073                 hitBand->cx = hitBand->cxEffective;
02074                 shrunkBands = TRUE;
02075             }
02076 
02077         } else if (movement > 0) {
02078 
02079             cxLeft = movement;
02080             if (prev_visible(infoPtr, iHitBand) >= 0)
02081                 cxLeft = REBAR_ShrinkBandsLTR(infoPtr, iHitBand, iRowEnd, movement, TRUE);
02082 
02083             if(cxLeft < movement)
02084             {
02085                 REBAR_BAND *lpPrev = REBAR_GetBand(infoPtr, prev_visible(infoPtr, iHitBand));
02086                 lpPrev->cxEffective += movement - cxLeft;
02087                 lpPrev->cx = hitBand->cxEffective;
02088                 shrunkBands = TRUE;
02089             }
02090 
02091         }
02092     }
02093 
02094     if(!shrunkBands)
02095     {
02096         /* It was not possible to move the band by shrinking bands.
02097          * Try relocating the band instead. */
02098         REBAR_MoveBandToRowOffset(infoPtr, iHitBand, iRowBegin,
02099             iRowEnd, xBand + movement, TRUE);
02100     }
02101 
02102     REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
02103     if (infoPtr->dwStyle & CCS_VERT)
02104         REBAR_CalcVertBand(infoPtr, 0, infoPtr->uNumBands);
02105     else
02106         REBAR_CalcHorzBand(infoPtr, 0, infoPtr->uNumBands);
02107     REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
02108 }
02109 
02110 static void
02111 REBAR_HandleUDDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
02112 {
02113     INT yOff = (infoPtr->dwStyle & CCS_VERT) ? ptsmove->x : ptsmove->y;
02114     INT iHitBand, iRowBegin, iNextRowBegin;
02115     REBAR_BAND *hitBand, *rowBeginBand;
02116 
02117     if(infoPtr->uNumBands <= 0)
02118         ERR("There are no bands in this rebar\n");
02119 
02120     /* Up/down dragging can only occur when there is more than one
02121      * band in the rebar */
02122     if(infoPtr->uNumBands <= 1)
02123         return;
02124 
02125     iHitBand = infoPtr->iGrabbedBand;
02126     hitBand = REBAR_GetBand(infoPtr, iHitBand);
02127 
02128     /* If we're taking a band that has the RBBS_BREAK style set, this
02129      * style needs to be reapplied to the band that is going to become
02130      * the new start of the row. */
02131     if((hitBand->fStyle & RBBS_BREAK) &&
02132         (iHitBand < infoPtr->uNumBands - 1))
02133         REBAR_GetBand(infoPtr, iHitBand + 1)->fStyle |= RBBS_BREAK;
02134 
02135     if(yOff < 0)
02136     {
02137         /* Place the band above the current top row */
02138         DPA_DeletePtr(infoPtr->bands, iHitBand);
02139         hitBand->fStyle &= RBBS_BREAK;
02140         REBAR_GetBand(infoPtr, 0)->fStyle |= RBBS_BREAK;
02141         infoPtr->iGrabbedBand = DPA_InsertPtr(
02142             infoPtr->bands, 0, hitBand);
02143     }
02144     else if(yOff > REBAR_GetBand(infoPtr, infoPtr->uNumBands - 1)->rcBand.bottom)
02145     {
02146         /* Place the band below the current bottom row */
02147         DPA_DeletePtr(infoPtr->bands, iHitBand);
02148         hitBand->fStyle |= RBBS_BREAK;
02149         infoPtr->iGrabbedBand = DPA_InsertPtr(
02150             infoPtr->bands, infoPtr->uNumBands - 1, hitBand);
02151     }
02152     else
02153     {
02154         /* Place the band in the prexisting row the mouse is hovering over */
02155         iRowBegin = first_visible(infoPtr);
02156         while(iRowBegin < infoPtr->uNumBands)
02157         {
02158             iNextRowBegin = get_row_end_for_band(infoPtr, iRowBegin);
02159             rowBeginBand = REBAR_GetBand(infoPtr, iRowBegin);
02160             if(rowBeginBand->rcBand.bottom > yOff)
02161             {
02162                 REBAR_MoveBandToRowOffset(
02163                     infoPtr, iHitBand, iRowBegin, iNextRowBegin,
02164                     ((infoPtr->dwStyle & CCS_VERT) ? ptsmove->y : ptsmove->x)
02165                         - REBAR_PRE_GRIPPER - infoPtr->ihitoffset, FALSE);
02166                 break;
02167             }
02168 
02169             iRowBegin = iNextRowBegin;
02170         }
02171     }
02172 
02173     REBAR_Layout(infoPtr);
02174 }
02175 
02176 
02177 /* << REBAR_BeginDrag >> */
02178 
02179 
02180 static LRESULT
02181 REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam)
02182 {
02183     UINT uBand = (UINT)wParam;
02184     REBAR_BAND *lpBand;
02185 
02186     if (uBand >= infoPtr->uNumBands)
02187     return FALSE;
02188 
02189     TRACE("deleting band %u!\n", uBand);
02190     lpBand = REBAR_GetBand(infoPtr, uBand);
02191     REBAR_Notify_NMREBAR (infoPtr, uBand, RBN_DELETINGBAND);
02192     /* TODO: a return of 1 should probably cancel the deletion */
02193 
02194     if (lpBand->hwndChild)
02195         ShowWindow(lpBand->hwndChild, SW_HIDE);
02196     Free(lpBand->lpText);
02197     Free(lpBand);
02198 
02199     infoPtr->uNumBands--;
02200     DPA_DeletePtr(infoPtr->bands, uBand);
02201 
02202     REBAR_Notify_NMREBAR (infoPtr, -1, RBN_DELETEDBAND);
02203 
02204     /* if only 1 band left the re-validate to possible eliminate gripper */
02205     if (infoPtr->uNumBands == 1)
02206       REBAR_ValidateBand (infoPtr, REBAR_GetBand(infoPtr, 0));
02207 
02208     REBAR_Layout(infoPtr);
02209 
02210     return TRUE;
02211 }
02212 
02213 
02214 /* << REBAR_DragMove >> */
02215 /* << REBAR_EndDrag >> */
02216 
02217 
02218 static LRESULT
02219 REBAR_GetBandBorders (const REBAR_INFO *infoPtr, UINT uBand, RECT *lpRect)
02220 {
02221     REBAR_BAND *lpBand;
02222 
02223     if (!lpRect)
02224     return 0;
02225     if (uBand >= infoPtr->uNumBands)
02226     return 0;
02227 
02228     lpBand = REBAR_GetBand(infoPtr, uBand);
02229 
02230     /* FIXME - the following values were determined by experimentation */
02231     /* with the REBAR Control Spy. I have guesses as to what the 4 and */
02232     /* 1 are, but I am not sure. There doesn't seem to be any actual   */
02233     /* difference in size of the control area with and without the     */
02234     /* style.  -  GA                                                   */
02235     if (infoPtr->dwStyle & RBS_BANDBORDERS) {
02236     if (infoPtr->dwStyle & CCS_VERT) {
02237         lpRect->left = 1;
02238         lpRect->top = lpBand->cxHeader + 4;
02239         lpRect->right = 1;
02240         lpRect->bottom = 0;
02241     }
02242     else {
02243         lpRect->left = lpBand->cxHeader + 4;
02244         lpRect->top = 1;
02245         lpRect->right = 0;
02246         lpRect->bottom = 1;
02247     }
02248     }
02249     else {
02250     lpRect->left = lpBand->cxHeader;
02251     }
02252     return 0;
02253 }
02254 
02255 
02256 static inline LRESULT
02257 REBAR_GetBandCount (const REBAR_INFO *infoPtr)
02258 {
02259     TRACE("band count %u!\n", infoPtr->uNumBands);
02260 
02261     return infoPtr->uNumBands;
02262 }
02263 
02264 
02265 static LRESULT
02266 REBAR_GetBandInfoT(const REBAR_INFO *infoPtr, UINT uIndex, LPREBARBANDINFOW lprbbi, BOOL bUnicode)
02267 {
02268     REBAR_BAND *lpBand;
02269 
02270     if (!lprbbi || lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
02271     return FALSE;
02272 
02273     if (uIndex >= infoPtr->uNumBands)
02274     return FALSE;
02275 
02276     TRACE("index %u (bUnicode=%d)\n", uIndex, bUnicode);
02277 
02278     /* copy band information */
02279     lpBand = REBAR_GetBand(infoPtr, uIndex);
02280 
02281     if (lprbbi->fMask & RBBIM_STYLE)
02282     lprbbi->fStyle = lpBand->fStyle;
02283 
02284     if (lprbbi->fMask & RBBIM_COLORS) {
02285     lprbbi->clrFore = lpBand->clrFore;
02286     lprbbi->clrBack = lpBand->clrBack;
02287     if (lprbbi->clrBack == CLR_DEFAULT)
02288         lprbbi->clrBack = infoPtr->clrBtnFace;
02289     }
02290 
02291     if (lprbbi->fMask & RBBIM_TEXT) {
02292         if (bUnicode)
02293             Str_GetPtrW(lpBand->lpText, lprbbi->lpText, lprbbi->cch);
02294         else
02295             Str_GetPtrWtoA(lpBand->lpText, (LPSTR)lprbbi->lpText, lprbbi->cch);
02296     }
02297 
02298     if (lprbbi->fMask & RBBIM_IMAGE)
02299     lprbbi->iImage = lpBand->iImage;
02300 
02301     if (lprbbi->fMask & RBBIM_CHILD)
02302     lprbbi->hwndChild = lpBand->hwndChild;
02303 
02304     if (lprbbi->fMask & RBBIM_CHILDSIZE) {
02305     lprbbi->cxMinChild = lpBand->cxMinChild;
02306     lprbbi->cyMinChild = lpBand->cyMinChild;
02307         /* to make tests pass we follow Windows behaviour and allow to read these fields only
02308          * for RBBS_VARIABLEHEIGHTS bands */
02309         if (lprbbi->cbSize >= REBARBANDINFOW_V6_SIZE && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
02310         lprbbi->cyChild    = lpBand->cyChild;
02311         lprbbi->cyMaxChild = lpBand->cyMaxChild;
02312         lprbbi->cyIntegral = lpBand->cyIntegral;
02313     }
02314     }
02315 
02316     if (lprbbi->fMask & RBBIM_SIZE)
02317     lprbbi->cx = lpBand->cx;
02318 
02319     if (lprbbi->fMask & RBBIM_BACKGROUND)
02320     lprbbi->hbmBack = lpBand->hbmBack;
02321 
02322     if (lprbbi->fMask & RBBIM_ID)
02323     lprbbi->wID = lpBand->wID;
02324 
02325     /* check for additional data */
02326     if (lprbbi->cbSize >= REBARBANDINFOW_V6_SIZE) {
02327     if (lprbbi->fMask & RBBIM_IDEALSIZE)
02328         lprbbi->cxIdeal = lpBand->cxIdeal;
02329 
02330     if (lprbbi->fMask & RBBIM_LPARAM)
02331         lprbbi->lParam = lpBand->lParam;
02332 
02333     if (lprbbi->fMask & RBBIM_HEADERSIZE)
02334         lprbbi->cxHeader = lpBand->cxHeader;
02335     }
02336 
02337     REBAR_DumpBandInfo(lprbbi);
02338 
02339     return TRUE;
02340 }
02341 
02342 
02343 static LRESULT
02344 REBAR_GetBarHeight (const REBAR_INFO *infoPtr)
02345 {
02346     INT nHeight;
02347 
02348     nHeight = infoPtr->calcSize.cy;
02349 
02350     TRACE("height = %d\n", nHeight);
02351 
02352     return nHeight;
02353 }
02354 
02355 
02356 static LRESULT
02357 REBAR_GetBarInfo (const REBAR_INFO *infoPtr, LPREBARINFO lpInfo)
02358 {
02359     if (!lpInfo || lpInfo->cbSize < sizeof (REBARINFO))
02360     return FALSE;
02361 
02362     TRACE("getting bar info!\n");
02363 
02364     if (infoPtr->himl) {
02365     lpInfo->himl = infoPtr->himl;
02366     lpInfo->fMask |= RBIM_IMAGELIST;
02367     }
02368 
02369     return TRUE;
02370 }
02371 
02372 
02373 static inline LRESULT
02374 REBAR_GetBkColor (const REBAR_INFO *infoPtr)
02375 {
02376     COLORREF clr = infoPtr->clrBk;
02377 
02378     if (clr == CLR_DEFAULT)
02379       clr = infoPtr->clrBtnFace;
02380 
02381     TRACE("background color 0x%06x!\n", clr);
02382 
02383     return clr;
02384 }
02385 
02386 
02387 /* << REBAR_GetColorScheme >> */
02388 /* << REBAR_GetDropTarget >> */
02389 
02390 
02391 static LRESULT
02392 REBAR_GetPalette (const REBAR_INFO *infoPtr)
02393 {
02394     FIXME("empty stub!\n");
02395 
02396     return 0;
02397 }
02398 
02399 
02400 static LRESULT
02401 REBAR_GetRect (const REBAR_INFO *infoPtr, INT iBand, RECT *lprc)
02402 {
02403     REBAR_BAND *lpBand;
02404 
02405     if (iBand < 0 || iBand >= infoPtr->uNumBands)
02406     return FALSE;
02407     if (!lprc)
02408     return FALSE;
02409 
02410     lpBand = REBAR_GetBand(infoPtr, iBand);
02411     /* For CCS_VERT the coordinates will be swapped - like on Windows */
02412     CopyRect (lprc, &lpBand->rcBand);
02413 
02414     TRACE("band %d, (%s)\n", iBand, wine_dbgstr_rect(lprc));
02415 
02416     return TRUE;
02417 }
02418 
02419 
02420 static inline LRESULT
02421 REBAR_GetRowCount (const REBAR_INFO *infoPtr)
02422 {
02423     TRACE("%u\n", infoPtr->uNumRows);
02424 
02425     return infoPtr->uNumRows;
02426 }
02427 
02428 
02429 static LRESULT
02430 REBAR_GetRowHeight (const REBAR_INFO *infoPtr, INT iRow)
02431 {
02432     int j = 0, ret = 0;
02433     UINT i;
02434     REBAR_BAND *lpBand;
02435 
02436     for (i=0; i<infoPtr->uNumBands; i++) {
02437     lpBand = REBAR_GetBand(infoPtr, i);
02438     if (HIDDENBAND(lpBand)) continue;
02439     if (lpBand->iRow != iRow) continue;
02440         j = lpBand->rcBand.bottom - lpBand->rcBand.top;
02441     if (j > ret) ret = j;
02442     }
02443 
02444     TRACE("row %d, height %d\n", iRow, ret);
02445 
02446     return ret;
02447 }
02448 
02449 
02450 static inline LRESULT
02451 REBAR_GetTextColor (const REBAR_INFO *infoPtr)
02452 {
02453     TRACE("text color 0x%06x!\n", infoPtr->clrText);
02454 
02455     return infoPtr->clrText;
02456 }
02457 
02458 
02459 static inline LRESULT
02460 REBAR_GetToolTips (const REBAR_INFO *infoPtr)
02461 {
02462     return (LRESULT)infoPtr->hwndToolTip;
02463 }
02464 
02465 
02466 static inline LRESULT
02467 REBAR_GetUnicodeFormat (const REBAR_INFO *infoPtr)
02468 {
02469     TRACE("%s hwnd=%p\n",
02470       infoPtr->bUnicode ? "TRUE" : "FALSE", infoPtr->hwndSelf);
02471 
02472     return infoPtr->bUnicode;
02473 }
02474 
02475 
02476 static inline LRESULT
02477 REBAR_GetVersion (const REBAR_INFO *infoPtr)
02478 {
02479     TRACE("version %d\n", infoPtr->iVersion);
02480     return infoPtr->iVersion;
02481 }
02482 
02483 
02484 static LRESULT
02485 REBAR_HitTest (const REBAR_INFO *infoPtr, LPRBHITTESTINFO lprbht)
02486 {
02487     if (!lprbht)
02488     return -1;
02489 
02490     REBAR_InternalHitTest (infoPtr, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
02491 
02492     return lprbht->iBand;
02493 }
02494 
02495 
02496 static LRESULT
02497 REBAR_IdToIndex (const REBAR_INFO *infoPtr, UINT uId)
02498 {
02499     UINT i;
02500 
02501     if (infoPtr->uNumBands < 1)
02502     return -1;
02503 
02504     for (i = 0; i < infoPtr->uNumBands; i++) {
02505     if (REBAR_GetBand(infoPtr, i)->wID == uId) {
02506         TRACE("id %u is band %u found!\n", uId, i);
02507         return i;
02508     }
02509     }
02510 
02511     TRACE("id %u is not found\n", uId);
02512     return -1;
02513 }
02514 
02515 
02516 static LRESULT
02517 REBAR_InsertBandT(REBAR_INFO *infoPtr, INT iIndex, const REBARBANDINFOW *lprbbi, BOOL bUnicode)
02518 {
02519     REBAR_BAND *lpBand;
02520 
02521     if (!lprbbi || lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
02522     return FALSE;
02523 
02524     /* trace the index as signed to see the -1 */
02525     TRACE("insert band at %d (bUnicode=%d)!\n", iIndex, bUnicode);
02526     REBAR_DumpBandInfo(lprbbi);
02527 
02528     if (!(lpBand = Alloc(sizeof(REBAR_BAND)))) return FALSE;
02529     if ((iIndex == -1) || (iIndex > infoPtr->uNumBands))
02530         iIndex = infoPtr->uNumBands;
02531     if (DPA_InsertPtr(infoPtr->bands, iIndex, lpBand) == -1)
02532     {
02533         Free(lpBand);
02534         return FALSE;
02535     }
02536     infoPtr->uNumBands++;
02537 
02538     TRACE("index %d!\n", iIndex);
02539 
02540     /* initialize band */
02541     memset(lpBand, 0, sizeof(*lpBand));
02542     lpBand->clrFore = infoPtr->clrText;
02543     lpBand->clrBack = infoPtr->clrBk;
02544     lpBand->iImage = -1;
02545 
02546     REBAR_CommonSetupBand(infoPtr->hwndSelf, lprbbi, lpBand);
02547 
02548     /* Make sure the defaults for these are correct */
02549     if (lprbbi->cbSize < REBARBANDINFOA_V6_SIZE || !(lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
02550         lpBand->cyChild    = lpBand->cyMinChild;
02551         lpBand->cyMaxChild = 0x7fffffff;
02552         lpBand->cyIntegral = 0;
02553     }
02554 
02555     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
02556         if (bUnicode)
02557             Str_SetPtrW(&lpBand->lpText, lprbbi->lpText);
02558         else
02559             Str_SetPtrAtoW(&lpBand->lpText, (LPSTR)lprbbi->lpText);
02560     }
02561 
02562     REBAR_ValidateBand (infoPtr, lpBand);
02563     /* On insert of second band, revalidate band 1 to possible add gripper */
02564     if (infoPtr->uNumBands == 2)
02565     REBAR_ValidateBand (infoPtr, REBAR_GetBand(infoPtr, 0));
02566 
02567     REBAR_DumpBand (infoPtr);
02568 
02569     REBAR_Layout(infoPtr);
02570     InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
02571 
02572     return TRUE;
02573 }
02574 
02575 
02576 static LRESULT
02577 REBAR_MaximizeBand (const REBAR_INFO *infoPtr, INT iBand, LPARAM lParam)
02578 {
02579     REBAR_BAND *lpBand;
02580     int iRowBegin, iRowEnd;
02581     int cxDesired, extra, extraOrig;
02582     int cxIdealBand;
02583 
02584     /* Validate */
02585     if (infoPtr->uNumBands == 0 || iBand < 0 || iBand >= infoPtr->uNumBands) {
02586     /* error !!! */
02587     ERR("Illegal MaximizeBand, requested=%d, current band count=%d\n",
02588           iBand, infoPtr->uNumBands);
02589         return FALSE;
02590     }
02591 
02592     lpBand = REBAR_GetBand(infoPtr, iBand);
02593 
02594     if (lpBand->fStyle & RBBS_HIDDEN)
02595     {
02596         /* Windows is buggy and creates a hole */
02597         WARN("Ignoring maximize request on a hidden band (%d)\n", iBand);
02598         return FALSE;
02599     }
02600 
02601     cxIdealBand = lpBand->cxIdeal + lpBand->cxHeader + REBAR_POST_CHILD;
02602     if (lParam && (lpBand->cxEffective < cxIdealBand))
02603         cxDesired = cxIdealBand;
02604     else
02605         cxDesired = infoPtr->calcSize.cx;
02606 
02607     iRowBegin = get_row_begin_for_band(infoPtr, iBand);
02608     iRowEnd   = get_row_end_for_band(infoPtr, iBand);
02609     extraOrig = extra = cxDesired - lpBand->cxEffective;
02610     if (extra > 0)
02611         extra = REBAR_ShrinkBandsRTL(infoPtr, iRowBegin, iBand, extra, TRUE);
02612     if (extra > 0)
02613         extra = REBAR_ShrinkBandsLTR(infoPtr, next_visible(infoPtr, iBand), iRowEnd, extra, TRUE);
02614     lpBand->cxEffective += extraOrig - extra;
02615     lpBand->cx = lpBand->cxEffective;
02616     TRACE("(%d, %ld): Wanted size %d, obtained %d (shrink %d, %d)\n", iBand, lParam, cxDesired, lpBand->cx, extraOrig, extra);
02617     REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
02618 
02619     if (infoPtr->dwStyle & CCS_VERT)
02620         REBAR_CalcVertBand(infoPtr, iRowBegin, iRowEnd);
02621     else
02622         REBAR_CalcHorzBand(infoPtr, iRowBegin, iRowEnd);
02623     REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
02624     return TRUE;
02625 
02626 }
02627 
02628 
02629 static LRESULT
02630 REBAR_MinimizeBand (const REBAR_INFO *infoPtr, INT iBand)
02631 {
02632     REBAR_BAND *lpBand;
02633     int iPrev, iRowBegin, iRowEnd;
02634 
02635     /* A "minimize" band is equivalent to "dragging" the gripper
02636      * of than band to the right till the band is only the size
02637      * of the cxHeader.
02638      */
02639 
02640     /* Validate */
02641     if (infoPtr->uNumBands == 0 || iBand < 0 || iBand >= infoPtr->uNumBands) {
02642     /* error !!! */
02643     ERR("Illegal MinimizeBand, requested=%d, current band count=%d\n",
02644           iBand, infoPtr->uNumBands);
02645         return FALSE;
02646     }
02647 
02648     /* compute amount of movement and validate */
02649     lpBand = REBAR_GetBand(infoPtr, iBand);
02650 
02651     if (lpBand->fStyle & RBBS_HIDDEN)
02652     {
02653         /* Windows is buggy and creates a hole/overlap */
02654         WARN("Ignoring minimize request on a hidden band (%d)\n", iBand);
02655         return FALSE;
02656     }
02657 
02658     iPrev = prev_visible(infoPtr, iBand);
02659     /* if first band in row */
02660     if (iPrev < 0 || REBAR_GetBand(infoPtr, iPrev)->iRow != lpBand->iRow) {
02661         int iNext = next_visible(infoPtr, iBand);
02662         if (iNext < infoPtr->uNumBands && REBAR_GetBand(infoPtr, iNext)->iRow == lpBand->iRow) {
02663             TRACE("(%d): Minimizing the first band in row is by maximizing the second\n", iBand);
02664             REBAR_MaximizeBand(infoPtr, iNext, FALSE);
02665         }
02666         else
02667             TRACE("(%d): Only one band in row - nothing to do\n", iBand);
02668         return TRUE;
02669     }
02670 
02671     REBAR_GetBand(infoPtr, iPrev)->cxEffective += lpBand->cxEffective - lpBand->cxMinBand;
02672     REBAR_GetBand(infoPtr, iPrev)->cx = REBAR_GetBand(infoPtr, iPrev)->cxEffective;
02673     lpBand->cx = lpBand->cxEffective = lpBand->cxMinBand;
02674 
02675     iRowBegin = get_row_begin_for_band(infoPtr, iBand);
02676     iRowEnd = get_row_end_for_band(infoPtr, iBand);
02677     REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
02678 
02679     if (infoPtr->dwStyle & CCS_VERT)
02680         REBAR_CalcVertBand(infoPtr, iRowBegin, iRowEnd);
02681     else
02682         REBAR_CalcHorzBand(infoPtr, iRowBegin, iRowEnd);
02683     REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
02684     return FALSE;
02685 }
02686 
02687 
02688 static LRESULT
02689 REBAR_MoveBand (REBAR_INFO *infoPtr, INT iFrom, INT iTo)
02690 {
02691     REBAR_BAND *lpBand;
02692 
02693     /* Validate */
02694     if ((infoPtr->uNumBands == 0) ||
02695     (iFrom < 0) || iFrom >= infoPtr->uNumBands ||
02696     (iTo < 0)   || iTo >= infoPtr->uNumBands) {
02697     /* error !!! */
02698     ERR("Illegal MoveBand, from=%d, to=%d, current band count=%d\n",
02699           iFrom, iTo, infoPtr->uNumBands);
02700         return FALSE;
02701     }
02702 
02703     lpBand = REBAR_GetBand(infoPtr, iFrom);
02704     DPA_DeletePtr(infoPtr->bands, iFrom);
02705     DPA_InsertPtr(infoPtr->bands, iTo, lpBand);
02706 
02707     TRACE("moved band %d to index %d\n", iFrom, iTo);
02708     REBAR_DumpBand (infoPtr);
02709 
02710     /* **************************************************** */
02711     /*                                                      */
02712     /* We do not do a REBAR_Layout here because the native  */
02713     /* control does not do that. The actual layout and      */
02714     /* repaint is done by the *next* real action, ex.:      */
02715     /* RB_INSERTBAND, RB_DELETEBAND, RB_SIZETORECT, etc.    */
02716     /*                                                      */
02717     /* **************************************************** */
02718 
02719     return TRUE;
02720 }
02721 
02722 
02723 /* return TRUE if two strings are different */
02724 static BOOL
02725 REBAR_strdifW( LPCWSTR a, LPCWSTR b )
02726 {
02727     return ( (a && !b) || (b && !a) || (a && b && lstrcmpW(a, b) ) );
02728 }
02729 
02730 static LRESULT
02731 REBAR_SetBandInfoT(REBAR_INFO *infoPtr, INT iBand, const REBARBANDINFOW *lprbbi, BOOL bUnicode)
02732 {
02733     REBAR_BAND *lpBand;
02734     UINT uChanged;
02735 
02736     if (!lprbbi || lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
02737     return FALSE;
02738 
02739     if (iBand >= infoPtr->uNumBands)
02740     return FALSE;
02741 
02742     TRACE("index %d\n", iBand);
02743     REBAR_DumpBandInfo (lprbbi);
02744 
02745     /* set band information */
02746     lpBand = REBAR_GetBand(infoPtr, iBand);
02747 
02748     uChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand);
02749     if (lprbbi->fMask & RBBIM_TEXT) {
02750         LPWSTR wstr = NULL;
02751         if (bUnicode)
02752             Str_SetPtrW(&wstr, lprbbi->lpText);
02753         else
02754             Str_SetPtrAtoW(&wstr, (LPSTR)lprbbi->lpText);
02755 
02756         if (REBAR_strdifW(wstr, lpBand->lpText)) {
02757             Free(lpBand->lpText);
02758             lpBand->lpText = wstr;
02759             uChanged |= RBBIM_TEXT;
02760         }
02761         else
02762             Free(wstr);
02763     }
02764 
02765     REBAR_ValidateBand (infoPtr, lpBand);
02766 
02767     REBAR_DumpBand (infoPtr);
02768 
02769     if (uChanged & (RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE | RBBIM_IMAGE)) {
02770       REBAR_Layout(infoPtr);
02771       InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
02772     }
02773 
02774     return TRUE;
02775 }
02776 
02777 
02778 static LRESULT
02779 REBAR_SetBarInfo (REBAR_INFO *infoPtr, const REBARINFO *lpInfo)
02780 {
02781     REBAR_BAND *lpBand;
02782     UINT i;
02783 
02784     if (!lpInfo || lpInfo->cbSize < sizeof (REBARINFO))
02785     return FALSE;
02786 
02787     TRACE("setting bar info!\n");
02788 
02789     if (lpInfo->fMask & RBIM_IMAGELIST) {
02790     infoPtr->himl = lpInfo->himl;
02791     if (infoPtr->himl) {
02792             INT cx, cy;
02793         ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
02794         infoPtr->imageSize.cx = cx;
02795         infoPtr->imageSize.cy = cy;
02796     }
02797     else {
02798         infoPtr->imageSize.cx = 0;
02799         infoPtr->imageSize.cy = 0;
02800     }
02801     TRACE("new image cx=%d, cy=%d\n", infoPtr->imageSize.cx,
02802           infoPtr->imageSize.cy);
02803     }
02804 
02805     /* revalidate all bands to reset flags for images in headers of bands */
02806     for (i=0; i<infoPtr->uNumBands; i++) {
02807         lpBand = REBAR_GetBand(infoPtr, i);
02808     REBAR_ValidateBand (infoPtr, lpBand);
02809     }
02810 
02811     return TRUE;
02812 }
02813 
02814 
02815 static LRESULT
02816 REBAR_SetBkColor (REBAR_INFO *infoPtr, COLORREF clr)
02817 {
02818     COLORREF clrTemp;
02819 
02820     clrTemp = infoPtr->clrBk;
02821     infoPtr->clrBk = clr;
02822 
02823     TRACE("background color 0x%06x!\n", infoPtr->clrBk);
02824 
02825     return clrTemp;
02826 }
02827 
02828 
02829 /* << REBAR_SetColorScheme >> */
02830 /* << REBAR_SetPalette >> */
02831 
02832 
02833 static LRESULT
02834 REBAR_SetParent (REBAR_INFO *infoPtr, HWND parent)
02835 {
02836     HWND hwndTemp = infoPtr->hwndNotify;
02837 
02838     infoPtr->hwndNotify = parent;
02839 
02840     return (LRESULT)hwndTemp;
02841 }
02842 
02843 
02844 static LRESULT
02845 REBAR_SetTextColor (REBAR_INFO *infoPtr, COLORREF clr)
02846 {
02847     COLORREF clrTemp;
02848 
02849     clrTemp = infoPtr->clrText;
02850     infoPtr->clrText = clr;
02851 
02852     TRACE("text color 0x%06x!\n", infoPtr->clrText);
02853 
02854     return clrTemp;
02855 }
02856 
02857 
02858 /* << REBAR_SetTooltips >> */
02859 
02860 
02861 static inline LRESULT
02862 REBAR_SetUnicodeFormat (REBAR_INFO *infoPtr, BOOL unicode)
02863 {
02864     BOOL bTemp = infoPtr->bUnicode;
02865 
02866     TRACE("to %s hwnd=%p, was %s\n",
02867        unicode ? "TRUE" : "FALSE", infoPtr->hwndSelf,
02868       (bTemp) ? "TRUE" : "FALSE");
02869 
02870     infoPtr->bUnicode = unicode;
02871 
02872    return bTemp;
02873 }
02874 
02875 
02876 static LRESULT
02877 REBAR_SetVersion (REBAR_INFO *infoPtr, INT iVersion)
02878 {
02879     INT iOldVersion = infoPtr->iVersion;
02880 
02881     if (iVersion > COMCTL32_VERSION)
02882     return -1;
02883 
02884     infoPtr->iVersion = iVersion;
02885 
02886     TRACE("new version %d\n", iVersion);
02887 
02888     return iOldVersion;
02889 }
02890 
02891 
02892 static LRESULT
02893 REBAR_ShowBand (REBAR_INFO *infoPtr, INT iBand, BOOL show)
02894 {
02895     REBAR_BAND *lpBand;
02896 
02897     if (iBand < 0 || iBand >= infoPtr->uNumBands)
02898     return FALSE;
02899 
02900     lpBand = REBAR_GetBand(infoPtr, iBand);
02901 
02902     if (show) {
02903     TRACE("show band %d\n", iBand);
02904     lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
02905     if (IsWindow (lpBand->hwndChild))
02906         ShowWindow (lpBand->hwndChild, SW_SHOW);
02907     }
02908     else {
02909     TRACE("hide band %d\n", iBand);
02910     lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
02911     if (IsWindow (lpBand->hwndChild))
02912         ShowWindow (lpBand->hwndChild, SW_HIDE);
02913     }
02914 
02915     REBAR_Layout(infoPtr);
02916     InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
02917 
02918     return TRUE;
02919 }
02920 
02921 
02922 static LRESULT
02923 REBAR_SizeToRect (REBAR_INFO *infoPtr, const RECT *lpRect)
02924 {
02925     if (!lpRect) return FALSE;
02926 
02927     TRACE("[%s]\n", wine_dbgstr_rect(lpRect));
02928     REBAR_SizeToHeight(infoPtr, get_rect_cy(infoPtr, lpRect));
02929     return TRUE;
02930 }
02931 
02932 
02933 
02934 static LRESULT
02935 REBAR_Create (REBAR_INFO *infoPtr, LPCREATESTRUCTW cs)
02936 {
02937     RECT wnrc1, clrc1;
02938 
02939     if (TRACE_ON(rebar)) {
02940     GetWindowRect(infoPtr->hwndSelf, &wnrc1);
02941     GetClientRect(infoPtr->hwndSelf, &clrc1);
02942         TRACE("window=(%s) client=(%s) cs=(%d,%d %dx%d)\n",
02943               wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1),
02944           cs->x, cs->y, cs->cx, cs->cy);
02945     }
02946 
02947     TRACE("created!\n");
02948 
02949     if (OpenThemeData (infoPtr->hwndSelf, themeClass))
02950     {
02951         /* native seems to clear WS_BORDER when themed */
02952         infoPtr->dwStyle &= ~WS_BORDER;
02953     }
02954 
02955     return 0;
02956 }
02957 
02958 
02959 static LRESULT
02960 REBAR_Destroy (REBAR_INFO *infoPtr)
02961 {
02962     REBAR_BAND *lpBand;
02963     UINT i;
02964 
02965     /* clean up each band */
02966     for (i = 0; i < infoPtr->uNumBands; i++) {
02967     lpBand = REBAR_GetBand(infoPtr, i);
02968 
02969     /* delete text strings */
02970         Free (lpBand->lpText);
02971     lpBand->lpText = NULL;
02972     /* destroy child window */
02973     DestroyWindow (lpBand->hwndChild);
02974     Free (lpBand);
02975     }
02976 
02977     /* free band array */
02978     DPA_Destroy (infoPtr->bands);
02979     infoPtr->bands = NULL;
02980 
02981     DestroyCursor (infoPtr->hcurArrow);
02982     DestroyCursor (infoPtr->hcurHorz);
02983     DestroyCursor (infoPtr->hcurVert);
02984     DestroyCursor (infoPtr->hcurDrag);
02985     if (infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont);
02986     SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0);
02987     
02988     CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
02989 
02990     /* free rebar info data */
02991     Free (infoPtr);
02992     TRACE("destroyed!\n");
02993     return 0;
02994 }
02995 
02996 static LRESULT
02997 REBAR_GetFont (const REBAR_INFO *infoPtr)
02998 {
02999     return (LRESULT)infoPtr->hFont;
03000 }
03001 
03002 static LRESULT
03003 REBAR_PushChevron(const REBAR_INFO *infoPtr, UINT uBand, LPARAM lParam)
03004 {
03005     if (uBand < infoPtr->uNumBands)
03006     {
03007         NMREBARCHEVRON nmrbc;
03008         REBAR_BAND *lpBand = REBAR_GetBand(infoPtr, uBand);
03009 
03010         TRACE("Pressed chevron on band %u\n", uBand);
03011 
03012         /* redraw chevron in pushed state */
03013         lpBand->fDraw |= DRAW_CHEVRONPUSHED;
03014         RedrawWindow(infoPtr->hwndSelf, &lpBand->rcChevron,0,
03015           RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
03016 
03017         /* notify app so it can display a popup menu or whatever */
03018         nmrbc.uBand = uBand;
03019         nmrbc.wID = lpBand->wID;
03020         nmrbc.lParam = lpBand->lParam;
03021         nmrbc.rc = lpBand->rcChevron;
03022         nmrbc.lParamNM = lParam;
03023         REBAR_Notify((NMHDR*)&nmrbc, infoPtr, RBN_CHEVRONPUSHED);
03024 
03025         /* redraw chevron in previous state */
03026         lpBand->fDraw &= ~DRAW_CHEVRONPUSHED;
03027         InvalidateRect(infoPtr->hwndSelf, &lpBand->rcChevron, TRUE);
03028 
03029         return TRUE;
03030     }
03031     return FALSE;
03032 }
03033 
03034 static LRESULT
03035 REBAR_LButtonDown (REBAR_INFO *infoPtr, LPARAM lParam)
03036 {
03037     UINT htFlags;
03038     INT iHitBand;
03039     POINT ptMouseDown;
03040     ptMouseDown.x = (short)LOWORD(lParam);
03041     ptMouseDown.y = (short)HIWORD(lParam);
03042 
03043     REBAR_InternalHitTest(infoPtr, &ptMouseDown, &htFlags, &iHitBand);
03044 
03045     if (htFlags == RBHT_CHEVRON)
03046     {
03047         REBAR_PushChevron(infoPtr, iHitBand, 0);
03048     }
03049     else if (htFlags == RBHT_GRABBER || htFlags == RBHT_CAPTION)
03050     {
03051         REBAR_BAND *lpBand;
03052 
03053         TRACE("Starting drag\n");
03054 
03055         lpBand = REBAR_GetBand(infoPtr, iHitBand);
03056 
03057         SetCapture (infoPtr->hwndSelf);
03058         infoPtr->iGrabbedBand = iHitBand;
03059 
03060         /* save off the LOWORD and HIWORD of lParam as initial x,y */
03061         infoPtr->dragStart.x = (short)LOWORD(lParam);
03062         infoPtr->dragStart.y = (short)HIWORD(lParam);
03063         infoPtr->dragNow = infoPtr->dragStart;
03064         if (infoPtr->dwStyle & CCS_VERT)
03065             infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.left + REBAR_PRE_GRIPPER);
03066         else
03067             infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left + REBAR_PRE_GRIPPER);
03068     }
03069     return 0;
03070 }
03071 
03072 static LRESULT
03073 REBAR_LButtonUp (REBAR_INFO *infoPtr)
03074 {
03075     if (infoPtr->iGrabbedBand >= 0)
03076     {
03077         NMHDR layout;
03078         RECT rect;
03079 
03080         infoPtr->dragStart.x = 0;
03081         infoPtr->dragStart.y = 0;
03082         infoPtr->dragNow = infoPtr->dragStart;
03083 
03084         ReleaseCapture ();
03085 
03086         if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
03087             REBAR_Notify(&layout, infoPtr, RBN_LAYOUTCHANGED);
03088             REBAR_Notify_NMREBAR (infoPtr, infoPtr->iGrabbedBand, RBN_ENDDRAG);
03089             infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
03090         }
03091 
03092         infoPtr->iGrabbedBand = -1;
03093 
03094         GetClientRect(infoPtr->hwndSelf, &rect);
03095         InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
03096     }
03097 
03098     return 0;
03099 }
03100 
03101 static LRESULT
03102 REBAR_MouseLeave (REBAR_INFO *infoPtr)
03103 {
03104     if (infoPtr->ichevronhotBand >= 0)
03105     {
03106         REBAR_BAND *lpChevronBand = REBAR_GetBand(infoPtr, infoPtr->ichevronhotBand);
03107         if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
03108         {
03109             lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
03110             InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
03111         }
03112     }
03113     infoPtr->iOldBand = -1;
03114     infoPtr->ichevronhotBand = -2;
03115 
03116     return TRUE;
03117 }
03118 
03119 static LRESULT
03120 REBAR_MouseMove (REBAR_INFO *infoPtr, LPARAM lParam)
03121 {
03122     REBAR_BAND *lpChevronBand;
03123     POINT ptMove;
03124 
03125     ptMove.x = (short)LOWORD(lParam);
03126     ptMove.y = (short)HIWORD(lParam);
03127 
03128     /* if we are currently dragging a band */
03129     if (infoPtr->iGrabbedBand >= 0)
03130     {
03131         REBAR_BAND *band;
03132         int yPtMove = (infoPtr->dwStyle & CCS_VERT ? ptMove.x : ptMove.y);
03133 
03134         if (GetCapture() != infoPtr->hwndSelf)
03135             ERR("We are dragging but haven't got capture?!?\n");
03136 
03137         band = REBAR_GetBand(infoPtr, infoPtr->iGrabbedBand);
03138 
03139         /* if mouse did not move much, exit */
03140         if ((abs(ptMove.x - infoPtr->dragNow.x) <= mindragx) &&
03141             (abs(ptMove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
03142 
03143         /* on first significant mouse movement, issue notify */
03144         if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
03145             if (REBAR_Notify_NMREBAR (infoPtr, -1, RBN_BEGINDRAG)) {
03146                 /* Notify returned TRUE - abort drag */
03147                 infoPtr->dragStart.x = 0;
03148                 infoPtr->dragStart.y = 0;
03149                 infoPtr->dragNow = infoPtr->dragStart;
03150                 infoPtr->iGrabbedBand = -1;
03151                 ReleaseCapture ();
03152                 return 0;
03153             }
03154             infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
03155         }
03156 
03157         /* Test for valid drag case - must not be first band in row */
03158         if ((yPtMove < band->rcBand.top) ||
03159               (yPtMove > band->rcBand.bottom)) {
03160             REBAR_HandleUDDrag (infoPtr, &ptMove);
03161         }
03162         else {
03163             REBAR_HandleLRDrag (infoPtr, &ptMove);
03164         }
03165     }
03166     else
03167     {
03168         INT iHitBand;
03169         UINT htFlags;
03170         TRACKMOUSEEVENT trackinfo;
03171 
03172         REBAR_InternalHitTest(infoPtr, &ptMove, &htFlags, &iHitBand);
03173 
03174         if (infoPtr->iOldBand >= 0 && infoPtr->iOldBand == infoPtr->ichevronhotBand)
03175         {
03176             lpChevronBand = REBAR_GetBand(infoPtr, infoPtr->ichevronhotBand);
03177             if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
03178             {
03179                 lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
03180                 InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
03181             }
03182             infoPtr->ichevronhotBand = -2;
03183         }
03184 
03185         if (htFlags == RBHT_CHEVRON)
03186         {
03187             /* fill in the TRACKMOUSEEVENT struct */
03188             trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
03189             trackinfo.dwFlags = TME_QUERY;
03190             trackinfo.hwndTrack = infoPtr->hwndSelf;
03191             trackinfo.dwHoverTime = 0;
03192 
03193             /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
03194             _TrackMouseEvent(&trackinfo);
03195 
03196             /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
03197             if(!(trackinfo.dwFlags & TME_LEAVE))
03198             {
03199                 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
03200 
03201                 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
03202                 /* and can properly deactivate the hot chevron */
03203                 _TrackMouseEvent(&trackinfo);
03204             }
03205 
03206             lpChevronBand = REBAR_GetBand(infoPtr, iHitBand);
03207             if (!(lpChevronBand->fDraw & DRAW_CHEVRONHOT))
03208             {
03209                 lpChevronBand->fDraw |= DRAW_CHEVRONHOT;
03210                 InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
03211                 infoPtr->ichevronhotBand = iHitBand;
03212             }
03213         }
03214         infoPtr->iOldBand = iHitBand;
03215     }
03216 
03217     return 0;
03218 }
03219 
03220 
03221 static inline LRESULT
03222 REBAR_NCCalcSize (const REBAR_INFO *infoPtr, RECT *rect)
03223 {
03224     HTHEME theme;
03225 
03226     if (infoPtr->dwStyle & WS_BORDER) {
03227         rect->left   = min(rect->left + GetSystemMetrics(SM_CXEDGE), rect->right);
03228         rect->right  = max(rect->right - GetSystemMetrics(SM_CXEDGE), rect->left);
03229         rect->top    = min(rect->top + GetSystemMetrics(SM_CYEDGE), rect->bottom);
03230         rect->bottom = max(rect->bottom - GetSystemMetrics(SM_CYEDGE), rect->top);
03231     }
03232     else if ((theme = GetWindowTheme (infoPtr->hwndSelf)))
03233     {
03234         /* FIXME: should use GetThemeInt */
03235         rect->top = min(rect->top + 1, rect->bottom);
03236     }
03237     TRACE("new client=(%s)\n", wine_dbgstr_rect(rect));
03238     return 0;
03239 }
03240 
03241 
03242 static LRESULT
03243 REBAR_NCCreate (HWND hwnd, const CREATESTRUCTW *cs)
03244 {
03245     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
03246     RECT wnrc1, clrc1;
03247     NONCLIENTMETRICSW ncm;
03248     HFONT tfont;
03249 
03250     if (infoPtr) {
03251     ERR("Strange info structure pointer *not* NULL\n");
03252     return FALSE;
03253     }
03254 
03255     if (TRACE_ON(rebar)) {
03256     GetWindowRect(hwnd, &wnrc1);
03257     GetClientRect(hwnd, &clrc1);
03258         TRACE("window=(%s) client=(%s) cs=(%d,%d %dx%d)\n",
03259               wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1),
03260           cs->x, cs->y, cs->cx, cs->cy);
03261     }
03262 
03263     /* allocate memory for info structure */
03264     infoPtr = Alloc (sizeof(REBAR_INFO));
03265     SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
03266 
03267     /* initialize info structure - initial values are 0 */
03268     infoPtr->clrBk = CLR_NONE;
03269     infoPtr->clrText = CLR_NONE;
03270     infoPtr->clrBtnText = comctl32_color.clrBtnText;
03271     infoPtr->clrBtnFace = comctl32_color.clrBtnFace;
03272     infoPtr->iOldBand = -1;
03273     infoPtr->ichevronhotBand = -2;
03274     infoPtr->iGrabbedBand = -1;
03275     infoPtr->hwndSelf = hwnd;
03276     infoPtr->DoRedraw = TRUE;
03277     infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW);
03278     infoPtr->hcurHorz  = LoadCursorW (0, (LPWSTR)IDC_SIZEWE);
03279     infoPtr->hcurVert  = LoadCursorW (0, (LPWSTR)IDC_SIZENS);
03280     infoPtr->hcurDrag  = LoadCursorW (0, (LPWSTR)IDC_SIZE);
03281     infoPtr->fStatus = 0;
03282     infoPtr->hFont = GetStockObject (SYSTEM_FONT);
03283     infoPtr->bands = DPA_Create(8);
03284 
03285     /* issue WM_NOTIFYFORMAT to get unicode status of parent */
03286     REBAR_NotifyFormat(infoPtr, NF_REQUERY);
03287 
03288     /* Stow away the original style */
03289     infoPtr->orgStyle = cs->style;
03290     /* add necessary styles to the requested styles */
03291     infoPtr->dwStyle = cs->style | WS_VISIBLE;
03292     if ((infoPtr->dwStyle & CCS_LAYOUT_MASK) == 0)
03293         infoPtr->dwStyle |= CCS_TOP;
03294     SetWindowLongW (hwnd, GWL_STYLE, infoPtr->dwStyle);
03295 
03296     /* get font handle for Caption Font */
03297     ncm.cbSize = sizeof(ncm);
03298     SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
03299     /* if the font is bold, set to normal */
03300     if (ncm.lfCaptionFont.lfWeight > FW_NORMAL) {
03301     ncm.lfCaptionFont.lfWeight = FW_NORMAL;
03302     }
03303     tfont = CreateFontIndirectW (&ncm.lfCaptionFont);
03304     if (tfont) {
03305         infoPtr->hFont = infoPtr->hDefaultFont = tfont;
03306     }
03307 
03308 /* native does:
03309         GetSysColor (numerous);
03310         GetSysColorBrush (numerous) (see WM_SYSCOLORCHANGE);
03311        *GetStockObject (SYSTEM_FONT);
03312        *SetWindowLong (hwnd, 0, info ptr);
03313        *WM_NOTIFYFORMAT;
03314        *SetWindowLong (hwnd, GWL_STYLE, style+0x10000001);
03315                                     WS_VISIBLE = 0x10000000;
03316                                     CCS_TOP    = 0x00000001;
03317        *SystemParametersInfo (SPI_GETNONCLIENTMETRICS...);
03318        *CreateFontIndirect (lfCaptionFont from above);
03319         GetDC ();
03320         SelectObject (hdc, fontabove);
03321         GetTextMetrics (hdc, );    guessing is tmHeight
03322         SelectObject (hdc, oldfont);
03323         ReleaseDC ();
03324         GetWindowRect ();
03325         MapWindowPoints (0, parent, rectabove, 2);
03326         GetWindowRect ();
03327         GetClientRect ();
03328         ClientToScreen (clientrect);
03329         SetWindowPos (hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER);
03330  */
03331     return TRUE;
03332 }
03333 
03334 
03335 static LRESULT
03336 REBAR_NCHitTest (const REBAR_INFO *infoPtr, LPARAM lParam)
03337 {
03338     NMMOUSE nmmouse;
03339     POINT clpt;
03340     INT i;
03341     UINT scrap;
03342     LRESULT ret = HTCLIENT;
03343 
03344     /*
03345      * Differences from doc at MSDN (as observed with version 4.71 of
03346      *      comctl32.dll
03347      * 1. doc says nmmouse.pt is in screen coord, trace shows client coord.
03348      * 2. if band is not identified .dwItemSpec is 0xffffffff.
03349      * 3. native always seems to return HTCLIENT if notify return is 0.
03350      */
03351 
03352     clpt.x = (short)LOWORD(lParam);
03353     clpt.y = (short)HIWORD(lParam);
03354     ScreenToClient (infoPtr->hwndSelf, &clpt);
03355     REBAR_InternalHitTest (infoPtr, &clpt, &scrap,
03356                (INT *)&nmmouse.dwItemSpec);
03357     nmmouse.dwItemData = 0;
03358     nmmouse.pt = clpt;
03359     nmmouse.dwHitInfo = 0;
03360     if ((i = REBAR_Notify((NMHDR *) &nmmouse, infoPtr, NM_NCHITTEST))) {
03361     TRACE("notify changed return value from %ld to %d\n",
03362           ret, i);
03363     ret = (LRESULT) i;
03364     }
03365     TRACE("returning %ld, client point (%d,%d)\n", ret, clpt.x, clpt.y);
03366     return ret;
03367 }
03368 
03369 
03370 static LRESULT
03371 REBAR_NCPaint (const REBAR_INFO *infoPtr)
03372 {
03373     RECT rcWindow;
03374     HDC hdc;
03375     HTHEME theme;
03376 
03377     if (infoPtr->dwStyle & WS_MINIMIZE)
03378     return 0; /* Nothing to do */
03379 
03380     if (infoPtr->dwStyle & WS_BORDER) {
03381 
03382     /* adjust rectangle and draw the necessary edge */
03383     if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
03384         return 0;
03385     GetWindowRect (infoPtr->hwndSelf, &rcWindow);
03386     OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
03387         TRACE("rect (%s)\n", wine_dbgstr_rect(&rcWindow));
03388     DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
03389     ReleaseDC( infoPtr->hwndSelf, hdc );
03390     }
03391     else if ((theme = GetWindowTheme (infoPtr->hwndSelf)))
03392     {
03393         /* adjust rectangle and draw the necessary edge */
03394         if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
03395             return 0;
03396         GetWindowRect (infoPtr->hwndSelf, &rcWindow);
03397         OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
03398         TRACE("rect (%s)\n", wine_dbgstr_rect(&rcWindow));
03399         DrawThemeEdge (theme, hdc, 0, 0, &rcWindow, BDR_RAISEDINNER, BF_TOP, NULL);
03400         ReleaseDC( infoPtr->hwndSelf, hdc );
03401     }
03402 
03403     return 0;
03404 }
03405 
03406 
03407 static LRESULT
03408 REBAR_NotifyFormat (REBAR_INFO *infoPtr, LPARAM cmd)
03409 {
03410     INT i;
03411 
03412     if (cmd == NF_REQUERY) {
03413     i = SendMessageW(REBAR_GetNotifyParent (infoPtr),
03414              WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY);
03415         if ((i != NFR_ANSI) && (i != NFR_UNICODE)) {
03416         ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", i);
03417         i = NFR_ANSI;
03418     }
03419         infoPtr->bUnicode = (i == NFR_UNICODE) ? 1 : 0;
03420     return (LRESULT)i;
03421     }
03422     return (LRESULT)((infoPtr->bUnicode) ? NFR_UNICODE : NFR_ANSI);
03423 }
03424 
03425 
03426 static LRESULT
03427 REBAR_Paint (const REBAR_INFO *infoPtr, HDC hdc)
03428 {
03429     if (hdc) {
03430         TRACE("painting\n");
03431         REBAR_Refresh (infoPtr, hdc);
03432     } else {
03433         PAINTSTRUCT ps;
03434         hdc = BeginPaint (infoPtr->hwndSelf, &ps);
03435         TRACE("painting (%s)\n", wine_dbgstr_rect(&ps.rcPaint));
03436         if (ps.fErase) {
03437             /* Erase area of paint if requested */
03438             REBAR_EraseBkGnd (infoPtr, hdc);
03439         }
03440         REBAR_Refresh (infoPtr, hdc);
03441     EndPaint (infoPtr->hwndSelf, &ps);
03442     }
03443 
03444     return 0;
03445 }
03446 
03447 
03448 static LRESULT
03449 REBAR_SetCursor (const REBAR_INFO *infoPtr, LPARAM lParam)
03450 {
03451     POINT pt;
03452     UINT  flags;
03453 
03454     TRACE("code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
03455 
03456     GetCursorPos (&pt);
03457     ScreenToClient (infoPtr->hwndSelf, &pt);
03458 
03459     REBAR_InternalHitTest (infoPtr, &pt, &flags, NULL);
03460 
03461     if (flags == RBHT_GRABBER) {
03462     if ((infoPtr->dwStyle & CCS_VERT) &&
03463         !(infoPtr->dwStyle & RBS_VERTICALGRIPPER))
03464         SetCursor (infoPtr->hcurVert);
03465     else
03466         SetCursor (infoPtr->hcurHorz);
03467     }
03468     else if (flags != RBHT_CLIENT)
03469     SetCursor (infoPtr->hcurArrow);
03470 
03471     return 0;
03472 }
03473 
03474 
03475 static LRESULT
03476 REBAR_SetFont (REBAR_INFO *infoPtr, HFONT font)
03477 {
03478     REBAR_BAND *lpBand;
03479     UINT i;
03480 
03481     infoPtr->hFont = font;
03482 
03483     /* revalidate all bands to change sizes of text in headers of bands */
03484     for (i=0; i<infoPtr->uNumBands; i++) {
03485         lpBand = REBAR_GetBand(infoPtr, i);
03486     REBAR_ValidateBand (infoPtr, lpBand);
03487     }
03488 
03489     REBAR_Layout(infoPtr);
03490     return 0;
03491 }
03492 
03493 
03494 /*****************************************************
03495  *
03496  *  Handles the WM_SETREDRAW message.
03497  *
03498  * Documentation:
03499  *  According to testing V4.71 of COMCTL32 returns the
03500  *  *previous* status of the redraw flag (either 0 or -1)
03501  *  instead of the MSDN documented value of 0 if handled
03502  *
03503  *****************************************************/
03504 static inline LRESULT
03505 REBAR_SetRedraw (REBAR_INFO *infoPtr, BOOL redraw)
03506 {
03507     BOOL oldredraw = infoPtr->DoRedraw;
03508 
03509     TRACE("set to %s, fStatus=%08x\n",
03510       (redraw) ? "TRUE" : "FALSE", infoPtr->fStatus);
03511     infoPtr->DoRedraw = redraw;
03512     if (redraw) {
03513     if (infoPtr->fStatus & BAND_NEEDS_REDRAW) {
03514         REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
03515         REBAR_ForceResize (infoPtr);
03516         InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
03517     }
03518     infoPtr->fStatus &= ~BAND_NEEDS_REDRAW;
03519     }
03520     return (oldredraw) ? -1 : 0;
03521 }
03522 
03523 
03524 static LRESULT
03525 REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
03526 {
03527     TRACE("wParam=%lx, lParam=%lx\n", wParam, lParam);
03528 
03529     /* avoid _Layout resize recursion (but it shouldn't be infinite and it seems Windows does recurse) */
03530     if (infoPtr->fStatus & SELF_RESIZE) {
03531     infoPtr->fStatus &= ~SELF_RESIZE;
03532     TRACE("SELF_RESIZE was set, reset, fStatus=%08x lparam=%08lx\n",
03533           infoPtr->fStatus, lParam);
03534     return 0;
03535     }
03536     
03537     if (infoPtr->dwStyle & RBS_AUTOSIZE)
03538         REBAR_AutoSize(infoPtr, TRUE);
03539     else
03540         REBAR_Layout(infoPtr);
03541 
03542     return 0;
03543 }
03544 
03545 
03546 static LRESULT
03547 REBAR_StyleChanged (REBAR_INFO *infoPtr, INT nType, const STYLESTRUCT *lpStyle)
03548 {
03549     TRACE("current style=%08x, styleOld=%08x, style being set to=%08x\n",
03550       infoPtr->dwStyle, lpStyle->styleOld, lpStyle->styleNew);
03551     if (nType == GWL_STYLE)
03552     {
03553         infoPtr->orgStyle = infoPtr->dwStyle = lpStyle->styleNew;
03554         if (GetWindowTheme (infoPtr->hwndSelf))
03555             infoPtr->dwStyle &= ~WS_BORDER;
03556         /* maybe it should be COMMON_STYLES like in toolbar */
03557         if ((lpStyle->styleNew ^ lpStyle->styleOld) & CCS_VERT)
03558             REBAR_Layout(infoPtr);
03559     }
03560     return FALSE;
03561 }
03562 
03563 /* update theme after a WM_THEMECHANGED message */
03564 static LRESULT theme_changed (REBAR_INFO* infoPtr)
03565 {
03566     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
03567     CloseThemeData (theme);
03568     theme = OpenThemeData (infoPtr->hwndSelf, themeClass);
03569     /* WS_BORDER disappears when theming is enabled and reappears when
03570      * disabled... */
03571     infoPtr->dwStyle &= ~WS_BORDER;
03572     infoPtr->dwStyle |= theme ? 0 : (infoPtr->orgStyle & WS_BORDER);
03573     return 0;
03574 }
03575 
03576 static LRESULT
03577 REBAR_WindowPosChanged (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
03578 {
03579     LRESULT ret;
03580     RECT rc;
03581 
03582     ret = DefWindowProcW(infoPtr->hwndSelf, WM_WINDOWPOSCHANGED,
03583              wParam, lParam);
03584     GetWindowRect(infoPtr->hwndSelf, &rc);
03585     TRACE("hwnd %p new pos (%s)\n", infoPtr->hwndSelf, wine_dbgstr_rect(&rc));
03586     return ret;
03587 }
03588 
03589 
03590 static LRESULT WINAPI
03591 REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
03592 {
03593     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
03594 
03595     TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n",
03596       hwnd, uMsg, wParam, lParam);
03597     if (!infoPtr && (uMsg != WM_NCCREATE))
03598         return DefWindowProcW (hwnd, uMsg, wParam, lParam);
03599     switch (uMsg)
03600     {
03601 /*  case RB_BEGINDRAG: */
03602 
03603     case RB_DELETEBAND:
03604         return REBAR_DeleteBand (infoPtr, wParam);
03605 
03606 /*  case RB_DRAGMOVE: */
03607 /*  case RB_ENDDRAG: */
03608 
03609     case RB_GETBANDBORDERS:
03610         return REBAR_GetBandBorders (infoPtr, wParam, (LPRECT)lParam);
03611 
03612     case RB_GETBANDCOUNT:
03613         return REBAR_GetBandCount (infoPtr);
03614 
03615     case RB_GETBANDINFO_OLD:
03616     case RB_GETBANDINFOA:
03617     case RB_GETBANDINFOW:
03618         return REBAR_GetBandInfoT(infoPtr, wParam, (LPREBARBANDINFOW)lParam,
03619                                                     uMsg == RB_GETBANDINFOW);
03620     case RB_GETBARHEIGHT:
03621         return REBAR_GetBarHeight (infoPtr);
03622 
03623     case RB_GETBARINFO:
03624         return REBAR_GetBarInfo (infoPtr, (LPREBARINFO)lParam);
03625 
03626     case RB_GETBKCOLOR:
03627         return REBAR_GetBkColor (infoPtr);
03628 
03629 /*  case RB_GETCOLORSCHEME: */
03630 /*  case RB_GETDROPTARGET: */
03631 
03632     case RB_GETPALETTE:
03633         return REBAR_GetPalette (infoPtr);
03634 
03635     case RB_GETRECT:
03636         return REBAR_GetRect (infoPtr, wParam, (LPRECT)lParam);
03637 
03638     case RB_GETROWCOUNT:
03639         return REBAR_GetRowCount (infoPtr);
03640 
03641     case RB_GETROWHEIGHT:
03642         return REBAR_GetRowHeight (infoPtr, wParam);
03643 
03644     case RB_GETTEXTCOLOR:
03645         return REBAR_GetTextColor (infoPtr);
03646 
03647     case RB_GETTOOLTIPS:
03648         return REBAR_GetToolTips (infoPtr);
03649 
03650     case RB_GETUNICODEFORMAT:
03651         return REBAR_GetUnicodeFormat (infoPtr);
03652 
03653     case CCM_GETVERSION:
03654         return REBAR_GetVersion (infoPtr);
03655 
03656     case RB_HITTEST:
03657         return REBAR_HitTest (infoPtr, (LPRBHITTESTINFO)lParam);
03658 
03659     case RB_IDTOINDEX:
03660         return REBAR_IdToIndex (infoPtr, wParam);
03661 
03662     case RB_INSERTBANDA:
03663     case RB_INSERTBANDW:
03664         return REBAR_InsertBandT(infoPtr, wParam, (LPREBARBANDINFOW)lParam,
03665                                                    uMsg == RB_INSERTBANDW);
03666     case RB_MAXIMIZEBAND:
03667         return REBAR_MaximizeBand (infoPtr, wParam, lParam);
03668 
03669     case RB_MINIMIZEBAND:
03670         return REBAR_MinimizeBand (infoPtr, wParam);
03671 
03672     case RB_MOVEBAND:
03673         return REBAR_MoveBand (infoPtr, wParam, lParam);
03674 
03675     case RB_PUSHCHEVRON:
03676         return REBAR_PushChevron (infoPtr, wParam, lParam);
03677 
03678     case RB_SETBANDINFOA:
03679     case RB_SETBANDINFOW:
03680         return REBAR_SetBandInfoT(infoPtr, wParam, (LPREBARBANDINFOW)lParam,
03681                                                     uMsg == RB_SETBANDINFOW);
03682     case RB_SETBARINFO:
03683         return REBAR_SetBarInfo (infoPtr, (LPREBARINFO)lParam);
03684 
03685     case RB_SETBKCOLOR:
03686         return REBAR_SetBkColor (infoPtr, lParam);
03687 
03688 /*  case RB_SETCOLORSCHEME: */
03689 /*  case RB_SETPALETTE: */
03690 
03691     case RB_SETPARENT:
03692         return REBAR_SetParent (infoPtr, (HWND)wParam);
03693 
03694     case RB_SETTEXTCOLOR:
03695         return REBAR_SetTextColor (infoPtr, lParam);
03696 
03697 /*  case RB_SETTOOLTIPS: */
03698 
03699     case RB_SETUNICODEFORMAT:
03700         return REBAR_SetUnicodeFormat (infoPtr, wParam);
03701 
03702     case CCM_SETVERSION:
03703         return REBAR_SetVersion (infoPtr, (INT)wParam);
03704 
03705     case RB_SHOWBAND:
03706         return REBAR_ShowBand (infoPtr, wParam, lParam);
03707 
03708     case RB_SIZETORECT:
03709         return REBAR_SizeToRect (infoPtr, (LPCRECT)lParam);
03710 
03711 
03712 /*    Messages passed to parent */
03713     case WM_COMMAND:
03714     case WM_DRAWITEM:
03715     case WM_NOTIFY:
03716             return SendMessageW(REBAR_GetNotifyParent (infoPtr), uMsg, wParam, lParam);
03717 
03718 
03719 /*      case WM_CHARTOITEM:     supported according to ControlSpy */
03720 
03721     case WM_CREATE:
03722         return REBAR_Create (infoPtr, (LPCREATESTRUCTW)lParam);
03723 
03724     case WM_DESTROY:
03725         return REBAR_Destroy (infoPtr);
03726 
03727         case WM_ERASEBKGND:
03728         return REBAR_EraseBkGnd (infoPtr, (HDC)wParam);
03729 
03730     case WM_GETFONT:
03731         return REBAR_GetFont (infoPtr);
03732 
03733 /*      case WM_LBUTTONDBLCLK:  supported according to ControlSpy */
03734 
03735     case WM_LBUTTONDOWN:
03736         return REBAR_LButtonDown (infoPtr, lParam);
03737 
03738     case WM_LBUTTONUP:
03739         return REBAR_LButtonUp (infoPtr);
03740 
03741 /*      case WM_MEASUREITEM:    supported according to ControlSpy */
03742 
03743     case WM_MOUSEMOVE:
03744         return REBAR_MouseMove (infoPtr, lParam);
03745 
03746     case WM_MOUSELEAVE:
03747         return REBAR_MouseLeave (infoPtr);
03748 
03749     case WM_NCCALCSIZE:
03750         return REBAR_NCCalcSize (infoPtr, (RECT*)lParam);
03751 
03752         case WM_NCCREATE:
03753         return REBAR_NCCreate (hwnd, (LPCREATESTRUCTW)lParam);
03754 
03755         case WM_NCHITTEST:
03756         return REBAR_NCHitTest (infoPtr, lParam);
03757 
03758     case WM_NCPAINT:
03759         return REBAR_NCPaint (infoPtr);
03760 
03761         case WM_NOTIFYFORMAT:
03762         return REBAR_NotifyFormat (infoPtr, lParam);
03763 
03764     case WM_PRINTCLIENT:
03765     case WM_PAINT:
03766         return REBAR_Paint (infoPtr, (HDC)wParam);
03767 
03768 /*      case WM_PALETTECHANGED: supported according to ControlSpy */
03769 /*      case WM_QUERYNEWPALETTE:supported according to ControlSpy */
03770 /*      case WM_RBUTTONDOWN:    supported according to ControlSpy */
03771 /*      case WM_RBUTTONUP:      supported according to ControlSpy */
03772 
03773     case WM_SETCURSOR:
03774         return REBAR_SetCursor (infoPtr, lParam);
03775 
03776     case WM_SETFONT:
03777         return REBAR_SetFont (infoPtr, (HFONT)wParam);
03778 
03779         case WM_SETREDRAW:
03780         return REBAR_SetRedraw (infoPtr, wParam);
03781 
03782     case WM_SIZE:
03783         return REBAR_Size (infoPtr, wParam, lParam);
03784 
03785         case WM_STYLECHANGED:
03786         return REBAR_StyleChanged (infoPtr, wParam, (LPSTYLESTRUCT)lParam);
03787 
03788         case WM_THEMECHANGED:
03789             return theme_changed (infoPtr);
03790 
03791         case WM_SYSCOLORCHANGE:
03792             COMCTL32_RefreshSysColors();
03793             infoPtr->clrBtnText = comctl32_color.clrBtnText;
03794             infoPtr->clrBtnFace = comctl32_color.clrBtnFace;
03795             return 0;
03796 
03797 /*      case WM_VKEYTOITEM:     supported according to ControlSpy */
03798 /*  case WM_WININICHANGE: */
03799 
03800         case WM_WINDOWPOSCHANGED:
03801         return REBAR_WindowPosChanged (infoPtr, wParam, lParam);
03802 
03803     default:
03804         if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
03805         ERR("unknown msg %04x wp=%08lx lp=%08lx\n",
03806              uMsg, wParam, lParam);
03807         return DefWindowProcW (hwnd, uMsg, wParam, lParam);
03808     }
03809 }
03810 
03811 
03812 VOID
03813 REBAR_Register (void)
03814 {
03815     WNDCLASSW wndClass;
03816 
03817     ZeroMemory (&wndClass, sizeof(WNDCLASSW));
03818     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
03819     wndClass.lpfnWndProc   = REBAR_WindowProc;
03820     wndClass.cbClsExtra    = 0;
03821     wndClass.cbWndExtra    = sizeof(REBAR_INFO *);
03822     wndClass.hCursor       = 0;
03823     wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
03824 #if GLATESTING
03825     wndClass.hbrBackground = CreateSolidBrush(RGB(0,128,0));
03826 #endif
03827     wndClass.lpszClassName = REBARCLASSNAMEW;
03828 
03829     RegisterClassW (&wndClass);
03830 
03831     mindragx = GetSystemMetrics (SM_CXDRAG);
03832     mindragy = GetSystemMetrics (SM_CYDRAG);
03833 
03834 }
03835 
03836 
03837 VOID
03838 REBAR_Unregister (void)
03839 {
03840     UnregisterClassW (REBARCLASSNAMEW, NULL);
03841 }

Generated on Sat May 26 2012 04:21:37 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.