Implement dragging on gripper to expand and compress bands. Actual

moving bands to different rows will be later.
This commit is contained in:
Guy L. Albertelli 2000-11-13 19:29:16 +00:00 committed by Alexandre Julliard
parent 1eac1911c7
commit 418efdc410
1 changed files with 502 additions and 83 deletions

View File

@ -1,5 +1,5 @@
/*
* Rebar control rev 4a
* Rebar control rev 5b
*
* Copyright 1998, 1999 Eric Kohl
*
@ -18,18 +18,18 @@
* - All notifications.
* Changes Guy Albertelli <galberte@neo.lrun.com>
* 1. Correct use of fStyle for fMask
* 2. Rewrite to support putting bands in rows, also supports GETROWCOUNT
* and GETROWHEIGHT.
* 3. Make fMask in internal band info indicate what is valid rather than -1.
* 4. Correct output of GETBANDINFO to match MS for iImage, lpText
* 5. Handle RBN_CHILDSIZE notification (not really working)
* 6. Draw separators between bands and fix size of grippers.
* 7. Draw separators between rows.
* 8. Support RBBS_BREAK if specified by user.
* 9. Support background color for band and draw the background.
* 10. Eliminated duplicate code in SetBandInfo[AW] and InsertBand[AW].
* 11. Support text color and propagate colors from Bar to Band
* rev 2,3,4
* - Implement initial version of row grouping, row separators,
* text and background colors. Support additional messages.
* Support RBBS_BREAK. Implement ERASEBKGND and improve painting.
* rev 5
* 1. Support dragging by the Gripper for only left and right drags
* within a row. (5a)
* 2. Implement WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE.
* 3. Support RBS_BANDBORDERS.
* 4. Total rewrite of MouseMove code to handle multiple bands in row. (5b)
* 5. Fix drawing bugs.
*
* Still to do:
* 1. default row height should be the max height of all visible bands
* 2. Following still not handled: RBBS_FIXEDBMP, RBBS_CHILDEDGE,
@ -40,8 +40,10 @@
#include <string.h>
#include "class.h"
#include "winbase.h"
#include "wingdi.h"
#include "win.h"
#include "wine/unicode.h"
#include "wine/winestring.h"
#include "commctrl.h"
@ -74,6 +76,7 @@ typedef struct
UINT lcy; /* minimum cy for band */
UINT hcy; /* maximum cy for band */
SIZE offChild; /* x,y offset if child is not FIXEDSIZE */
UINT uMinHeight;
INT iRow; /* row this band assigned to */
UINT fDraw; /* drawing flags */
@ -87,6 +90,14 @@ typedef struct
HWND hwndPrevParent;
} REBAR_BAND;
/* fDraw flags */
#define DRAW_GRIPPER 1
#define DRAW_IMAGE 2
#define DRAW_TEXT 4
#define DRAW_CHILD 8
#define DRAW_SEP 16
typedef struct
{
COLORREF clrBk; /* background color */
@ -100,24 +111,25 @@ typedef struct
SIZE imageSize; /* image size (image list) */
SIZE calcSize; /* calculated rebar size */
BOOL bAutoResize; /* auto resize deadlock flag */
BOOL bUnicode; /* Unicode flag */
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 */
POINTS dragStart; /* x,y of button down */
POINTS dragNow; /* x,y of this MouseMove */
INT ihitBand; /* band number of band whose gripper was grabbed */
INT ihitoffset; /* offset of hotspot from gripper.left */
REBAR_BAND *bands; /* pointer to the array of rebar bands */
} REBAR_INFO;
/* fStatus flags */
#define BEGIN_DRAG_ISSUED 1
#define AUTO_RESIZE 2
/* fDraw flags */
#define DRAW_GRIPPER 1
#define DRAW_IMAGE 2
#define DRAW_TEXT 4
#define DRAW_CHILD 8
#define DRAW_SEP 16
#define GRIPPER_WIDTH 8
#define GRIPPER_HEIGHT 16
@ -129,6 +141,13 @@ typedef struct
#define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongA (hwnd, 0))
/* "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 VOID
REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
{
@ -153,6 +172,10 @@ REBAR_DumpBand (HWND hwnd)
TRACE("hwnd=%04x: color=%08lx/%08lx, bands=%u, rows=%u, cSize=%ld,%ld\n",
hwnd, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
iP->calcSize.cx, iP->calcSize.cy);
TRACE("hwnd=%04x: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, ihitBand=%d\n",
hwnd, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
iP->dragNow.x, iP->dragNow.y,
iP->ihitBand);
for (i = 0; i < iP->uNumBands; i++) {
pB = &iP->bands[i];
TRACE("band # %u: ID=%u, mask=0x%08x, style=0x%08x, child=%04x, row=%u\n",
@ -160,8 +183,8 @@ REBAR_DumpBand (HWND hwnd)
TRACE("band # %u: xMin=%u, yMin=%u, cx=%u, yChild=%u, yMax=%u, yIntgl=%u, uMinH=%u,\n",
i, pB->cxMinChild, pB->cyMinChild, pB->cx,
pB->cyChild, pB->cyMaxChild, pB->cyIntegral, pB->uMinHeight);
TRACE("band # %u: header=%u, lcx=%u, hcx=%u, lcy=%u, hcy=%u\n",
i, pB->cxHeader, pB->lcx, pB->hcx, pB->lcy, pB->hcy);
TRACE("band # %u: header=%u, lcx=%u, hcx=%u, lcy=%u, hcy=%u, offChild=%ld,%ld\n",
i, pB->cxHeader, pB->lcx, pB->hcx, pB->lcy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
TRACE("band # %u: fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n",
i, pB->fDraw,
pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
@ -176,6 +199,22 @@ REBAR_DumpBand (HWND hwnd)
}
}
static void
REBAR_Notify (HWND hwnd, NMHDR *nmhdr, UINT code)
{
HWND parent, owner;
parent = GetParent (hwnd);
owner = GetWindow (hwnd, GW_OWNER);
if (owner) parent = owner;
nmhdr->idFrom = GetDlgCtrlID (hwnd);
nmhdr->hwndFrom = hwnd;
nmhdr->code = code;
SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
(LPARAM)nmhdr);
}
static VOID
REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand, DWORD dwStyle)
{
@ -194,17 +233,6 @@ REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand, DWORD dwStyle)
DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_LEFT | BF_TOP | BF_MIDDLE);
}
/* draw background */
if (lpBand->clrBack != CLR_NONE) {
HBRUSH brh = CreateSolidBrush (lpBand->clrBack);
TRACE("backround color=0x%06lx, rect (%d,%d)-(%d,%d)\n",
lpBand->clrBack,
lpBand->rcBand.left,lpBand->rcBand.top,
lpBand->rcBand.right,lpBand->rcBand.bottom);
FillRect (hdc, &lpBand->rcBand, brh);
DeleteObject (brh);
}
/* draw gripper */
if (lpBand->fDraw & DRAW_GRIPPER)
DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
@ -260,6 +288,7 @@ REBAR_Refresh (HWND hwnd, HDC hdc)
/* if a new row then draw a separator */
if (oldrow != lpBand->iRow) {
if (dwStyle & RBS_BANDBORDERS) {
if (dwStyle & CCS_VERT) {
SetRect (&rcRowSep, lpBand->rcBand.left-2, 0,
lpBand->rcBand.left-1, infoPtr->calcSize.cy);
@ -269,10 +298,12 @@ REBAR_Refresh (HWND hwnd, HDC hdc)
infoPtr->calcSize.cx, lpBand->rcBand.top-1);
}
TRACE ("drawing row sep (%d,%d)-(%d,%d)\n",
rcRowSep.left, rcRowSep.top, rcRowSep.right, rcRowSep.bottom);
rcRowSep.left, rcRowSep.top,
rcRowSep.right, rcRowSep.bottom);
DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_TOP|BF_LEFT);
oldrow = lpBand->iRow;
}
}
/* now draw the band */
REBAR_DrawBand (hdc, infoPtr, lpBand, dwStyle);
@ -419,21 +450,15 @@ REBAR_CalcHorzBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL
/* set initial child window rectangle if there is a child */
if (lpBand->fMask & RBBIM_CHILD) {
if (lpBand->fStyle & RBBS_FIXEDSIZE) {
xoff = 0;
yoff = 0;
}
else {
xoff = 4;
yoff = 2;
}
xoff = lpBand->offChild.cx;
yoff = lpBand->offChild.cy;
SetRect (&lpBand->rcChild,
lpBand->rcBand.left+lpBand->cxHeader+xoff, lpBand->rcBand.top+yoff,
lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
}
else {
SetRect (&lpBand->rcChild,
lpBand->rcBand.right, lpBand->rcBand.top,
lpBand->rcCapText.right, lpBand->rcBand.top,
lpBand->rcBand.right, lpBand->rcBand.bottom);
}
@ -571,14 +596,8 @@ REBAR_CalcVertBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL
/* set initial child window rectangle if there is a child */
if (lpBand->fMask & RBBIM_CHILD) {
if (lpBand->fStyle & RBBS_FIXEDSIZE) {
xoff = 0;
yoff = 0;
}
else {
xoff = 2;
yoff = 4;
}
yoff = lpBand->offChild.cx;
xoff = lpBand->offChild.cy;
SetRect (&lpBand->rcChild,
lpBand->rcBand.left+xoff,
lpBand->rcBand.top+lpBand->cxHeader+yoff,
@ -586,7 +605,7 @@ REBAR_CalcVertBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL
}
else {
SetRect (&lpBand->rcChild,
lpBand->rcBand.right, lpBand->rcBand.top,
lpBand->rcBand.left, lpBand->rcCapText.bottom,
lpBand->rcBand.right, lpBand->rcBand.top);
}
@ -676,7 +695,6 @@ REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
cxsep = (x==0) ? 0 : SEP_WIDTH; /* separator from previous band */
cx = lpBand->cxHeader + /* Header: includes gripper, text, image */
lpBand->hcx; /* coumpted size of child */
if (dwStyle & CCS_VERT)
dobreak = (y + cx + cxsep > adjcy);
else
@ -684,8 +702,10 @@ REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
/* This is the check for whether we need to start a new row */
if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
( ((dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
TRACE("Spliting to new row %d on band %u\n", row+1, i);
INT borders;
TRACE("Spliting to new row %d on band %u\n", row+1, i);
borders = (dwStyle & RBS_BANDBORDERS) ? 2 : 0;
if (dwStyle & CCS_VERT) {
/* first adjust all bands in previous current row to */
/* redistribute extra x pixels */
@ -695,7 +715,7 @@ REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
REBAR_CalcVertBand (hwnd, infoPtr, rowstartband, i,
notify, dwStyle);
y = 0;
x += (mcy + 2);
x += (mcy + borders);
}
else {
/* first adjust all bands in previous current row to */
@ -706,7 +726,7 @@ REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
REBAR_CalcHorzBand (hwnd, infoPtr, rowstartband, i,
notify, dwStyle);
x = 0;
y += (mcy + 2);
y += (mcy + borders);
}
/* FIXME: if not RBS_VARHEIGHT then find max */
@ -802,6 +822,8 @@ REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
static VOID
REBAR_ForceResize (HWND hwnd)
/* Function: This changes the size of the REBAR window to that */
/* calculated by REBAR_Layout. */
{
REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
RECT rc;
@ -809,7 +831,7 @@ REBAR_ForceResize (HWND hwnd)
TRACE( " to [%ld x %ld]!\n",
infoPtr->calcSize.cx, infoPtr->calcSize.cy);
infoPtr->bAutoResize = TRUE;
infoPtr->fStatus |= AUTO_RESIZE;
rc.left = 0;
rc.top = 0;
@ -975,7 +997,13 @@ REBAR_ValidateBand (HWND hwnd, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
/* Now compute minimum size of child window */
lpBand->offChild.cx = 0;
lpBand->offChild.cy = 0;
if (lpBand->fMask & RBBIM_CHILDSIZE) {
if (!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
lpBand->offChild.cx = 4;
lpBand->offChild.cy = 2;
}
lpBand->lcx = lpBand->cxMinChild;
lpBand->lcy = lpBand->cyMinChild;
lpBand->hcy = lpBand->lcy;
@ -1057,6 +1085,40 @@ REBAR_CommonSetupBand (HWND hwnd, LPREBARBANDINFOA lprbbi, REBAR_BAND *lpBand)
}
}
static LRESULT
REBAR_InternalEraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam, RECT *clip)
/* Function: This erases the background rectangle with the */
/* default brush, then with any band that has a different */
/* background color. */
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
RECT eraserect;
REBAR_BAND *lpBand;
INT i;
if (wndPtr->class->hbrBackground)
FillRect( (HDC) wParam, clip, wndPtr->class->hbrBackground);
WIN_ReleaseWndPtr(wndPtr);
for(i=0; i<infoPtr->uNumBands; i++) {
lpBand = &infoPtr->bands[i];
if (lpBand->clrBack != CLR_NONE) {
if (IntersectRect (&eraserect, clip, &lpBand->rcBand)) {
/* draw background */
HBRUSH brh = CreateSolidBrush (lpBand->clrBack);
TRACE("backround color=0x%06lx, rect (%d,%d)-(%d,%d)\n",
lpBand->clrBack,
lpBand->rcBand.left,lpBand->rcBand.top,
lpBand->rcBand.right,lpBand->rcBand.bottom);
FillRect ( (HDC)wParam, &eraserect, brh);
DeleteObject (brh);
}
}
}
return TRUE;
}
static void
REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
{
@ -1079,6 +1141,7 @@ REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
}
else {
/* somewhere inside */
infoPtr->ihitBand = -1;
for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
lpBand = &infoPtr->bands[iCount];
if (PtInRect (&lpBand->rcBand, *lpPt)) {
@ -1086,6 +1149,7 @@ REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
*pBand = iCount;
if (PtInRect (&lpBand->rcGripper, *lpPt)) {
*pFlags = RBHT_GRABBER;
infoPtr->ihitBand = iCount;
TRACE("ON GRABBER %d\n", iCount);
return;
}
@ -1132,6 +1196,257 @@ REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
return;
}
#define READJ(b,i) {b->rcChild.right += (i);b->rcBand.right += (i);}
#define LEADJ(b,i) {b->rcBand.left += (i); \
b->rcGripper.left += (i); \
b->rcGripper.right += (i); \
b->rcCapImage.left += (i); \
b->rcCapImage.right += (i); \
b->rcCapText.left += (i); \
b->rcCapText.right += (i); \
b->rcChild.left += (i);}
static INT
REBAR_Shrink (REBAR_BAND *band, INT movement, INT i)
/* Function: This attempts to shrink the given band by the */
/* the amount in "movement". A shrink to the left is indi- */
/* cated by "movement" being negative. "i" is merely the */
/* band index for trace messages. */
{
INT Leadjust, Readjust, avail, ret;
/* Note: a left drag is indicated by "movement" being negative. */
/* Similarly, a right drag is indicated by "movement" */
/* being positive. "movement" should never be 0, but if */
/* it is then the band does not move. */
avail = band->rcBand.right - band->rcBand.left -
band->cxHeader - band->offChild.cx;
/* now compute the Left End adjustment factor and Right End */
/* adjustment factor. They may be different if shrinking. */
if (avail <= 0) {
/* if this band is not shrinkable, then just move it */
Leadjust = Readjust = movement;
ret = movement;
}
else {
if (movement < 0) {
/* Drag to left */
if (avail <= abs(movement)) {
Readjust = movement;
Leadjust = movement + avail;
ret = Leadjust;
}
else {
Readjust = movement;
Leadjust = 0;
ret = 0;
}
}
else {
/* Drag to right */
if (avail <= abs(movement)) {
Leadjust = movement;
Readjust = movement - avail;
ret = Readjust;
}
else {
Leadjust = movement;
Readjust = 0;
ret = 0;
}
}
}
/* Reasonability Check */
if (band->rcBand.left+Leadjust < 0) {
ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n",
i, Leadjust, Readjust, movement, ret);
}
LEADJ(band, Leadjust);
READJ(band, Readjust);
TRACE("band %d: left=%d, right=%d, move=%d, rtn=%d, rcBand=(%d,%d)-(%d,%d)\n",
i, Leadjust, Readjust, movement, ret,
band->rcBand.left, band->rcBand.top,
band->rcBand.right, band->rcBand.bottom);
return ret;
}
static void
REBAR_HandleLRDrag (HWND hwnd, REBAR_INFO *infoPtr, POINTS *ptsmove)
/* Function: This will implement the functionality of a */
/* Gripper drag within a row. It will not implement "out- */
/* of-row" drags. (They are detected and handled in */
/* REBAR_MouseMove.) */
/* **** FIXME Vertical rebars not implemented. **** */
/* **** FIXME Switching order of bands in a row not **** */
/* **** yet implemented. **** */
{
REBAR_BAND *hitBand, *band, *prevband, *mindBand, *maxdBand;
DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
HDWP deferpos;
NMREBARCHILDSIZE cs;
NMREBAR startdrag;
RECT newrect;
INT imindBand = -1, imaxdBand, ihitBand, i, movement, tempx;
INT RHeaderSum = 0, LHeaderSum = 0;
INT compress;
/* *** FIXME drag does not work for vertical *** */
if (dwStyle & CCS_VERT) {
FIXME("Drag not yet implemented for vertical rebars\n");
return;
}
/* on first significant mouse movement, issue notify */
if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
startdrag.dwMask = 0;
startdrag.uBand = -1;
REBAR_Notify(hwnd, (NMHDR *) &startdrag, RBN_BEGINDRAG);
infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
}
ihitBand = infoPtr->ihitBand;
hitBand = &infoPtr->bands[ihitBand];
imaxdBand = ihitBand; /* to suppress warning message */
/* find all the bands in the row of the one whose Gripper was seized */
for (i=0; i<infoPtr->uNumBands; i++) {
band = &infoPtr->bands[i];
if (band->iRow == hitBand->iRow) {
imaxdBand = i;
if (imindBand == -1) imindBand = i;
/* minimum size of each band is size of header plus */
/* size of minimum child plus offset of child from header plus */
/* a one to separate each band. */
if (i < ihitBand)
LHeaderSum += (band->cxHeader + band->offChild.cx +
band->lcx + 1);
else
RHeaderSum += (band->cxHeader + band->offChild.cx +
band->lcx + 1);
}
}
if (RHeaderSum) RHeaderSum--; /* no separator afterlast band */
mindBand = &infoPtr->bands[imindBand];
maxdBand = &infoPtr->bands[imaxdBand];
if (imindBand == imaxdBand) return; /* nothing to drag agains */
if (imindBand == ihitBand) return; /* first band in row, cant drag */
/* limit movement to inside adjustable bands - Left */
if (ptsmove->x < mindBand->rcBand.left)
return; /* should swap bands */
/* limit movement to inside adjustable bands - Right */
if (ptsmove->x > maxdBand->rcBand.right)
return; /* should swap bands */
movement = ptsmove->x - (hitBand->rcGripper.left - infoPtr->ihitoffset);
infoPtr->dragNow = *ptsmove;
TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
imaxdBand, LHeaderSum, RHeaderSum);
REBAR_DumpBand (hwnd);
if (movement < 0) {
/* *** Drag left *** */
compress = hitBand->rcBand.left-1 - mindBand->rcBand.left -
LHeaderSum;
if (compress < abs(movement)) {
TRACE("limiting left drag, was %d changed to %d\n",
movement, -compress);
movement = -compress;
}
for (i=ihitBand; i>=imindBand; i--) {
band = &infoPtr->bands[i];
if (i == ihitBand) {
prevband = &infoPtr->bands[i-1];
if (band->rcBand.left - movement <= prevband->rcBand.right) {
tempx = movement - (prevband->rcBand.right-band->rcBand.left+1);
ERR("movement bad. BUG!! was %d, left=%d, right=%d, setting to %d\n",
movement, band->rcBand.left, prevband->rcBand.right, tempx);
movement = tempx;
}
LEADJ(band, movement)
}
else
movement = REBAR_Shrink (band, movement, i);
}
}
else {
/* *** Drag right *** */
compress = maxdBand->rcBand.right - hitBand->rcBand.left -
RHeaderSum;
if (compress < abs(movement)) {
TRACE("limiting right drag, was %d changed to %d\n",
movement, compress);
movement = compress;
}
for (i=ihitBand-1; i<=imaxdBand; i++) {
band = &infoPtr->bands[i];
if (i == ihitBand-1) {
READJ(band, movement)
}
else
movement = REBAR_Shrink (band, movement, i);
}
}
TRACE("bands after adjustment, see band # %d, %d\n",
imindBand, imaxdBand);
REBAR_DumpBand (hwnd);
SetRect (&newrect,
mindBand->rcBand.left,
min(mindBand->rcBand.top, maxdBand->rcBand.top),
maxdBand->rcBand.right,
max(mindBand->rcBand.bottom, maxdBand->rcBand.bottom));
if (!(deferpos = BeginDeferWindowPos (4))) {
ERR("BeginDeferWindowPos returned NULL\n");
}
for (i=imindBand; i<=imaxdBand; i++) {
band = &infoPtr->bands[i];
if ((band->fMask & RBBIM_CHILD) && band->hwndChild) {
cs.uBand = i;
cs.wID = band->wID;
cs.rcChild = band->rcChild;
cs.rcBand = band->rcBand;
REBAR_Notify (hwnd, (NMHDR *) &cs, RBN_CHILDSIZE);
deferpos = DeferWindowPos (deferpos, band->hwndChild, HWND_TOP,
cs.rcChild.left, cs.rcChild.top,
cs.rcChild.right - cs.rcChild.left,
cs.rcChild.bottom - cs.rcChild.top,
SWP_NOZORDER);
if (!deferpos) {
ERR("DeferWindowPos returned NULL\n");
}
}
}
if (!EndDeferWindowPos (deferpos)) {
ERR("EndDeferWindowPos failed\n");
}
InvalidateRect (hwnd, &newrect, TRUE);
UpdateWindow (hwnd);
}
#undef READJ
#undef LEADJ
/* << REBAR_BeginDrag >> */
@ -2058,8 +2373,9 @@ REBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
infoPtr->iVersion = 0;
infoPtr->clrBk = CLR_NONE;
infoPtr->clrText = GetSysColor (COLOR_BTNTEXT);
infoPtr->ihitBand = -1;
infoPtr->fStatus = 0;
infoPtr->bAutoResize = FALSE;
infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
infoPtr->hcurHorz = LoadCursorA (0, IDC_SIZEWEA);
infoPtr->hcurVert = LoadCursorA (0, IDC_SIZENSA);
@ -2107,17 +2423,11 @@ REBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
infoPtr->bands = NULL;
}
DeleteObject (infoPtr->hcurArrow);
DeleteObject (infoPtr->hcurHorz);
DeleteObject (infoPtr->hcurVert);
DeleteObject (infoPtr->hcurDrag);
/* free rebar info data */
COMCTL32_Free (infoPtr);
SetWindowLongA (hwnd, 0, 0);
@ -2126,6 +2436,17 @@ REBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
static LRESULT
REBAR_EraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
RECT cliprect;
if (GetClipBox ( (HDC)wParam, &cliprect))
return REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &cliprect);
return 0;
}
static LRESULT
REBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
@ -2135,15 +2456,94 @@ REBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
#if 0
static LRESULT
REBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
REBAR_BAND *lpBand;
/* If InternalHitTest did not find a hit on the Gripper, */
/* then ignore the button click. */
if (infoPtr->ihitBand == -1) return 0;
SetCapture (hwnd);
/* save off the LOWORD and HIWORD of lParam as initial x,y */
lpBand = &infoPtr->bands[infoPtr->ihitBand];
infoPtr->dragStart = MAKEPOINTS(lParam);
infoPtr->dragNow = infoPtr->dragStart;
infoPtr->ihitoffset = infoPtr->dragStart.x - lpBand->rcGripper.left;
return 0;
}
static LRESULT
REBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
NMHDR layout;
NMREBAR enddrag;
RECT rect;
/* If InternalHitTest did not find a hit on the Gripper, */
/* then ignore the button click. */
if (infoPtr->ihitBand == -1) return 0;
infoPtr->dragStart.x = 0;
infoPtr->dragStart.y = 0;
infoPtr->dragNow = infoPtr->dragStart;
infoPtr->ihitBand = -1;
ReleaseCapture ();
if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
REBAR_Notify(hwnd, (NMHDR *) &layout, RBN_LAYOUTCHANGED);
enddrag.dwMask = 0;
enddrag.uBand = -1;
REBAR_Notify(hwnd, (NMHDR *) &enddrag, RBN_ENDDRAG);
infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
}
GetClientRect(hwnd, &rect);
InvalidateRect(hwnd, NULL, TRUE);
return 0;
}
static LRESULT
REBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
REBAR_BAND *band1, *band2;
POINTS ptsmove;
/* Validate entry as hit on Gripper has occured */
if (GetCapture() != hwnd) return 0;
if (infoPtr->ihitBand == -1) return 0;
ptsmove = MAKEPOINTS(lParam);
/* if mouse did not move much, exit */
if ((abs(ptsmove.x - infoPtr->dragNow.x) <= mindragx) &&
(abs(ptsmove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
band1 = &infoPtr->bands[infoPtr->ihitBand-1];
band2 = &infoPtr->bands[infoPtr->ihitBand];
/* Test for valid drag case - must not be first band in row */
if ((ptsmove.y < band2->rcBand.top) ||
(ptsmove.y > band2->rcBand.bottom) ||
((infoPtr->ihitBand > 0) && (band1->iRow != band2->iRow))) {
FIXME("Cannot drag to other rows yet!!\n");
}
else {
REBAR_HandleLRDrag (hwnd, infoPtr, &ptsmove);
}
return 0;
}
#endif
inline static LRESULT
@ -2188,12 +2588,18 @@ REBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
static LRESULT
REBAR_Paint (HWND hwnd, WPARAM wParam)
REBAR_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
if (ps.fErase) {
/* Erase area of paint if requested */
REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &ps.rcPaint);
}
REBAR_Refresh (hwnd, hdc);
if (!wParam)
EndPaint (hwnd, &ps);
@ -2269,8 +2675,8 @@ REBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
RECT rcClient;
/* auto resize deadlock check */
if (infoPtr->bAutoResize) {
infoPtr->bAutoResize = FALSE;
if (infoPtr->fStatus & AUTO_RESIZE) {
infoPtr->fStatus &= ~AUTO_RESIZE;
return 0;
}
@ -2430,8 +2836,14 @@ REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_GETFONT:
return REBAR_GetFont (hwnd, wParam, lParam);
/* case WM_MOUSEMOVE: */
/* return REBAR_MouseMove (hwnd, wParam, lParam); */
case WM_LBUTTONDOWN:
return REBAR_LButtonDown (hwnd, wParam, lParam);
case WM_LBUTTONUP:
return REBAR_LButtonUp (hwnd, wParam, lParam);
case WM_MOUSEMOVE:
return REBAR_MouseMove (hwnd, wParam, lParam);
case WM_NCCALCSIZE:
return REBAR_NCCalcSize (hwnd, wParam, lParam);
@ -2443,7 +2855,7 @@ REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
case WM_PAINT:
return REBAR_Paint (hwnd, wParam);
return REBAR_Paint (hwnd, wParam, lParam);
case WM_SETCURSOR:
return REBAR_SetCursor (hwnd, wParam, lParam);
@ -2460,6 +2872,9 @@ REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* case WM_WININICHANGE: */
case WM_ERASEBKGND:
return REBAR_EraseBkGnd (hwnd, wParam, lParam);
default:
if (uMsg >= WM_USER)
ERR("unknown msg %04x wp=%08x lp=%08lx\n",
@ -2485,6 +2900,10 @@ REBAR_Register (void)
wndClass.lpszClassName = REBARCLASSNAMEA;
RegisterClassA (&wndClass);
mindragx = GetSystemMetrics (SM_CXDRAG);
mindragy = GetSystemMetrics (SM_CYDRAG);
}