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