📄 rebar.c
字号:
/*
* Rebar control
*
* Copyright 1998, 1999 Eric Kohl
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* NOTES
*
* This code was audited for completeness against the documented features
* of Comctl32.dll version 6.0 on Oct. 19, 2004, by Robert Shearman.
*
* Unless otherwise noted, we believe this code to be complete, as per
* the specification mentioned above.
* If you discover missing features or bugs please note them below.
*
* TODO
* Styles:
* - RBS_DBLCLKTOGGLE
* - RBS_FIXEDORDER
* - RBS_REGISTERDROP
* - RBS_TOOLTIPS
* - CCS_NORESIZE
* - CCS_NOMOVEX
* - CCS_NOMOVEY
* Messages:
* - RB_BEGINDRAG
* - RB_DRAGMOVE
* - RB_ENDDRAG
* - RB_GETBANDMARGINS
* - RB_GETCOLORSCHEME
* - RB_GETDROPTARGET
* - RB_GETPALETTE
* - RB_SETCOLORSCHEME
* - RB_SETPALETTE
* - RB_SETTOOLTIPS
* - WM_CHARTOITEM
* - WM_LBUTTONDBLCLK
* - WM_MEASUREITEM
* - WM_PALETTECHANGED
* - WM_QUERYNEWPALETTE
* - WM_RBUTTONDOWN
* - WM_RBUTTONUP
* - WM_SYSCOLORCHANGE
* - WM_VKEYTOITEM
* - WM_WININICHANGE
* Notifications:
* - NM_HCHITTEST
* - NM_RELEASEDCAPTURE
* - RBN_AUTOBREAK
* - RBN_GETOBJECT
* - RBN_MINMAX
* Band styles:
* - RBBS_FIXEDBMP
* Native uses (on each draw!!) SM_CYBORDER (or SM_CXBORDER for CCS_VERT)
* to set the size of the separator width (the value SEP_WIDTH_SIZE
* in here). Should be fixed!!
*/
/*
* Testing: set to 1 to make background brush *always* green
*/
#define GLATESTING 0
/*
*
* 2. At "FIXME: problem # 2" WinRAR:
* if "#if 1" then last band draws in separate row
* if "#if 0" then last band draws in previous row *** just like native ***
*
*/
#define PROBLEM2 0
/*
* 3. REBAR_MoveChildWindows should have a loop because more than
* one pass is made (together with the RBN_CHILDSIZEs) is made on
* at least RB_INSERTBAND
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "wine/unicode.h"
#include "winuser.h"
#include "winnls.h"
#include "commctrl.h"
#include "comctl32.h"
#include "uxtheme.h"
#include "tmschema.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(rebar);
typedef struct
{
UINT fStyle;
UINT fMask;
COLORREF clrFore;
COLORREF clrBack;
INT iImage;
HWND hwndChild;
UINT cxMinChild; /* valid if _CHILDSIZE */
UINT cyMinChild; /* valid if _CHILDSIZE */
UINT cx; /* valid if _SIZE */
HBITMAP hbmBack;
UINT wID;
UINT cyChild; /* valid if _CHILDSIZE */
UINT cyMaxChild; /* valid if _CHILDSIZE */
UINT cyIntegral; /* valid if _CHILDSIZE */
UINT cxIdeal;
LPARAM lParam;
UINT cxHeader;
UINT lcx; /* minimum cx for band */
UINT ccx; /* current cx for band */
UINT hcx; /* maximum cx for band */
UINT lcy; /* minimum cy for band */
UINT ccy; /* current cy for band */
UINT hcy; /* maximum cy for band */
SIZE offChild; /* x,y offset if child is not FIXEDSIZE */
UINT uMinHeight;
INT iRow; /* zero-based index of the row this band assigned to */
UINT fStatus; /* status flags, reset only by _Validate */
UINT fDraw; /* drawing flags, reset only by _Layout */
UINT uCDret; /* last return from NM_CUSTOMDRAW */
RECT rcoldBand; /* previous calculated band rectangle */
RECT rcBand; /* calculated band rectangle */
RECT rcGripper; /* calculated gripper rectangle */
RECT rcCapImage; /* calculated caption image rectangle */
RECT rcCapText; /* calculated caption text rectangle */
RECT rcChild; /* calculated child rectangle */
RECT rcChevron; /* calculated chevron rectangle */
LPWSTR lpText;
HWND hwndPrevParent;
} REBAR_BAND;
/* fStatus flags */
#define HAS_GRIPPER 0x00000001
#define HAS_IMAGE 0x00000002
#define HAS_TEXT 0x00000004
/* fDraw flags */
#define DRAW_GRIPPER 0x00000001
#define DRAW_IMAGE 0x00000002
#define DRAW_TEXT 0x00000004
#define DRAW_RIGHTSEP 0x00000010
#define DRAW_BOTTOMSEP 0x00000020
#define DRAW_CHEVRONHOT 0x00000040
#define DRAW_CHEVRONPUSHED 0x00000080
#define DRAW_LAST_IN_ROW 0x00000100
#define DRAW_FIRST_IN_ROW 0x00000200
#define NTF_INVALIDATE 0x01000000
typedef struct
{
COLORREF clrBk; /* background color */
COLORREF clrText; /* text color */
COLORREF clrBtnText; /* system color for BTNTEXT */
COLORREF clrBtnFace; /* system color for BTNFACE */
HIMAGELIST himl; /* handle to imagelist */
UINT uNumBands; /* # of bands in rebar (first=0, last=uNumBands-1 */
UINT uNumRows; /* # of rows of bands (first=1, last=uNumRows */
HWND hwndSelf; /* handle of REBAR window itself */
HWND hwndToolTip; /* handle to the tool tip control */
HWND hwndNotify; /* notification window (parent) */
HFONT hDefaultFont;
HFONT hFont; /* handle to the rebar's font */
SIZE imageSize; /* image size (image list) */
DWORD dwStyle; /* window style */
DWORD orgStyle; /* original style (dwStyle may change) */
SIZE calcSize; /* calculated rebar size */
SIZE oldSize; /* previous calculated rebar size */
BOOL bUnicode; /* TRUE if parent wants notify in W format */
BOOL DoRedraw; /* TRUE to acutally draw bands */
UINT fStatus; /* Status flags (see below) */
HCURSOR hcurArrow; /* handle to the arrow cursor */
HCURSOR hcurHorz; /* handle to the EW cursor */
HCURSOR hcurVert; /* handle to the NS cursor */
HCURSOR hcurDrag; /* handle to the drag cursor */
INT iVersion; /* version number */
POINT dragStart; /* x,y of button down */
POINT dragNow; /* x,y of this MouseMove */
INT iOldBand; /* last band that had the mouse cursor over it */
INT ihitoffset; /* offset of hotspot from gripper.left */
POINT origin; /* left/upper corner of client */
INT ichevronhotBand; /* last band that had a hot chevron */
INT iGrabbedBand;/* band number of band whose gripper was grabbed */
REBAR_BAND *bands; /* pointer to the array of rebar bands */
} REBAR_INFO;
/* fStatus flags */
#define BEGIN_DRAG_ISSUED 0x00000001
#define AUTO_RESIZE 0x00000002
#define RESIZE_ANYHOW 0x00000004
#define NTF_HGHTCHG 0x00000008
#define BAND_NEEDS_LAYOUT 0x00000010
#define BAND_NEEDS_REDRAW 0x00000020
#define CREATE_RUNNING 0x00000040
/* ---- REBAR layout constants. Mostly determined by ---- */
/* ---- experiment on WIN 98. ---- */
/* Width (or height) of separators between bands (either horz. or */
/* vert.). True only if RBS_BANDBORDERS is set */
#define SEP_WIDTH_SIZE 2
#define SEP_WIDTH ((infoPtr->dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
/* Blank (background color) space between Gripper (if present) */
/* and next item (image, text, or window). Always present */
#define REBAR_ALWAYS_SPACE 4
/* Blank (background color) space after Image (if present). */
#define REBAR_POST_IMAGE 2
/* Blank (background color) space after Text (if present). */
#define REBAR_POST_TEXT 4
/* Height of vertical gripper in a CCS_VERT rebar. */
#define GRIPPER_HEIGHT 16
/* Blank (background color) space before Gripper (if present). */
#define REBAR_PRE_GRIPPER 2
/* Width (of normal vertical gripper) or height (of horz. gripper) */
/* if present. */
#define GRIPPER_WIDTH 3
/* Width of the chevron button if present */
#define CHEVRON_WIDTH 10
/* Height of divider for Rebar if not disabled (CCS_NODIVIDER) */
/* either top or bottom */
#define REBAR_DIVIDER 2
/* minimium vertical height of a normal bar */
/* or minimum width of a CCS_VERT bar - from experiment on Win2k */
#define REBAR_MINSIZE 23
/* This is the increment that is used over the band height */
#define REBARSPACE(a) ((a->fStyle & RBBS_CHILDEDGE) ? 2*REBAR_DIVIDER : 0)
/* ---- End of REBAR layout constants. ---- */
#define RB_GETBANDINFO_OLD (WM_USER+5) /* obsoleted after IE3, but we have to support it anyway */
/* The following 6 defines return the proper rcBand element */
/* depending on whether CCS_VERT was set. */
#define rcBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.top : b->rcBand.left)
#define rcBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.bottom : b->rcBand.right)
#define rcBw(b) ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.bottom - b->rcBand.top) : \
(b->rcBand.right - b->rcBand.left))
#define ircBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.left : b->rcBand.top)
#define ircBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.right : b->rcBand.bottom)
#define ircBw(b) ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.right - b->rcBand.left) : \
(b->rcBand.bottom - b->rcBand.top))
/* The following define determines if a given band is hidden */
#define HIDDENBAND(a) (((a)->fStyle & RBBS_HIDDEN) || \
((infoPtr->dwStyle & CCS_VERT) && \
((a)->fStyle & RBBS_NOVERT)))
/* The following defines adjust the right or left end of a rectangle */
#define READJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.bottom+=(i); \
else b->rcBand.right += (i); } while(0)
#define LEADJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.top+=(i); \
else b->rcBand.left += (i); } while(0)
#define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongPtrW (hwnd, 0))
static LRESULT REBAR_NotifyFormat(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam);
/* "constant values" retrieved when DLL was initialized */
/* FIXME we do this when the classes are registered. */
static UINT mindragx = 0;
static UINT mindragy = 0;
static const char *band_stylename[] = {
"RBBS_BREAK", /* 0001 */
"RBBS_FIXEDSIZE", /* 0002 */
"RBBS_CHILDEDGE", /* 0004 */
"RBBS_HIDDEN", /* 0008 */
"RBBS_NOVERT", /* 0010 */
"RBBS_FIXEDBMP", /* 0020 */
"RBBS_VARIABLEHEIGHT", /* 0040 */
"RBBS_GRIPPERALWAYS", /* 0080 */
"RBBS_NOGRIPPER", /* 0100 */
NULL };
static const char *band_maskname[] = {
"RBBIM_STYLE", /* 0x00000001 */
"RBBIM_COLORS", /* 0x00000002 */
"RBBIM_TEXT", /* 0x00000004 */
"RBBIM_IMAGE", /* 0x00000008 */
"RBBIM_CHILD", /* 0x00000010 */
"RBBIM_CHILDSIZE", /* 0x00000020 */
"RBBIM_SIZE", /* 0x00000040 */
"RBBIM_BACKGROUND", /* 0x00000080 */
"RBBIM_ID", /* 0x00000100 */
"RBBIM_IDEALSIZE", /* 0x00000200 */
"RBBIM_LPARAM", /* 0x00000400 */
"RBBIM_HEADERSIZE", /* 0x00000800 */
NULL };
static CHAR line[200];
static const WCHAR themeClass[] = { 'R','e','b','a','r',0 };
static CHAR *
REBAR_FmtStyle( UINT style)
{
INT i = 0;
*line = 0;
while (band_stylename[i]) {
if (style & (1<<i)) {
if (*line != 0) strcat(line, " | ");
strcat(line, band_stylename[i]);
}
i++;
}
return line;
}
static CHAR *
REBAR_FmtMask( UINT mask)
{
INT i = 0;
*line = 0;
while (band_maskname[i]) {
if (mask & (1<<i)) {
if (*line != 0) strcat(line, " | ");
strcat(line, band_maskname[i]);
}
i++;
}
return line;
}
static VOID
REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
{
if( !TRACE_ON(rebar) ) return;
TRACE("band info: ");
if (pB->fMask & RBBIM_ID)
TRACE("ID=%u, ", pB->wID);
TRACE("size=%u, child=%p", pB->cbSize, pB->hwndChild);
if (pB->fMask & RBBIM_COLORS)
TRACE(", clrF=0x%06x, clrB=0x%06x", pB->clrFore, pB->clrBack);
TRACE("\n");
TRACE("band info: mask=0x%08x (%s)\n", pB->fMask, REBAR_FmtMask(pB->fMask));
if (pB->fMask & RBBIM_STYLE)
TRACE("band info: style=0x%08x (%s)\n", pB->fStyle, REBAR_FmtStyle(pB->fStyle));
if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_HEADERSIZE | RBBIM_LPARAM )) {
TRACE("band info:");
if (pB->fMask & RBBIM_SIZE)
TRACE(" cx=%u", pB->cx);
if (pB->fMask & RBBIM_IDEALSIZE)
TRACE(" xIdeal=%u", pB->cxIdeal);
if (pB->fMask & RBBIM_HEADERSIZE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -