2735 lines
72 KiB
C
2735 lines
72 KiB
C
|
#include "ctlspriv.h"
|
||
|
#include "rebar.h"
|
||
|
#include "image.h"
|
||
|
|
||
|
extern HPALETTE CreateHalftonePalette(HDC hdc);
|
||
|
extern BOOL WINAPI ImageList_DrawIndirect(IMAGELISTDRAWPARAMS FAR* pimldp);
|
||
|
#define RB_GRABWIDTH 8
|
||
|
|
||
|
#ifdef WIN32
|
||
|
#define SEND_WM_COMMAND(hwnd, id, hwndCtl, codeNotify) \
|
||
|
(void)SendMessage((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))
|
||
|
#else
|
||
|
// dont cast result to void since we depend on this hack to get a handle back
|
||
|
// from some WM_COMMAND messages
|
||
|
#define SEND_WM_COMMAND(hwnd, id, hwndCtl, codeNotify) \
|
||
|
SendMessage((hwnd), WM_COMMAND, (WPARAM)(int)(id), MAKELPARAM((UINT)(hwndCtl), (codeNotify)))
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// RBSendNotify
|
||
|
|
||
|
// sends a notification to parent
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBSendNotify(PRB prb, int code)
|
||
|
{
|
||
|
#if defined(WIN32) || defined(IEWIN31_25)
|
||
|
NMHDR hdr;
|
||
|
SendNotifyEx(prb->ci.hwndParent, prb->ci.hwnd, code, &hdr, prb->ci.bUnicode);
|
||
|
#else
|
||
|
SEND_WM_COMMAND(prb->ci.hwndParent, GetWindowID(prb->ci.hwnd), prb->ci.hwnd, code);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBCanBandMove
|
||
|
|
||
|
// returns TRUE if the given band can be moved and FALSE if it cannot
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBCanBandMove(PRB prb, PRBB prbb)
|
||
|
{
|
||
|
if ((prb->ci.style & RBS_FIXEDORDER) && (prbb == prb->rbbList))
|
||
|
// the first band in fixed order rebars can't be moved
|
||
|
return(FALSE);
|
||
|
|
||
|
// fixed size bands can't be moved
|
||
|
return(!(prbb->fStyle & RBBS_FIXEDSIZE));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBBCalcMinWidth
|
||
|
|
||
|
// calculates minimum width for the given band
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBBCalcMinWidth(PRB prb, PRBB prbb)
|
||
|
{
|
||
|
BOOL fMovable = RBCanBandMove(prb, prbb);
|
||
|
BOOL fVertical;
|
||
|
int cEdge;
|
||
|
BOOL fEmpty = ((prbb->iImage == -1) && !prbb->lpText);
|
||
|
|
||
|
prbb->cxMin = prbb->cxMinChild;
|
||
|
|
||
|
if (!fMovable && fEmpty)
|
||
|
return;
|
||
|
|
||
|
fVertical = (BOOL)(prb->ci.style & CCS_VERT);
|
||
|
cEdge = fVertical ? g_cyEdge : g_cxEdge;
|
||
|
|
||
|
prbb->cxMin += 2 * cEdge;
|
||
|
|
||
|
if (fMovable)
|
||
|
{
|
||
|
prbb->cxMin += RB_GRABWIDTH * (fVertical ? g_cyBorder : g_cxBorder);
|
||
|
if (fEmpty)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
prbb->cxMin += 2 * cEdge;
|
||
|
|
||
|
if (prbb->iImage != -1)
|
||
|
prbb->cxMin += (fVertical ? prb->cyImage : prb->cxImage);
|
||
|
|
||
|
if (prbb->lpText)
|
||
|
{
|
||
|
if (fVertical)
|
||
|
prbb->cxMin += prb->cyFont;
|
||
|
else
|
||
|
prbb->cxMin += prbb->cxText;
|
||
|
if (prbb->iImage != -1)
|
||
|
// has both image and text -- add in edge between 'em
|
||
|
prbb->cxMin += cEdge;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBBCalcTextExtent
|
||
|
|
||
|
// computes the horizontal extent of the given band's title text in the current
|
||
|
// title font for the rebar
|
||
|
|
||
|
// returns TRUE if the extent changed; FALSE if it remains the same
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBBCalcTextExtent(PRB prb, PRBB prbb, HDC hdcIn)
|
||
|
{
|
||
|
HDC hdc = hdcIn;
|
||
|
HFONT hFontOld;
|
||
|
SIZE size;
|
||
|
|
||
|
if (!prbb->lpText)
|
||
|
return(FALSE);
|
||
|
|
||
|
if (!hdcIn && !(hdc = GetDC(prb->ci.hwnd)))
|
||
|
return(FALSE);
|
||
|
|
||
|
hFontOld = SelectObject(hdc, prb->hFont);
|
||
|
GetTextExtentPoint(hdc, prbb->lpText, lstrlen(prbb->lpText), &size);
|
||
|
SelectObject(hdc, hFontOld);
|
||
|
|
||
|
if (!hdcIn)
|
||
|
ReleaseDC(prb->ci.hwnd, hdc);
|
||
|
|
||
|
if (prbb->cxText == (UINT) size.cx)
|
||
|
return(FALSE);
|
||
|
|
||
|
prbb->cxText = size.cx;
|
||
|
|
||
|
RBBCalcMinWidth(prb, prbb);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBBGetHeight
|
||
|
|
||
|
// returns minimum height for the given band
|
||
|
// TODO: make this a field in the band structure instead of always calling this
|
||
|
|
||
|
|
||
|
UINT NEAR PASCAL RBBGetHeight(PRB prb, PRBB prbb)
|
||
|
{
|
||
|
UINT cy = 0;
|
||
|
BOOL fVertical = (BOOL)(prb->ci.style & CCS_VERT);
|
||
|
UINT cyCheck, cyBorder;
|
||
|
|
||
|
cyBorder = (fVertical ? g_cxEdge : g_cyEdge) * 2;
|
||
|
|
||
|
if (prbb->hwndChild)
|
||
|
{
|
||
|
cy = prbb->cyMinChild;
|
||
|
if (!(prbb->fStyle & RBBS_CHILDEDGE))
|
||
|
// add edge to top and bottom of child window
|
||
|
cy -= cyBorder;
|
||
|
}
|
||
|
|
||
|
if (prbb->lpText)
|
||
|
{
|
||
|
cyCheck = (fVertical) ? prbb->cxText : prb->cyFont;
|
||
|
|
||
|
if (cyCheck > cy)
|
||
|
cy = cyCheck;
|
||
|
}
|
||
|
|
||
|
if (prbb->iImage != -1)
|
||
|
{
|
||
|
cyCheck = (fVertical) ? prb->cxImage : prb->cyImage;
|
||
|
|
||
|
if (cyCheck > cy)
|
||
|
cy = cyCheck;
|
||
|
}
|
||
|
|
||
|
return(cy + cyBorder);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBGetRowCount
|
||
|
|
||
|
// returns the number of rows in the rebar's current configuration
|
||
|
|
||
|
|
||
|
UINT NEAR PASCAL RBGetRowCount(PRB prb)
|
||
|
{
|
||
|
UINT i;
|
||
|
UINT cRows = 0;
|
||
|
|
||
|
for (i = 0; i < prb->cBands; i++)
|
||
|
if (!prb->rbbList[i].x)
|
||
|
cRows++;
|
||
|
|
||
|
return(cRows);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBGetLineHeight
|
||
|
|
||
|
// returns the height of the line of bands from iStart to iEnd, inclusively
|
||
|
|
||
|
|
||
|
UINT NEAR PASCAL RBGetLineHeight(PRB prb, UINT iStart, UINT iEnd)
|
||
|
{
|
||
|
UINT cy = 0;
|
||
|
PRBB prbb;
|
||
|
UINT cyBand;
|
||
|
|
||
|
if (!(prb->ci.style & RBS_VARHEIGHT))
|
||
|
{
|
||
|
// for fixed height bars, line height is maximum height of ALL bands
|
||
|
iStart = 0;
|
||
|
iEnd = prb->cBands - 1;
|
||
|
}
|
||
|
|
||
|
for (prbb = prb->rbbList + iStart; iStart <= iEnd; prbb++, iStart++)
|
||
|
{
|
||
|
cyBand = RBBGetHeight(prb, prbb);
|
||
|
cy = max(cy, cyBand);
|
||
|
}
|
||
|
|
||
|
return(cy);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBResizeChildren
|
||
|
|
||
|
// resizes children to fit properly in their respective bands' bounding rects
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBResizeChildren(PRB prb, PRBB prbb, PRBB prbbEnd)
|
||
|
{
|
||
|
int cx, cy, x, y, cxHeading;
|
||
|
HDWP hdwp;
|
||
|
BOOL fVertical = (BOOL)(prb->ci.style & CCS_VERT);
|
||
|
|
||
|
if (!prb->cBands)
|
||
|
return;
|
||
|
|
||
|
hdwp = BeginDeferWindowPos(prb->cBands);
|
||
|
|
||
|
if (!prbb)
|
||
|
prbb = prb->rbbList;
|
||
|
|
||
|
if (!prbbEnd)
|
||
|
prbbEnd = prb->rbbList + (prb->cBands - 1);
|
||
|
|
||
|
for ( ; prbb <= prbbEnd ; prbb++)
|
||
|
{
|
||
|
if (!prbb->hwndChild)
|
||
|
continue;
|
||
|
|
||
|
cxHeading = prbb->cxMin - prbb->cxMinChild;
|
||
|
x = prbb->x + cxHeading;
|
||
|
|
||
|
cx = prbb->cx - cxHeading;
|
||
|
if (!(prbb->fStyle & RBBS_FIXEDSIZE))
|
||
|
cx -= (fVertical ? g_cyEdge : g_cxEdge) * 2;
|
||
|
|
||
|
if (cx < 0)
|
||
|
cx = 0;
|
||
|
y = prbb->y;
|
||
|
cy = prbb->cy;
|
||
|
if (prbb->cyMinChild && (prbb->cyMinChild < (UINT) cy))
|
||
|
{
|
||
|
y += (cy - prbb->cyMinChild) / 2;
|
||
|
cy = prbb->cyMinChild;
|
||
|
}
|
||
|
|
||
|
#ifdef IEWIN31_25
|
||
|
|
||
|
// HACK HACK HACK:
|
||
|
|
||
|
// Windows 3.1 and windows 95 behave very differently when you resize a
|
||
|
// combobox! On Windows 95, the drop-down list size is determined on creation,
|
||
|
// but on win 3.1, if you get the window rect and then set it using the same
|
||
|
// dimensions, the dropdown list is hacked off! So we need to treat combo-box
|
||
|
// children differently!
|
||
|
|
||
|
if (cx > 0)
|
||
|
{
|
||
|
char szClass[20];
|
||
|
GetClassName(prbb->hwndChild, szClass, sizeof(szClass)-1);
|
||
|
if (StrCmpNI(szClass, "combobox", sizeof("combobox")) == 0)
|
||
|
{
|
||
|
// HACK: Don't allow the combobox width to be less than the scroll
|
||
|
// button (plus 1 for border) it bleeds to the left of its extent!
|
||
|
if (cx <= (GetSystemMetrics(SM_CXVSCROLL) + 1))
|
||
|
{
|
||
|
cx = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// We have a combo box, so make the height include the drop-down
|
||
|
// list box
|
||
|
RECT rcDrop;
|
||
|
SendMessage(prbb->hwndChild, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rcDrop);
|
||
|
cy = rcDrop.bottom - rcDrop.top;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif //IEWIN31_25
|
||
|
|
||
|
if(fVertical)
|
||
|
DeferWindowPos(hdwp, prbb->hwndChild, NULL, y, x, cy, cx, SWP_NOZORDER);
|
||
|
else
|
||
|
DeferWindowPos(hdwp, prbb->hwndChild, NULL, x, y, cx, cy, SWP_NOZORDER);
|
||
|
|
||
|
}
|
||
|
|
||
|
EndDeferWindowPos(hdwp);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBMoveBand
|
||
|
|
||
|
// moves the band from one position to another in the rebar's band array,
|
||
|
// updating the rebar's iCapture field as needed
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBMoveBand(PRB prb, UINT iFrom, UINT iTo)
|
||
|
{
|
||
|
RBB rbbMove;
|
||
|
int iShift;
|
||
|
BOOL fCaptureChanged = (prb->iCapture == -1);
|
||
|
|
||
|
if (iFrom != iTo)
|
||
|
{
|
||
|
rbbMove = prb->rbbList[iFrom];
|
||
|
if (prb->iCapture == (int) iFrom)
|
||
|
{
|
||
|
prb->iCapture = (int) iTo;
|
||
|
fCaptureChanged = TRUE;
|
||
|
}
|
||
|
|
||
|
iShift = (iFrom > iTo) ? -1 : 1;
|
||
|
|
||
|
while (iFrom != iTo)
|
||
|
{
|
||
|
if (!fCaptureChanged && (prb->iCapture == (int) (iFrom + iShift)))
|
||
|
{
|
||
|
prb->iCapture = (int) iFrom;
|
||
|
fCaptureChanged = TRUE;
|
||
|
}
|
||
|
|
||
|
prb->rbbList[iFrom] = prb->rbbList[iFrom + iShift];
|
||
|
iFrom += iShift;
|
||
|
}
|
||
|
prb->rbbList[iTo] = rbbMove;
|
||
|
}
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBRecalc
|
||
|
|
||
|
// recomputes bounding rects for all bands in given rebar
|
||
|
|
||
|
|
||
|
UINT NEAR PASCAL RBRecalc(PRB prb)
|
||
|
{
|
||
|
PRBB prbb = prb->rbbList;
|
||
|
PRBB prbbWalk;
|
||
|
UINT cxRow;
|
||
|
UINT cxMin;
|
||
|
UINT i;
|
||
|
UINT j;
|
||
|
UINT k;
|
||
|
UINT iFixed = 0xFFFF;
|
||
|
int cy;
|
||
|
int y;
|
||
|
int x;
|
||
|
UINT cxBar;
|
||
|
RECT rc;
|
||
|
HWND hwndSize;
|
||
|
BOOL fNewLine = FALSE;
|
||
|
BOOL fChanged;
|
||
|
BOOL fVertical = (BOOL)(prb->ci.style & CCS_VERT);
|
||
|
BOOL fBandBorders;
|
||
|
|
||
|
if (!prb->cBands)
|
||
|
return(0);
|
||
|
|
||
|
if ((prb->ci.style & CCS_NORESIZE) || (prb->ci.style & CCS_NOPARENTALIGN))
|
||
|
// size based on rebar window itself
|
||
|
hwndSize = prb->ci.hwnd;
|
||
|
else if (!(hwndSize = GetParent(prb->ci.hwnd)))
|
||
|
// size based on parent window -- if no parent window, bail now
|
||
|
return(0);
|
||
|
|
||
|
GetClientRect(hwndSize, &rc);
|
||
|
|
||
|
cxBar = (UINT) (fVertical ? (rc.bottom - rc.top) : (rc.right - rc.left));
|
||
|
rc.right = cxBar;
|
||
|
|
||
|
fBandBorders = (BOOL)(prb->ci.style & RBS_BANDBORDERS);
|
||
|
|
||
|
for (i = 0, prbbWalk = prbb; i < prb->cBands; i++, prbbWalk++)
|
||
|
prbbWalk->cx = prbbWalk->cxRequest;
|
||
|
|
||
|
y = 0;
|
||
|
i = 0;
|
||
|
|
||
|
// Main Loop -- loop until all bands are calculated
|
||
|
while (i < prb->cBands)
|
||
|
{
|
||
|
if (fBandBorders && (y > 0))
|
||
|
y += g_cyEdge;
|
||
|
|
||
|
ReLoop:
|
||
|
cxRow = 0;
|
||
|
cxMin = 0;
|
||
|
|
||
|
x = 0;
|
||
|
|
||
|
// Row Loop -- loop until hard line break is found or soft line break
|
||
|
// is necessary
|
||
|
for (j = i, prbbWalk = prbb; j < prb->cBands; j++, prbbWalk++)
|
||
|
{
|
||
|
if (j > i)
|
||
|
{
|
||
|
// not the first band in the row -- check for break style
|
||
|
if (prbbWalk->fStyle & RBBS_BREAK)
|
||
|
break;
|
||
|
|
||
|
if (fBandBorders)
|
||
|
// add in space for vertical etch on palettized display
|
||
|
cxMin += g_cxEdge;
|
||
|
}
|
||
|
|
||
|
if (prbbWalk->fStyle & RBBS_FIXEDSIZE)
|
||
|
{
|
||
|
// remember location of branding brick
|
||
|
iFixed = j;
|
||
|
goto UseMin;
|
||
|
}
|
||
|
|
||
|
if (prbbWalk->cx < prbbWalk->cxMin)
|
||
|
{
|
||
|
UseMin:
|
||
|
prbbWalk->cx = prbbWalk->cxMin;
|
||
|
}
|
||
|
|
||
|
cxMin += prbbWalk->cxMin; // update running total of min widths
|
||
|
|
||
|
// read the assert comment below
|
||
|
if (j > i)
|
||
|
{
|
||
|
// not the first band in row -- check for need to autobreak
|
||
|
if (cxMin > cxBar)
|
||
|
// autobreak here
|
||
|
break;
|
||
|
|
||
|
if (fBandBorders)
|
||
|
// add in space for vertical etch on palettized display
|
||
|
cxRow += g_cxEdge;
|
||
|
}
|
||
|
|
||
|
cxRow += prbbWalk->cx; // update running total of current widths
|
||
|
}
|
||
|
|
||
|
if (!i)
|
||
|
{
|
||
|
// first row -- handle proper placement of branding band
|
||
|
if (iFixed == 0xFFFF)
|
||
|
{
|
||
|
// branding band not yet found; look in the remaining bands
|
||
|
k = j;
|
||
|
while (j < prb->cBands)
|
||
|
{
|
||
|
if (prb->rbbList[j].fStyle & RBBS_FIXEDSIZE)
|
||
|
{
|
||
|
// branding band found; move to 1st row and recompute
|
||
|
RBMoveBand(prb, j, k);
|
||
|
goto ReLoop;
|
||
|
}
|
||
|
j++;
|
||
|
}
|
||
|
// no branding band found -- reset j and continue on
|
||
|
j = k;
|
||
|
}
|
||
|
else
|
||
|
// we have a branding band; move it to
|
||
|
// the rightmost position in the row
|
||
|
RBMoveBand(prb, iFixed, j - 1);
|
||
|
}
|
||
|
|
||
|
// variant:
|
||
|
// now the current row of bands is from i to j - 1
|
||
|
|
||
|
// assert that j != i because then the above variant won't be true
|
||
|
Assert(j != i);
|
||
|
|
||
|
if (cxRow > cxBar)
|
||
|
{
|
||
|
// bands are too long -- shrink bands from right to left
|
||
|
for (k = i; k < j; k++)
|
||
|
{
|
||
|
prbbWalk--;
|
||
|
if (prbbWalk->cx > prbbWalk->cxMin)
|
||
|
{
|
||
|
cxRow -= prbbWalk->cx - prbbWalk->cxMin;
|
||
|
prbbWalk->cx = prbbWalk->cxMin;
|
||
|
if (cxRow <= cxBar)
|
||
|
{
|
||
|
prbbWalk->cx += cxBar - cxRow;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (cxRow < cxBar)
|
||
|
{
|
||
|
// bands are too short -- grow rightmost non-minimized band
|
||
|
for (k = j - 1; k >= i; k--)
|
||
|
{
|
||
|
prbbWalk--;
|
||
|
if ((k == i) || (prbbWalk->cx > prbbWalk->cxMin))
|
||
|
{
|
||
|
// the k == i check means we've made it to the first
|
||
|
// band on this row and so he has to get the cx change
|
||
|
prbbWalk->cx += cxBar - cxRow;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// items from index i to index j-1 (inclusive) WILL fit on one line
|
||
|
cy = RBGetLineHeight(prb, i, j - 1);
|
||
|
|
||
|
fChanged = FALSE; // set if any bands on current row changed position
|
||
|
|
||
|
while (i < j)
|
||
|
{
|
||
|
// go through row of bands, updating positions and heights,
|
||
|
// invalidating as needed
|
||
|
if ((prbb->y != y) || (prbb->x != x) || (prbb->cy != cy))
|
||
|
{
|
||
|
fChanged = TRUE;
|
||
|
rc.left = min(prbb->x, x);
|
||
|
rc.top = min(prbb->y, y);
|
||
|
rc.bottom = max(prbb->y + prbb->cy, y + cy);
|
||
|
if (fBandBorders)
|
||
|
{
|
||
|
// acount for etch line that will need to move
|
||
|
rc.left -= g_cxEdge;
|
||
|
rc.bottom += g_cyEdge/2;
|
||
|
}
|
||
|
if (prb->ci.style & CCS_VERT)
|
||
|
{
|
||
|
UINT uiTemp;
|
||
|
uiTemp = rc.left; rc.left = rc.top; rc.top = uiTemp;
|
||
|
uiTemp = rc.bottom; rc.bottom = rc.right; rc.right = uiTemp;
|
||
|
}
|
||
|
InvalidateRect(prb->ci.hwnd, &rc, TRUE);
|
||
|
}
|
||
|
|
||
|
prbb->x = x;
|
||
|
prbb->y = y;
|
||
|
prbb->cy = cy;
|
||
|
|
||
|
x += prbb->cx;
|
||
|
if (fBandBorders)
|
||
|
x += g_cxEdge;
|
||
|
|
||
|
prbb++;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
// i and prbb now refer to the first band in the next row of bands
|
||
|
y += cy;
|
||
|
}
|
||
|
|
||
|
prb->cy = y;
|
||
|
return(y);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBResize
|
||
|
|
||
|
// recomputes bounding rects for all bands and then resizes rebar and children
|
||
|
// based on these rects
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBResize(PRB prb, BOOL fForceHeightChange)
|
||
|
{
|
||
|
HWND hwndParent;
|
||
|
RECT rc;
|
||
|
UINT cy;
|
||
|
|
||
|
if (!prb || !(hwndParent = GetParent(prb->ci.hwnd)))
|
||
|
return;
|
||
|
|
||
|
cy = prb->cy;
|
||
|
RBRecalc(prb);
|
||
|
|
||
|
GetWindowRect(prb->ci.hwnd, &rc);
|
||
|
MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rc, 2);
|
||
|
RBResizeChildren(prb, NULL, NULL);
|
||
|
NewSize(prb->ci.hwnd, prb->cy, prb->ci.style, rc.left, rc.top, rc.right, rc.bottom);
|
||
|
if ((cy != prb->cy) || fForceHeightChange)
|
||
|
RBSendNotify(prb, RBN_HEIGHTCHANGE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBGetBarHeight
|
||
|
|
||
|
// returns total height of given rebar, recalculating heights if necessary
|
||
|
|
||
|
|
||
|
UINT NEAR PASCAL RBGetBarHeight(PRB prb)
|
||
|
{
|
||
|
return((prb->cBands && !prb->cy) ? RBRecalc(prb) : prb->cy);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBSetFont
|
||
|
|
||
|
// sets the rebar band title font to the current system-wide caption font
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBSetFont(PRB prb, WPARAM wParam)
|
||
|
{
|
||
|
HFONT hOldFont;
|
||
|
#ifdef IEWIN31_25
|
||
|
LOGFONT lf;
|
||
|
#else
|
||
|
NONCLIENTMETRICS ncm;
|
||
|
#endif
|
||
|
TEXTMETRIC tm;
|
||
|
HDC hdc;
|
||
|
BOOL fChange = FALSE;
|
||
|
UINT i;
|
||
|
|
||
|
if ((wParam != 0) && (wParam != SPI_SETNONCLIENTMETRICS))
|
||
|
return(FALSE);
|
||
|
|
||
|
#ifdef WIN32
|
||
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
||
|
if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
|
||
|
return(FALSE);
|
||
|
#else
|
||
|
#ifdef IEWIN31_25
|
||
|
if (!SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE))
|
||
|
return(FALSE);
|
||
|
#else
|
||
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
||
|
if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, (UINT)ncm.cbSize, &ncm, 0))
|
||
|
return(FALSE);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
hOldFont = prb->hFont;
|
||
|
|
||
|
#ifdef IEWIN31_25
|
||
|
lf.lfWeight = FW_NORMAL;
|
||
|
if (!(prb->hFont = CreateFontIndirect(&lf)))
|
||
|
#else
|
||
|
ncm.lfCaptionFont.lfWeight = FW_NORMAL;
|
||
|
if (!(prb->hFont = CreateFontIndirect(&ncm.lfCaptionFont)))
|
||
|
#endif
|
||
|
{
|
||
|
prb->hFont = hOldFont;
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
if (hOldFont)
|
||
|
DeleteObject(hOldFont);
|
||
|
|
||
|
hdc = GetDC(prb->ci.hwnd);
|
||
|
if (!hdc)
|
||
|
return(FALSE);
|
||
|
|
||
|
hOldFont = SelectObject(hdc, prb->hFont);
|
||
|
GetTextMetrics(hdc, &tm);
|
||
|
|
||
|
if (prb->cyFont != (UINT) tm.tmHeight)
|
||
|
{
|
||
|
prb->cyFont = tm.tmHeight;
|
||
|
fChange = TRUE;
|
||
|
}
|
||
|
|
||
|
// adjust bands
|
||
|
for (i = 0; i < prb->cBands; i++)
|
||
|
fChange |= RBBCalcTextExtent(prb, prb->rbbList + i, hdc);
|
||
|
|
||
|
SelectObject(hdc, hOldFont);
|
||
|
ReleaseDC(prb->ci.hwnd, hdc);
|
||
|
|
||
|
if (fChange)
|
||
|
RBResize(prb, FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBDrawBand
|
||
|
|
||
|
// draws the title icon and title text of the given band into the given DC
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBDrawBand(PRB prb, PRBB prbb, HDC hdc)
|
||
|
{
|
||
|
IMAGELISTDRAWPARAMS imldp;
|
||
|
int xStart, yCenter;
|
||
|
COLORREF clrBackSave, clrForeSave;
|
||
|
int iModeSave;
|
||
|
BOOL fVertical = (BOOL)(prb->ci.style & CCS_VERT);
|
||
|
UINT yStart;
|
||
|
NMCUSTOMDRAW nmcd;
|
||
|
DWORD dwRet;
|
||
|
|
||
|
clrForeSave = SetTextColor(hdc, g_clrBtnText);
|
||
|
clrBackSave = SetBkColor(hdc, g_clrBtnFace);
|
||
|
if (prbb->hbmBack)
|
||
|
iModeSave = SetBkMode(hdc, TRANSPARENT);
|
||
|
|
||
|
nmcd.hdc = hdc;
|
||
|
nmcd.dwItemSpec = prbb->wID;
|
||
|
nmcd.uItemState = 0;
|
||
|
nmcd.lItemlParam = 0;
|
||
|
dwRet = CICustomDrawNotify(&prb->ci, CDDS_ITEMPREPAINT, &nmcd);
|
||
|
|
||
|
if (!(dwRet & CDRF_SKIPDEFAULT))
|
||
|
{
|
||
|
yCenter = prbb->y + (prbb->cy / 2);
|
||
|
|
||
|
xStart = prbb->x;
|
||
|
if (RBCanBandMove(prb, prbb))
|
||
|
{
|
||
|
RECT rc;
|
||
|
int c;
|
||
|
|
||
|
if (fVertical)
|
||
|
{
|
||
|
c = 3 * g_cyBorder;
|
||
|
xStart += 2 * g_cyBorder;
|
||
|
|
||
|
SetRect(&rc, prbb->y + g_cxEdge, xStart, prbb->y + prbb->cy - g_cxEdge, xStart + c);
|
||
|
DrawEdge(hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
|
||
|
rc.top += c;
|
||
|
rc.bottom += c;
|
||
|
DrawEdge(hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
|
||
|
xStart += 2 * c;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
c = 3 * g_cxBorder;
|
||
|
xStart += 2 * g_cxBorder;
|
||
|
|
||
|
SetRect(&rc, xStart, prbb->y + g_cyEdge, xStart + c, prbb->y + prbb->cy - g_cyEdge);
|
||
|
DrawEdge(hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
|
||
|
rc.left += c;
|
||
|
rc.right += c;
|
||
|
DrawEdge(hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
|
||
|
xStart += 2 * c;
|
||
|
}
|
||
|
}
|
||
|
xStart += 2 * (fVertical ? g_cyEdge : g_cxEdge);
|
||
|
|
||
|
if (prbb->iImage != -1)
|
||
|
{
|
||
|
yStart = yCenter - ((fVertical ? prb->cxImage : prb->cyImage) / 2);
|
||
|
imldp.cbSize = sizeof(imldp);
|
||
|
imldp.himl = prb->himl;
|
||
|
imldp.i = prbb->iImage;
|
||
|
imldp.hdcDst = hdc;
|
||
|
imldp.x = (fVertical ? yStart : xStart);
|
||
|
imldp.y = (fVertical ? xStart : yStart);
|
||
|
imldp.cx = 0;
|
||
|
imldp.cy = 0;
|
||
|
imldp.xBitmap= 0;
|
||
|
imldp.yBitmap= 0;
|
||
|
imldp.rgbBk = CLR_DEFAULT;
|
||
|
imldp.rgbFg = CLR_DEFAULT;
|
||
|
imldp.fStyle = ILD_TRANSPARENT;
|
||
|
|
||
|
ImageList_DrawIndirect(&imldp);
|
||
|
xStart += (fVertical ? (prb->cyImage + g_cyEdge) : (prb->cxImage + g_cxEdge));
|
||
|
}
|
||
|
|
||
|
if (prbb->lpText)
|
||
|
{
|
||
|
HFONT hFontSave = SelectObject(hdc, prb->hFont);
|
||
|
if(fVertical)
|
||
|
TextOut(hdc, yCenter - (prbb->cxText / 2), xStart,
|
||
|
prbb->lpText, lstrlen(prbb->lpText));
|
||
|
else
|
||
|
TextOut(hdc, xStart, yCenter - (prb->cyFont / 2),
|
||
|
prbb->lpText, lstrlen(prbb->lpText));
|
||
|
|
||
|
SelectObject(hdc, hFontSave);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwRet & CDRF_NOTIFYPOSTPAINT)
|
||
|
CICustomDrawNotify(&prb->ci, CDDS_ITEMPOSTPAINT, &nmcd);
|
||
|
|
||
|
if (prbb->hbmBack)
|
||
|
SetBkMode(hdc, iModeSave);
|
||
|
SetTextColor(hdc, clrForeSave);
|
||
|
SetBkColor(hdc, clrBackSave);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBPaint
|
||
|
|
||
|
// processes WM_PAINT message
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBPaint(PRB prb, HDC hdcIn)
|
||
|
{
|
||
|
HDC hdc = hdcIn;
|
||
|
PAINTSTRUCT ps;
|
||
|
UINT i;
|
||
|
NMCUSTOMDRAW nmcd;
|
||
|
|
||
|
if (!hdcIn)
|
||
|
hdc = BeginPaint(prb->ci.hwnd, &ps);
|
||
|
|
||
|
nmcd.hdc = hdc;
|
||
|
nmcd.uItemState = 0;
|
||
|
nmcd.lItemlParam = 0;
|
||
|
prb->ci.dwCustom = CICustomDrawNotify(&prb->ci, CDDS_PREPAINT, &nmcd);
|
||
|
|
||
|
if (!(prb->ci.dwCustom & CDRF_SKIPDEFAULT))
|
||
|
{
|
||
|
for (i = 0; i < prb->cBands; i++)
|
||
|
RBDrawBand(prb, prb->rbbList + i, hdc);
|
||
|
}
|
||
|
|
||
|
if (prb->ci.dwCustom & CDRF_NOTIFYPOSTPAINT)
|
||
|
CICustomDrawNotify(&prb->ci, CDDS_POSTPAINT, &nmcd);
|
||
|
|
||
|
if (!hdcIn)
|
||
|
EndPaint(prb->ci.hwnd, &ps);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBTileBlt
|
||
|
|
||
|
// Fills the given rectangle with the rebar's background bitmap, tiling if
|
||
|
// necessary
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBTileBlt(PRB prb, PRBB prbb, UINT x, UINT y, UINT cx, UINT cy, HDC hdcDst, HDC hdcSrc)
|
||
|
{
|
||
|
UINT xOff = 0;
|
||
|
UINT yOff = 0;
|
||
|
BOOL fxTile, fyTile;
|
||
|
int cxPart, cyPart;
|
||
|
|
||
|
if (!(prbb->fStyle & RBBS_FIXEDBMP))
|
||
|
{
|
||
|
if (prb->ci.style & CCS_VERT)
|
||
|
{
|
||
|
xOff = -prbb->y;
|
||
|
yOff = -prbb->x;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
xOff = -prbb->x;
|
||
|
yOff = -prbb->y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
xOff += x;
|
||
|
if (xOff >= prbb->cxBmp)
|
||
|
xOff %= prbb->cxBmp;
|
||
|
|
||
|
yOff += y;
|
||
|
if (yOff >= prbb->cyBmp)
|
||
|
yOff %= prbb->cyBmp;
|
||
|
|
||
|
ReCheck:
|
||
|
fxTile = ((xOff + cx) > prbb->cxBmp);
|
||
|
fyTile = ((yOff + cy) > prbb->cyBmp);
|
||
|
|
||
|
if (!fxTile && !fyTile)
|
||
|
{
|
||
|
// no tiling needed -- blt and leave
|
||
|
BitBlt(hdcDst, x, y, cx, cy, hdcSrc, xOff, yOff, SRCCOPY);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!fxTile)
|
||
|
{
|
||
|
// vertically tile
|
||
|
cyPart = prbb->cyBmp - yOff;
|
||
|
BitBlt(hdcDst, x, y, cx, cyPart, hdcSrc, xOff, yOff, SRCCOPY);
|
||
|
y += cyPart;
|
||
|
cy -= cyPart;
|
||
|
yOff = 0;
|
||
|
goto ReCheck;
|
||
|
}
|
||
|
|
||
|
if (!fyTile)
|
||
|
{
|
||
|
// horizontally tile
|
||
|
cxPart = prbb->cxBmp - xOff;
|
||
|
BitBlt(hdcDst, x, y, cxPart, cy, hdcSrc, xOff, yOff, SRCCOPY);
|
||
|
x += cxPart;
|
||
|
cx -= cxPart;
|
||
|
xOff = 0;
|
||
|
goto ReCheck;
|
||
|
}
|
||
|
|
||
|
// tile both ways
|
||
|
cyPart = prbb->cyBmp - yOff;
|
||
|
RBTileBlt(prb, prbb, x, y, cx, cyPart, hdcDst, hdcSrc);
|
||
|
y += cyPart;
|
||
|
cy -= cyPart;
|
||
|
yOff = 0;
|
||
|
goto ReCheck;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBHitTest
|
||
|
|
||
|
// returns the index to the band that the given point lies in, or -1 if outside
|
||
|
// of all bands. Also, sets flags to indicate which part of the band the
|
||
|
// point lies in.
|
||
|
|
||
|
|
||
|
int FAR PASCAL RBHitTest(PRB prb, LPRBHITTESTINFO prbht)
|
||
|
{
|
||
|
int i;
|
||
|
PRBB prbb = prb->rbbList;
|
||
|
POINT pt;
|
||
|
BOOL fVert = (BOOL)(prb->ci.style & CCS_VERT);
|
||
|
int cx;
|
||
|
|
||
|
if (fVert)
|
||
|
{
|
||
|
pt.x = prbht->pt.y;
|
||
|
pt.y = prbht->pt.x;
|
||
|
}
|
||
|
else
|
||
|
pt = prbht->pt;
|
||
|
|
||
|
for (i = 0; i < (int) prb->cBands; i++)
|
||
|
{
|
||
|
if ((pt.x >= prbb->x) && (pt.y >= prbb->y) &&
|
||
|
(pt.x <= (prbb->x + prbb->cx)) && (pt.y <= (prbb->y + prbb->cy)))
|
||
|
{
|
||
|
cx = prbb->cxMin - prbb->cxMinChild;
|
||
|
if (pt.x <= (int) (prbb->x + cx))
|
||
|
{
|
||
|
cx = RB_GRABWIDTH * (fVert ? g_cyBorder : g_cxBorder);
|
||
|
if (RBCanBandMove(prb, prb->rbbList + i) &&
|
||
|
(pt.x <= (int) (prbb->x + cx)))
|
||
|
prbht->flags = RBHT_GRABBER;
|
||
|
else
|
||
|
prbht->flags = RBHT_CAPTION;
|
||
|
}
|
||
|
else
|
||
|
prbht->flags = RBHT_CLIENT;
|
||
|
|
||
|
prbht->iBand = i;
|
||
|
return(i);
|
||
|
break;
|
||
|
}
|
||
|
prbb++;
|
||
|
}
|
||
|
|
||
|
prbht->flags = RBHT_NOWHERE;
|
||
|
prbht->iBand = -1;
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// RBEraseBkgnd
|
||
|
|
||
|
// processes WM_ERASEBKGND message by drawing band borders, if necessary, and
|
||
|
// filling in the rebar bands with their background color
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBEraseBkgnd(PRB prb, HDC hdc, int iBand)
|
||
|
{
|
||
|
BOOL fVertical = (BOOL)(prb->ci.style & CCS_VERT);
|
||
|
NMCUSTOMDRAW nmcd;
|
||
|
DWORD dwItemRet;
|
||
|
BOOL fBandBorders;
|
||
|
RECT rcClient;
|
||
|
HDC hdcMem = NULL;
|
||
|
HPALETTE hpalSave = NULL;
|
||
|
UINT i;
|
||
|
PRBB prbb = prb->rbbList;
|
||
|
|
||
|
nmcd.hdc = hdc;
|
||
|
nmcd.uItemState = 0;
|
||
|
nmcd.lItemlParam = 0;
|
||
|
prb->ci.dwCustom = CICustomDrawNotify(&prb->ci, CDDS_PREERASE, &nmcd);
|
||
|
|
||
|
if (!(prb->ci.dwCustom & CDRF_SKIPDEFAULT))
|
||
|
{
|
||
|
if (fBandBorders = (BOOL)(prb->ci.style & RBS_BANDBORDERS))
|
||
|
GetClientRect(prb->ci.hwnd, &rcClient);
|
||
|
|
||
|
for (i = 0; i < prb->cBands; i++, prbb++)
|
||
|
{
|
||
|
if (fVertical)
|
||
|
SetRect(&nmcd.rc, prbb->y, prbb->x, prbb->y + prbb->cy, prbb->x + prbb->cx);
|
||
|
else
|
||
|
SetRect(&nmcd.rc, prbb->x, prbb->y, prbb->x + prbb->cx, prbb->y + prbb->cy);
|
||
|
|
||
|
if (fBandBorders)
|
||
|
{
|
||
|
if (prbb->x)
|
||
|
{
|
||
|
// draw etch between bands on same row
|
||
|
if (fVertical)
|
||
|
{
|
||
|
nmcd.rc.right += g_cxEdge / 2;
|
||
|
nmcd.rc.top -= g_cyEdge;
|
||
|
DrawEdge(hdc, &nmcd.rc, EDGE_ETCHED, BF_TOP);
|
||
|
nmcd.rc.right -= g_cxEdge / 2;
|
||
|
nmcd.rc.top += g_cyEdge;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nmcd.rc.bottom += g_cyEdge / 2;
|
||
|
nmcd.rc.left -= g_cxEdge;
|
||
|
DrawEdge(hdc, &nmcd.rc, EDGE_ETCHED, BF_LEFT);
|
||
|
nmcd.rc.bottom -= g_cyEdge / 2;
|
||
|
nmcd.rc.left += g_cxEdge;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// draw etch between rows
|
||
|
if (fVertical)
|
||
|
{
|
||
|
rcClient.right = prbb->y + prbb->cy + g_cxEdge;
|
||
|
DrawEdge(hdc, &rcClient, EDGE_ETCHED, BF_RIGHT);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rcClient.bottom = prbb->y + prbb->cy + g_cyEdge;
|
||
|
DrawEdge(hdc, &rcClient, EDGE_ETCHED, BF_BOTTOM);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
nmcd.dwItemSpec = prbb->wID;
|
||
|
nmcd.uItemState = 0;
|
||
|
dwItemRet = CICustomDrawNotify(&prb->ci, CDDS_ITEMPREERASE, &nmcd);
|
||
|
|
||
|
if (!(dwItemRet & CDRF_SKIPDEFAULT))
|
||
|
{
|
||
|
if (prbb->hbmBack)
|
||
|
{
|
||
|
if (!hdcMem)
|
||
|
{
|
||
|
if (!(hdcMem = CreateCompatibleDC(hdc)))
|
||
|
continue;
|
||
|
|
||
|
if (prb->hpal)
|
||
|
{
|
||
|
// Hack: For IEWIN31_25, we set the palette in the custom notify.
|
||
|
#ifndef IEWIN31_25
|
||
|
|
||
|
hpalSave = SelectPalette(hdc, prb->hpal, TRUE);
|
||
|
RealizePalette(hdc);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SelectObject(hdcMem, prbb->hbmBack);
|
||
|
|
||
|
RBTileBlt(prb, prbb, nmcd.rc.left, nmcd.rc.top, nmcd.rc.right - nmcd.rc.left,
|
||
|
nmcd.rc.bottom - nmcd.rc.top, hdc, hdcMem);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HBRUSH hbr = CreateSolidBrush(prbb->clrBack);
|
||
|
FillRect(hdc, &nmcd.rc, hbr);
|
||
|
DeleteObject(hbr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwItemRet & CDRF_NOTIFYPOSTERASE)
|
||
|
CICustomDrawNotify(&prb->ci, CDDS_ITEMPOSTERASE, &nmcd);
|
||
|
}
|
||
|
|
||
|
if (hdcMem)
|
||
|
{
|
||
|
DeleteDC(hdcMem);
|
||
|
#ifndef IEWIN31_25
|
||
|
if (prb->hpal)
|
||
|
SelectPalette(hdc, hpalSave, FALSE);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (prb->ci.dwCustom & CDRF_NOTIFYPOSTERASE)
|
||
|
{
|
||
|
nmcd.uItemState = 0;
|
||
|
nmcd.dwItemSpec = 0;
|
||
|
nmcd.lItemlParam = 0;
|
||
|
CICustomDrawNotify(&prb->ci, CDDS_POSTERASE, &nmcd);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBGetBarInfo
|
||
|
|
||
|
// retrieves the indicated values from the rebar's internal structure
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBGetBarInfo(PRB prb, LPREBARINFO lprbi)
|
||
|
{
|
||
|
if (!prb || (lprbi->cbSize != sizeof(REBARINFO)))
|
||
|
return(FALSE);
|
||
|
|
||
|
if (lprbi->fMask & RBIM_IMAGELIST)
|
||
|
lprbi->himl = prb->himl;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBSetBarInfo
|
||
|
|
||
|
// sets the indicated values in the rebar's internal structure, recalculating
|
||
|
// and refreshing as needed
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBSetBarInfo(PRB prb, LPREBARINFO lprbi)
|
||
|
{
|
||
|
if (!prb || (lprbi->cbSize != sizeof(REBARINFO)))
|
||
|
return(FALSE);
|
||
|
|
||
|
if (lprbi->fMask & RBIM_IMAGELIST)
|
||
|
{
|
||
|
HIMAGELIST himl = prb->himl;
|
||
|
UINT cxOld, cyOld;
|
||
|
|
||
|
//todo:validate lprbi->himl
|
||
|
prb->himl = lprbi->himl;
|
||
|
cxOld = prb->cxImage;
|
||
|
cyOld = prb->cyImage;
|
||
|
ImageList_GetIconSize(prb->himl, &prb->cxImage, &prb->cyImage);
|
||
|
if ((prb->cxImage != cxOld) || (prb->cyImage != cyOld))
|
||
|
{
|
||
|
UINT i;
|
||
|
|
||
|
for (i = 0; i < prb->cBands; i++)
|
||
|
RBBCalcMinWidth(prb, prb->rbbList + i);
|
||
|
|
||
|
RBResize(prb, FALSE);
|
||
|
}
|
||
|
else
|
||
|
InvalidateRect(prb->ci.hwnd, NULL, TRUE);
|
||
|
lprbi->himl = himl;
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
PRBB RBPtrFromID(PRB prb, UINT wID)
|
||
|
{
|
||
|
UINT i;
|
||
|
PRBB prbb = prb->rbbList;
|
||
|
|
||
|
for (i = 0; i < prb->cBands; i++, prbb++)
|
||
|
{
|
||
|
if (prbb->wID == wID)
|
||
|
return(prbb);
|
||
|
}
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBGetBandInfo
|
||
|
|
||
|
// retrieves the indicated values from the specified band's internal structure
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBGetBandInfo(PRB prb, UINT uBand, LPREBARBANDINFO lprbbi)
|
||
|
{
|
||
|
PRBB prbb;
|
||
|
|
||
|
if (!prb || (uBand >= prb->cBands) || (lprbbi->cbSize != sizeof(REBARBANDINFO)))
|
||
|
return(FALSE);
|
||
|
|
||
|
prbb = prb->rbbList + uBand;
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_SIZE)
|
||
|
lprbbi->cx = prbb->cxRequest;
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_STYLE)
|
||
|
lprbbi->fStyle = prbb->fStyle;
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_COLORS)
|
||
|
{
|
||
|
lprbbi->clrFore = prbb->clrFore;
|
||
|
lprbbi->clrBack = prbb->clrBack;
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_TEXT)
|
||
|
{
|
||
|
UINT cch = prbb->lpText ? lstrlen(prbb->lpText) : 0;
|
||
|
|
||
|
if (!lprbbi->cch || !lprbbi->lpText || (lprbbi->cch <= cch))
|
||
|
lprbbi->cch = cch + 1;
|
||
|
else if (prbb->lpText)
|
||
|
lstrcpy(lprbbi->lpText, prbb->lpText);
|
||
|
else
|
||
|
// no text -- so just make it an empty string
|
||
|
lprbbi->lpText[0] = 0;
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_IMAGE)
|
||
|
lprbbi->iImage = prbb->iImage;
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_CHILD)
|
||
|
lprbbi->hwndChild = prbb->hwndChild;
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_CHILDSIZE)
|
||
|
{
|
||
|
lprbbi->cxMinChild = prbb->cxMinChild;
|
||
|
lprbbi->cyMinChild = prbb->cyMinChild;
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_BACKGROUND)
|
||
|
lprbbi->hbmBack = prbb->hbmBack;
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_ID)
|
||
|
lprbbi->wID = prbb->wID;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBSetBandInfo
|
||
|
|
||
|
// sets the indicated values in the specified band's internal structure,
|
||
|
// recalculating and refreshing as needed
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBSetBandInfo(PRB prb, UINT uBand, LPREBARBANDINFO lprbbi)
|
||
|
{
|
||
|
PRBB prbb;
|
||
|
BOOL fRefresh = FALSE;
|
||
|
BOOL fRecalc = FALSE;
|
||
|
RECT rc;
|
||
|
|
||
|
if (!prb || (uBand >= prb->cBands) || (lprbbi->cbSize != sizeof(REBARBANDINFO)))
|
||
|
return(FALSE);
|
||
|
|
||
|
prbb = prb->rbbList + uBand;
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_TEXT)
|
||
|
{
|
||
|
UINT cbText;
|
||
|
LPTSTR lpNew = NULL;
|
||
|
|
||
|
if ((!prbb->lpText && lprbbi->lpText) || lstrcmp(lprbbi->lpText, prbb->lpText))
|
||
|
{
|
||
|
if (lprbbi->lpText && (cbText = lstrlen(lprbbi->lpText)))
|
||
|
{
|
||
|
if (!(lpNew = (LPTSTR)LocalAlloc(LPTR, (cbText + 1)*sizeof(TCHAR))))
|
||
|
return(FALSE);
|
||
|
|
||
|
lstrcpy(lpNew, lprbbi->lpText);
|
||
|
}
|
||
|
|
||
|
if (prbb->lpText)
|
||
|
LocalFree((HLOCAL) prbb->lpText);
|
||
|
|
||
|
prbb->lpText = lpNew;
|
||
|
if (RBBCalcTextExtent(prb, prbb, NULL))
|
||
|
fRecalc = TRUE;
|
||
|
else
|
||
|
fRefresh = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_STYLE)
|
||
|
{
|
||
|
UINT fStylePrev = prbb->fStyle;
|
||
|
prbb->fStyle = lprbbi->fStyle;
|
||
|
|
||
|
if (prbb->fStyle ^ fStylePrev)
|
||
|
fRecalc = TRUE;
|
||
|
|
||
|
if ((prbb->fStyle & RBBS_FIXEDSIZE) && !(fStylePrev & RBBS_FIXEDSIZE))
|
||
|
prbb->cxMin = prbb->cx;
|
||
|
else if (!(prbb->fStyle & RBBS_FIXEDSIZE) && (fStylePrev & RBBS_FIXEDSIZE))
|
||
|
RBBCalcMinWidth(prb, prbb);
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_SIZE)
|
||
|
{
|
||
|
if (prbb->cxRequest != (int) lprbbi->cx)
|
||
|
{
|
||
|
fRecalc = TRUE;
|
||
|
prbb->cxRequest = (int) lprbbi->cx;
|
||
|
}
|
||
|
|
||
|
if (prbb->fStyle & RBBS_FIXEDSIZE)
|
||
|
prbb->cxMin = prbb->cxRequest;
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_COLORS)
|
||
|
{
|
||
|
prbb->clrFore = lprbbi->clrFore;
|
||
|
prbb->clrBack = lprbbi->clrBack;
|
||
|
fRefresh = TRUE;
|
||
|
}
|
||
|
|
||
|
if ((lprbbi->fMask & RBBIM_IMAGE) && (prbb->iImage != lprbbi->iImage))
|
||
|
{
|
||
|
BOOL fToggleBmp = ((prbb->iImage == -1) || (lprbbi->iImage == -1));
|
||
|
|
||
|
prbb->iImage = lprbbi->iImage;
|
||
|
|
||
|
if (fToggleBmp)
|
||
|
{
|
||
|
fRecalc = TRUE;
|
||
|
RBBCalcMinWidth(prb, prbb);
|
||
|
}
|
||
|
else
|
||
|
fRefresh = TRUE;
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_CHILD)
|
||
|
{
|
||
|
if (prbb->hwndChild)
|
||
|
ShowWindow(prbb->hwndChild, SW_HIDE);
|
||
|
|
||
|
prbb->hwndChild = lprbbi->hwndChild;
|
||
|
SetParent(prbb->hwndChild, prb->ci.hwnd);
|
||
|
ShowWindow(prbb->hwndChild, SW_SHOW);
|
||
|
//RBResizeChildren(prb, NULL, NULL);
|
||
|
fRecalc = TRUE;
|
||
|
}
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_CHILDSIZE)
|
||
|
{
|
||
|
if (prbb->cyMinChild != lprbbi->cyMinChild)
|
||
|
{
|
||
|
prbb->cyMinChild = lprbbi->cyMinChild;
|
||
|
// TODO: revisit optimization:
|
||
|
// if (RBBGetHeight(prb, prbb) != (UINT) prbb->cy)
|
||
|
fRecalc = TRUE;
|
||
|
}
|
||
|
|
||
|
if (prbb->cxMinChild != lprbbi->cxMinChild)
|
||
|
{
|
||
|
prbb->cxMinChild = lprbbi->cxMinChild;
|
||
|
RBBCalcMinWidth(prb, prbb);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#ifdef IEWIN31_25
|
||
|
if (lprbbi->fMask & RBBIM_BACKGROUND)
|
||
|
{
|
||
|
BITMAP bmp;
|
||
|
|
||
|
if (lprbbi->hbmBack && !GetObject(lprbbi->hbmBack, sizeof(BITMAP), &bmp))
|
||
|
return(FALSE);
|
||
|
|
||
|
prbb->hbmBack = lprbbi->hbmBack;
|
||
|
prbb->cxBmp = bmp.bmWidth;
|
||
|
prbb->cyBmp = bmp.bmHeight;
|
||
|
fRefresh = TRUE;
|
||
|
}
|
||
|
#else
|
||
|
if (lprbbi->fMask & RBBIM_BACKGROUND)
|
||
|
{
|
||
|
DIBSECTION dib;
|
||
|
|
||
|
if (lprbbi->hbmBack && !GetObject(lprbbi->hbmBack, sizeof(DIBSECTION), &dib))
|
||
|
return(FALSE);
|
||
|
|
||
|
prbb->hbmBack = lprbbi->hbmBack;
|
||
|
prbb->cxBmp = dib.dsBm.bmWidth;
|
||
|
prbb->cyBmp = dib.dsBm.bmHeight;
|
||
|
fRefresh = TRUE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (lprbbi->fMask & RBBIM_ID)
|
||
|
prbb->wID = lprbbi->wID;
|
||
|
|
||
|
if (fRecalc)
|
||
|
RBResize(prb, FALSE);
|
||
|
if (fRefresh)
|
||
|
{
|
||
|
if (prb->ci.style & CCS_VERT)
|
||
|
SetRect(&rc, prbb->y, prbb->x, prbb->y + prbb->cy, prbb->x + prbb->cx);
|
||
|
else
|
||
|
SetRect(&rc, prbb->x, prbb->y, prbb->x + prbb->cx, prbb->y + prbb->cy);
|
||
|
InvalidateRect(prb->ci.hwnd, &rc, TRUE);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBReallocBands
|
||
|
|
||
|
// reallocates the array of bands pointed to by prb->rbbList to the given
|
||
|
// number of bands
|
||
|
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBReallocBands(PRB prb, UINT cBands)
|
||
|
{
|
||
|
PRBB rbbList;
|
||
|
|
||
|
if (!cBands)
|
||
|
{
|
||
|
if (prb->rbbList)
|
||
|
{
|
||
|
LocalFree((HLOCAL) prb->rbbList);
|
||
|
prb->rbbList = NULL;
|
||
|
}
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
if (!prb->rbbList)
|
||
|
{
|
||
|
if (!(rbbList = (PRBB) LocalAlloc(LMEM_FIXED, sizeof(RBB) * cBands)))
|
||
|
return(FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rbbList = (PRBB) LocalReAlloc(prb->rbbList, cBands * sizeof(RBB), LMEM_MOVEABLE);
|
||
|
if (!rbbList)
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
prb->rbbList = rbbList;
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBDeleteBand
|
||
|
|
||
|
// deletes the indicated band from the rebar's band array (rbbList) and
|
||
|
// decrements the rebar's band count (cBands)
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBDeleteBand(PRB prb, UINT uBand)
|
||
|
{
|
||
|
PRBB prbb;
|
||
|
PRBB prbbStop;
|
||
|
BOOL fRecalcFirst;
|
||
|
|
||
|
if (!prb || (uBand >= prb->cBands))
|
||
|
return(FALSE);
|
||
|
|
||
|
prbb = prb->rbbList + uBand;
|
||
|
|
||
|
if (prbb->lpText)
|
||
|
{
|
||
|
LocalFree((HLOCAL) prbb->lpText);
|
||
|
prbb->lpText = NULL;
|
||
|
}
|
||
|
|
||
|
// don't destroy the hbmBack 'cause it's given to us by app
|
||
|
|
||
|
prb->cBands--;
|
||
|
|
||
|
fRecalcFirst = (!uBand && prb->cBands);
|
||
|
|
||
|
if (prbb->hwndChild)
|
||
|
ShowWindow(prbb->hwndChild, SW_HIDE);
|
||
|
|
||
|
prbbStop = prb->rbbList + prb->cBands;
|
||
|
for ( ; prbb < prbbStop; prbb++)
|
||
|
*prbb = *(prbb + 1);
|
||
|
|
||
|
if (fRecalcFirst)
|
||
|
{
|
||
|
if ((prb->rbbList->fStyle & RBBS_FIXEDSIZE) && (prb->cBands > 1))
|
||
|
// get rid of line break on NEW first item
|
||
|
prb->rbbList[1].fStyle &= ~RBBS_BREAK;
|
||
|
|
||
|
if (prb->ci.style & RBS_FIXEDORDER)
|
||
|
// this is because the min width is now based on it's movability -- and
|
||
|
// since we are deleting the first item, the new first item becomes
|
||
|
// immovable
|
||
|
RBBCalcMinWidth(prb, prb->rbbList);
|
||
|
}
|
||
|
|
||
|
RBReallocBands(prb, prb->cBands);
|
||
|
|
||
|
RBResize(prb, FALSE);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBInsertBand
|
||
|
|
||
|
// inserts a new band at the given position in the rebar's band array (rbbList),
|
||
|
// increments the rebar's band count (cBands), and sets the band's structure
|
||
|
// based on the given REBARBANDINFO structure.
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBInsertBand(PRB prb, UINT uBand, LPREBARBANDINFO lprbbi)
|
||
|
{
|
||
|
PRBB prbb;
|
||
|
UINT i;
|
||
|
|
||
|
if (!prb || (lprbbi->cbSize != sizeof(REBARBANDINFO)))
|
||
|
return(FALSE);
|
||
|
|
||
|
if (uBand == -1)
|
||
|
uBand = prb->cBands;
|
||
|
else if (uBand > prb->cBands)
|
||
|
return(FALSE);
|
||
|
|
||
|
if (!RBReallocBands(prb, prb->cBands + 1))
|
||
|
return(FALSE);
|
||
|
|
||
|
for (i = prb->cBands; i > uBand; i--)
|
||
|
prb->rbbList[i] = prb->rbbList[i - 1];
|
||
|
|
||
|
prbb = prb->rbbList + uBand;
|
||
|
|
||
|
prb->cBands++;
|
||
|
|
||
|
prbb->fStyle = 0;
|
||
|
prbb->clrFore = 0x00000000;
|
||
|
prbb->clrBack = 0x00FFFFFF;
|
||
|
prbb->lpText = NULL;
|
||
|
prbb->cxText = 0;
|
||
|
prbb->iImage = -1;
|
||
|
prbb->hwndChild = NULL;
|
||
|
prbb->cxMinChild = 0;
|
||
|
prbb->cyMinChild = 0;
|
||
|
prbb->hbmBack = 0;
|
||
|
prbb->x = 0;
|
||
|
prbb->y = 0;
|
||
|
prbb->cx = 0;
|
||
|
prbb->cy = 0;
|
||
|
prbb->cxRestored = 0;
|
||
|
prbb->cxRequest = 0;
|
||
|
RBBCalcMinWidth(prb, prbb);
|
||
|
|
||
|
if (!RBSetBandInfo(prb, uBand, lprbbi))
|
||
|
{
|
||
|
RBDeleteBand(prb, uBand);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
#pragma code_seg(CODESEG_INIT)
|
||
|
|
||
|
LRESULT CALLBACK ReBarWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
BOOL FAR PASCAL InitReBarClass(HINSTANCE hInstance)
|
||
|
{
|
||
|
WNDCLASS wc;
|
||
|
|
||
|
if (!GetClassInfo(hInstance, c_szReBarClass, &wc))
|
||
|
{
|
||
|
#ifndef WIN32
|
||
|
#ifndef IEWIN31
|
||
|
extern LRESULT CALLBACK _ReBarWndProc(HWND, UINT, WPARAM, LPARAM);
|
||
|
wc.lpfnWndProc = _ReBarWndProc;
|
||
|
#else
|
||
|
wc.lpfnWndProc = (WNDPROC) ReBarWndProc;
|
||
|
#endif
|
||
|
#else
|
||
|
wc.lpfnWndProc = (WNDPROC) ReBarWndProc;
|
||
|
#endif
|
||
|
|
||
|
wc.lpszClassName= c_szReBarClass;
|
||
|
wc.style = CS_GLOBALCLASS;
|
||
|
wc.cbClsExtra = 0;
|
||
|
wc.cbWndExtra = sizeof(PRB);
|
||
|
wc.hInstance = hInstance; // use DLL instance if in DLL
|
||
|
wc.hIcon = NULL;
|
||
|
wc.hCursor = NULL;
|
||
|
wc.hbrBackground= (HBRUSH)(COLOR_BTNFACE + 1);
|
||
|
wc.lpszMenuName = NULL;
|
||
|
|
||
|
if (!RegisterClass(&wc))
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
#pragma code_seg()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// RBToggleBand
|
||
|
|
||
|
// switches a band between it's maximized and minimized state, based on where
|
||
|
// the user clicked
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBToggleBand(PRB prb)
|
||
|
{
|
||
|
PRBB prbb = prb->rbbList + prb->iCapture;
|
||
|
RECT rc;
|
||
|
int x;
|
||
|
PRBB prbbNext;
|
||
|
int xRight;
|
||
|
BOOL fBandBorders = (BOOL)(prb->ci.style & RBS_BANDBORDERS);
|
||
|
|
||
|
if (!prbb->x)
|
||
|
{
|
||
|
//left-most band -- slide the next band accordingly
|
||
|
|
||
|
if (prb->iCapture == (int) (prb->cBands - 1))
|
||
|
// last guy in list, nothing to move
|
||
|
return;
|
||
|
|
||
|
prbbNext = prbb + 1;
|
||
|
|
||
|
if (prbbNext->fStyle & (RBBS_BREAK | RBBS_FIXEDSIZE))
|
||
|
// nobody else on this line or next guy isn't sizable -- see ya'
|
||
|
return;
|
||
|
|
||
|
// toggle prbb between maximized and restored
|
||
|
if (prbbNext->cx == prbbNext->cxMin)
|
||
|
{
|
||
|
// prbb currently maximized -- toggle to restored
|
||
|
if (!prbb->cxRestored || (prbb->cx < prbb->cxRestored))
|
||
|
// not yet maximized or restored size is bigger than current size
|
||
|
x = prbb->x + prbb->cxMin;
|
||
|
else
|
||
|
x = prbb->x + prbb->cxRestored;
|
||
|
|
||
|
if (fBandBorders)
|
||
|
x += g_cxEdge;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// prbb currently not maximized -- save restored size and maximize
|
||
|
prbb->cxRestored = prbb->cx;
|
||
|
x = prbbNext->x + prbbNext->cx - prbbNext->cxMin;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
prbbNext = prbb--;
|
||
|
|
||
|
// toggle prbbNext between maximized and restored
|
||
|
if (prbb->cx == prbb->cxMin)
|
||
|
{
|
||
|
// prbbNext currently maximized -- toggle to restored
|
||
|
x = prbbNext->x + prbbNext->cx;
|
||
|
if (!prbbNext->cxRestored || (prbbNext->cx < prbbNext->cxRestored))
|
||
|
// not yet maximized or restored size is bigger than current size
|
||
|
x -= prbbNext->cxMin;
|
||
|
else
|
||
|
x -= prbbNext->cxRestored;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// prbbNext currently not maximized -- save restored size and maximize
|
||
|
prbbNext->cxRestored = prbbNext->cx;
|
||
|
x = prbb->x + prbb->cxMin;
|
||
|
|
||
|
if (fBandBorders)
|
||
|
x += g_cxEdge;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetRect(&rc, prbb->x, prbb->y, prbb->x + prbb->cx, prbb->y + prbb->cy);
|
||
|
rc.left = prbb->x + prbb->cx;
|
||
|
|
||
|
xRight = prbbNext->x + prbbNext->cx;
|
||
|
prbbNext->x = x;
|
||
|
prbbNext->cx = xRight - x;
|
||
|
prbb->cx = x - prbb->x;
|
||
|
|
||
|
if (rc.left > x)
|
||
|
{
|
||
|
rc.right = rc.left;
|
||
|
rc.left = x;
|
||
|
}
|
||
|
else
|
||
|
rc.right = x;
|
||
|
|
||
|
rc.right += prbbNext->cxMin;
|
||
|
if (fBandBorders)
|
||
|
{
|
||
|
// acount for etch line in preceding band that will need to move
|
||
|
prbb->cx -= g_cxEdge;
|
||
|
rc.left -= g_cxEdge;
|
||
|
rc.bottom += g_cyEdge / 2;
|
||
|
}
|
||
|
if (prb->ci.style & CCS_VERT)
|
||
|
{
|
||
|
UINT uiTemp;
|
||
|
uiTemp = rc.left; rc.left = rc.top; rc.top = uiTemp;
|
||
|
uiTemp = rc.bottom; rc.bottom = rc.right; rc.right = uiTemp;
|
||
|
}
|
||
|
InvalidateRect(prb->ci.hwnd, &rc, TRUE);
|
||
|
RBResizeChildren(prb, prbb, prbbNext);
|
||
|
UpdateWindow(prb->ci.hwnd);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// RBSetCursor
|
||
|
|
||
|
// sets the cursor to either the move cursor or the arrow cursor, depending
|
||
|
// on whether or not the cursor is on a band's caption
|
||
|
|
||
|
|
||
|
void NEAR PASCAL RBSetCursor(PRB prb, int x, int y)
|
||
|
{
|
||
|
int iBand;
|
||
|
RBHITTESTINFO rbht;
|
||
|
|
||
|
rbht.pt.x = x;
|
||
|
rbht.pt.y = y;
|
||
|
iBand = RBHitTest(prb, &rbht);
|
||
|
|
||
|
if (rbht.flags == RBHT_GRABBER)
|
||
|
{
|
||
|
SetCursor(LoadCursor(NULL, (prb->ci.style & CCS_VERT) ? IDC_SIZENS : IDC_SIZEWE));
|
||
|
return;
|
||
|
}
|
||
|
else if ((rbht.flags == RBHT_CAPTION) && RBCanBandMove(prb, prb->rbbList + iBand))
|
||
|
{
|
||
|
SetCursor(LoadCursor(HINST_THISDLL, MAKEINTRESOURCE(IDC_HAND)));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBDragBandVert
|
||
|
|
||
|
// checks for sufficient vertical drag movement and, if so, vertically
|
||
|
// rearranges bands on rebar. Returns TRUE if any rearranging was performed,
|
||
|
// FALSE otherwise.
|
||
|
|
||
|
|
||
|
BOOL FAR PASCAL RBDragBandVert(PRB prb, int x, int y)
|
||
|
{
|
||
|
PRBB prbb = prb->rbbList + prb->iCapture;
|
||
|
PRBB prbbLast = prb->rbbList + prb->cBands;
|
||
|
PRBB prbbWalk;
|
||
|
|
||
|
if (y <= (prbb->y - (prbb->cy / 2)))
|
||
|
{
|
||
|
// try to move up one line
|
||
|
if (prbb->y)
|
||
|
{
|
||
|
// can only move up if it's not in the top row
|
||
|
|
||
|
// walk back 'til we find a break (or autobreak) -- we KNOW we're
|
||
|
// going to find a band with this style 'cause we're not on the
|
||
|
// first row
|
||
|
prbbWalk = prbb;
|
||
|
while (prbbWalk->x)
|
||
|
prbbWalk--;
|
||
|
|
||
|
// bands will be reordered if this rebar is not a fixed order rebar
|
||
|
if (!(prb->ci.style & RBS_FIXEDORDER))
|
||
|
{
|
||
|
if (prbb == prbbWalk)
|
||
|
prbb->fStyle &= ~RBBS_BREAK;
|
||
|
|
||
|
prbbWalk--;
|
||
|
// walk back to find correct horizontal position for band
|
||
|
while (prbbWalk->x && ((prbbWalk->x + ((prbbWalk->cxMin * 2) / 3)) > x))
|
||
|
prbbWalk--;
|
||
|
prbbWalk++;
|
||
|
|
||
|
if (prbbWalk->fStyle & RBBS_BREAK)
|
||
|
{
|
||
|
prbb->fStyle |= RBBS_BREAK;
|
||
|
prbbWalk->fStyle &= ~RBBS_BREAK;
|
||
|
}
|
||
|
|
||
|
// rearrange bands
|
||
|
RBMoveBand(prb, prb->iCapture,
|
||
|
((WORD) prbbWalk - (WORD) prb->rbbList) / sizeof(RBB));
|
||
|
return(TRUE);
|
||
|
}
|
||
|
else if (prbbWalk->fStyle & RBBS_BREAK)
|
||
|
{
|
||
|
// explicit break (i.e. not an autobreak) -- move break to next
|
||
|
// band
|
||
|
prbbWalk->fStyle &= ~RBBS_BREAK;
|
||
|
if (prbb->fStyle & RBBS_DRAGBREAK)
|
||
|
prbb->fStyle &= ~RBBS_DRAGBREAK;
|
||
|
else if (prbb < (prbbLast - 1))
|
||
|
{
|
||
|
if (!((prbb + 1)->fStyle & RBBS_FIXEDSIZE) &&
|
||
|
!((prbb + 1)->fStyle & RBBS_BREAK))
|
||
|
{
|
||
|
(prbb + 1)->fStyle |= RBBS_BREAK;
|
||
|
if (prb->ci.style & RBS_FIXEDORDER)
|
||
|
prbb->fStyle |= RBBS_DRAGBREAK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (y >= (prbb->y + (prbb->cy * 3 / 2)))
|
||
|
{
|
||
|
prbbWalk = prbb;
|
||
|
|
||
|
// can only move down if it's not already on it's own line
|
||
|
if (!prbb->x)
|
||
|
{
|
||
|
// first band on line -- we can do something about this if the
|
||
|
// rebar isn't fixed order
|
||
|
if (!(prb->ci.style & RBS_FIXEDORDER))
|
||
|
{
|
||
|
BOOL fFound = FALSE;
|
||
|
|
||
|
while (++prbbWalk < prbbLast)
|
||
|
{
|
||
|
if (!prbbWalk->x)
|
||
|
break;
|
||
|
|
||
|
if (!(prbbWalk->fStyle & RBBS_FIXEDSIZE))
|
||
|
fFound = TRUE;
|
||
|
}
|
||
|
|
||
|
if (fFound)
|
||
|
{
|
||
|
// this band has a non-fixedsize band after it on the same
|
||
|
// row; so it can be moved to next row.
|
||
|
|
||
|
if (prbb->y)
|
||
|
{
|
||
|
(prbb + 1)->fStyle |= RBBS_BREAK;
|
||
|
prbb->fStyle &= ~RBBS_BREAK;
|
||
|
}
|
||
|
goto MoveDown;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!(prb->ci.style & RBS_FIXEDORDER))
|
||
|
{
|
||
|
while (++prbbWalk < prbbLast)
|
||
|
{
|
||
|
if (!prbbWalk->x)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (prbb != (prbbWalk - 1))
|
||
|
{
|
||
|
MoveDown:
|
||
|
if (prbbWalk == prbbLast)
|
||
|
prbb->fStyle |= RBBS_BREAK;
|
||
|
else
|
||
|
{
|
||
|
if (x > 0)
|
||
|
{
|
||
|
prbbWalk++; // skip first band on next row
|
||
|
|
||
|
// walk forward to find correct horizontal position
|
||
|
// for band
|
||
|
while ((prbbWalk < prbbLast) && prbbWalk->x &&
|
||
|
(prbbWalk->x + ((prbbWalk->cxMin * 2) / 3) < x))
|
||
|
prbbWalk++;
|
||
|
}
|
||
|
|
||
|
if ((prbbWalk < prbbLast) && (!prbbWalk->x))
|
||
|
{
|
||
|
prbb->fStyle |= RBBS_BREAK;
|
||
|
prbbWalk->fStyle &= ~RBBS_BREAK;
|
||
|
prbb->fStyle &= ~RBBS_DRAGBREAK; //???
|
||
|
}
|
||
|
}
|
||
|
prbbWalk--;
|
||
|
|
||
|
RBMoveBand(prb, prb->iCapture,
|
||
|
((WORD) prbbWalk - (WORD) prb->rbbList) / sizeof(RBB));
|
||
|
return(TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
prbb->fStyle |= RBBS_BREAK;
|
||
|
|
||
|
if (prb->ci.style & RBS_FIXEDORDER)
|
||
|
{
|
||
|
if (prbb->fStyle & RBBS_DRAGBREAK)
|
||
|
{
|
||
|
if (prb->iCapture < (int) (prb->cBands - 1))
|
||
|
{
|
||
|
if (!((prbb + 1)->fStyle & RBBS_FIXEDSIZE))
|
||
|
{
|
||
|
(prbb + 1)->fStyle &= ~RBBS_BREAK;
|
||
|
prbb->fStyle &= ~RBBS_DRAGBREAK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
prbb->fStyle |= RBBS_DRAGBREAK;
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
}
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBDragSize
|
||
|
|
||
|
// adjust the captured band's starting location to the given location and
|
||
|
// redraw
|
||
|
|
||
|
|
||
|
BOOL RBDragSize(PRB prb, int xLeft)
|
||
|
{
|
||
|
RECT rc;
|
||
|
PRBB prbb = prb->rbbList + prb->iCapture;
|
||
|
PRBB prbbPrev = prbb - 1;
|
||
|
int xRight;
|
||
|
BOOL fBandBorders = (BOOL)(prb->ci.style & RBS_BANDBORDERS);
|
||
|
BOOL fRight;
|
||
|
|
||
|
if (prbb->x == xLeft)
|
||
|
return(FALSE);
|
||
|
|
||
|
// band has moved within valid range -- adjust band sizes and redraw
|
||
|
// window
|
||
|
fRight = (prbb->x < xLeft);
|
||
|
|
||
|
SetRect(&rc, prbb->x, prbb->y, prbb->x + prbb->cxMin, prbb->y + prbb->cy);
|
||
|
xRight = prbb->x + prbb->cx;
|
||
|
prbb->x = xLeft;
|
||
|
prbb->cx = xRight - xLeft;
|
||
|
prbb->cxRequest = prbb->cx;
|
||
|
|
||
|
if (fRight)
|
||
|
{
|
||
|
//moving right
|
||
|
prbbPrev->cx = prbb->x - prbbPrev->x;
|
||
|
if (fBandBorders)
|
||
|
{
|
||
|
prbbPrev->cx -= g_cxEdge;
|
||
|
rc.left -= g_cxEdge;
|
||
|
}
|
||
|
prbbPrev->cxRequest = prbbPrev->cx;
|
||
|
|
||
|
//check for compacting of following bands
|
||
|
|
||
|
while (prbb->cx < prbb->cxMin)
|
||
|
{
|
||
|
prbb->cx = prbb->cxMin;
|
||
|
prbb->cxRequest = prbb->cx;
|
||
|
xLeft += prbb->cxMin;
|
||
|
if (fBandBorders)
|
||
|
xLeft += g_cxEdge;
|
||
|
prbb++;
|
||
|
xRight = prbb->x + prbb->cx;
|
||
|
prbb->x = xLeft;
|
||
|
prbb->cx = xRight - xLeft;
|
||
|
prbb->cxRequest = prbb->cx;
|
||
|
}
|
||
|
rc.right = xLeft + prbb->cxMin;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//moving left
|
||
|
|
||
|
//check for compacting of preceding bands
|
||
|
CompactPrevious:
|
||
|
if (fBandBorders)
|
||
|
xLeft -= g_cxEdge;
|
||
|
prbbPrev->cx = xLeft - prbbPrev->x;
|
||
|
prbbPrev->cxRequest = prbbPrev->cx;
|
||
|
if (prbbPrev->cx < prbbPrev->cxMin)
|
||
|
{
|
||
|
prbbPrev->x = xLeft - prbbPrev->cxMin;
|
||
|
prbbPrev->cx = prbbPrev->cxMin;
|
||
|
prbbPrev->cxRequest = prbbPrev->cx;
|
||
|
xLeft = prbbPrev->x;
|
||
|
prbbPrev--;
|
||
|
goto CompactPrevious;
|
||
|
}
|
||
|
rc.left = xLeft;
|
||
|
}
|
||
|
|
||
|
if (fBandBorders)
|
||
|
rc.bottom += g_cyEdge / 2;
|
||
|
|
||
|
RBResizeChildren(prb, NULL, NULL);
|
||
|
if (prb->ci.style & CCS_VERT)
|
||
|
{
|
||
|
// for vertical oriented rebar, reverse x & y (using xLeft as swap var)
|
||
|
xLeft = rc.left; rc.left = rc.top; rc.top = xLeft;
|
||
|
xLeft = rc.bottom; rc.bottom = rc.right; rc.right = xLeft;
|
||
|
}
|
||
|
InvalidateRect(prb->ci.hwnd, &rc, TRUE);
|
||
|
UpdateWindow(prb->ci.hwnd);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBDragBand
|
||
|
|
||
|
// resizes the currently tracked band based on the user's mouse movement as
|
||
|
// indicated in the given point (x, y)
|
||
|
|
||
|
|
||
|
void FAR PASCAL RBDragBand(PRB prb, int x, int y)
|
||
|
{
|
||
|
PRBB prbb;
|
||
|
PRBB prbbLast = prb->rbbList + prb->cBands;
|
||
|
int xLeft;
|
||
|
BOOL fBandBorders = (BOOL)(prb->ci.style & RBS_BANDBORDERS);
|
||
|
|
||
|
if (prb->ci.style & CCS_VERT)
|
||
|
{
|
||
|
// for vertical oriented rebar, reverse x & y (using xLeft as swap var)
|
||
|
xLeft = x;
|
||
|
x = y;
|
||
|
y = xLeft;
|
||
|
}
|
||
|
|
||
|
if (!prb->fFullOnDrag)
|
||
|
{
|
||
|
// don't begin dragging until mouse is moved outside of an edge-thick
|
||
|
// tolerance border
|
||
|
if ((y < (prb->ptCapture.y - g_cyEdge)) || (y > (prb->ptCapture.y + g_cyEdge)) ||
|
||
|
(x < (prb->ptCapture.x - g_cxEdge)) || (x > (prb->ptCapture.x + g_cxEdge)))
|
||
|
prb->fFullOnDrag = TRUE;
|
||
|
else
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (RBDragBandVert(prb, x, y))
|
||
|
// there were vertical changes -- resize the rebar
|
||
|
RBResize(prb, FALSE);
|
||
|
|
||
|
// don't set prbb until now since above RBResize could've changed iCapture
|
||
|
prbb = prb->rbbList + prb->iCapture;
|
||
|
|
||
|
xLeft = prb->xStart + (x - prb->ptCapture.x);
|
||
|
|
||
|
if (!prbb->x)
|
||
|
{
|
||
|
// first band in row
|
||
|
|
||
|
// for fixed order rebars, can't move first band in row
|
||
|
if (!(prb->ci.style & RBS_FIXEDORDER))
|
||
|
{
|
||
|
PRBB prbbNext = prbb + 1;
|
||
|
|
||
|
if ((prbbNext < prbbLast) && prbbNext->x &&
|
||
|
!(prbbNext->fStyle & RBBS_FIXEDSIZE) &&
|
||
|
(x > (prbbNext->x + ((prbbNext->cxMin * 2) / 3))))
|
||
|
{
|
||
|
// next band is a non-fixedsize band on same row and there's
|
||
|
// been sufficient drag motion -- switch the order of these
|
||
|
// two bands
|
||
|
if (prb->iCapture > 0)
|
||
|
{
|
||
|
// we're not on the first row -- move the break style from
|
||
|
// the captured band to the next band
|
||
|
prbb->fStyle &= ~RBBS_BREAK;
|
||
|
prbbNext->fStyle |= RBBS_BREAK;
|
||
|
}
|
||
|
RBMoveBand(prb, prb->iCapture, prb->iCapture + 1);
|
||
|
RBResize(prb, FALSE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// now we can assume there is a previous band since prbb->x is nonzero
|
||
|
int xLimit;
|
||
|
PRBB prbbWalk;
|
||
|
|
||
|
// perform bounds checking
|
||
|
|
||
|
// calc minimum
|
||
|
prbbWalk = prbb;
|
||
|
xLimit = 0;
|
||
|
while (prbbWalk->x)
|
||
|
{
|
||
|
prbbWalk--;
|
||
|
xLimit += prbbWalk->cxMin;
|
||
|
if (fBandBorders)
|
||
|
xLimit += g_cxEdge;
|
||
|
}
|
||
|
|
||
|
if (xLeft < xLimit)
|
||
|
{
|
||
|
xLeft = xLimit;
|
||
|
|
||
|
if (!(prb->ci.style & RBS_FIXEDORDER))
|
||
|
{
|
||
|
// for non-fixed order rebars, move this band forward on row
|
||
|
prbbWalk = prbb;
|
||
|
|
||
|
// walk preceding bands in row to first band that can handle
|
||
|
// new position of dragged band
|
||
|
while (prbbWalk->x &&
|
||
|
(x < (xLimit - (((prbbWalk - 1)->cxMin * 2) / 3))))
|
||
|
{
|
||
|
prbbWalk--;
|
||
|
xLimit -= prbbWalk->cxMin;
|
||
|
if (fBandBorders)
|
||
|
xLimit -= g_cxEdge;
|
||
|
}
|
||
|
|
||
|
if (prbbWalk < prbb)
|
||
|
{
|
||
|
// this band can be moved in front of at least one band
|
||
|
if (prbbWalk->fStyle & RBBS_BREAK)
|
||
|
{
|
||
|
// we're moving dragged band to beginning of row;
|
||
|
// transfer break style from
|
||
|
prbbWalk->fStyle &= ~RBBS_BREAK;
|
||
|
prbb->fStyle |= RBBS_BREAK;
|
||
|
}
|
||
|
RBMoveBand(prb, prb->iCapture,
|
||
|
((WORD) prbbWalk - (WORD) prb->rbbList) / sizeof(RBB));
|
||
|
RBResize(prb, FALSE);
|
||
|
xLeft = xLimit;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// calc maximum
|
||
|
prbbWalk = prbb;
|
||
|
|
||
|
xLimit = 0;
|
||
|
while ((prbbWalk < prbbLast) && prbbWalk->x )
|
||
|
{
|
||
|
if (fBandBorders && (prbbWalk != prbb))
|
||
|
xLimit += g_cxEdge;
|
||
|
xLimit += prbbWalk->cxMin;
|
||
|
prbbWalk++;
|
||
|
}
|
||
|
prbbWalk--;
|
||
|
xLimit = prbbWalk->x + prbbWalk->cx - xLimit;
|
||
|
|
||
|
if (xLeft > xLimit)
|
||
|
{
|
||
|
xLeft = xLimit;
|
||
|
|
||
|
if (!(prb->ci.style & RBS_FIXEDORDER))
|
||
|
{
|
||
|
// for non-fixed order rebars, move this band later on row
|
||
|
prbbWalk = prbb + 1;
|
||
|
|
||
|
x -= prbb->cxMin;
|
||
|
if (fBandBorders)
|
||
|
x -= g_cxEdge;
|
||
|
|
||
|
// walk following bands in row to first band that can handle
|
||
|
// new position of dragged band
|
||
|
while ((prbbWalk < prbbLast) && prbbWalk->x &&
|
||
|
!(prbbWalk->fStyle & RBBS_FIXEDSIZE) &&
|
||
|
(x > (xLimit + ((prbbWalk->cxMin * 2) / 3))))
|
||
|
{
|
||
|
if (fBandBorders)
|
||
|
xLimit += g_cxEdge;
|
||
|
xLimit += prbbWalk->cxMin;
|
||
|
prbbWalk++;
|
||
|
}
|
||
|
prbbWalk--;
|
||
|
|
||
|
if (prbbWalk > prbb)
|
||
|
{
|
||
|
RBMoveBand(prb, prb->iCapture,
|
||
|
((WORD) prbbWalk - (WORD) prb->rbbList) / sizeof(RBB));
|
||
|
RBResize(prb, FALSE);
|
||
|
xLeft = xLimit;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
RBDragSize(prb, xLeft);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBDestroy
|
||
|
|
||
|
// frees all memory allocated by rebar, including rebar structure
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBDestroy(PRB prb)
|
||
|
{
|
||
|
UINT c = prb->cBands;
|
||
|
while (c--)
|
||
|
RBDeleteBand(prb, c);
|
||
|
|
||
|
if (prb->hpal)
|
||
|
DeleteObject(prb->hpal);
|
||
|
|
||
|
if (prb->hFont)
|
||
|
DeleteObject(prb->hFont);
|
||
|
|
||
|
if ((prb->ci.style & RBS_TOOLTIPS) && IsWindow(prb->hwndToolTips))
|
||
|
{
|
||
|
DestroyWindow (prb->hwndToolTips);
|
||
|
prb->hwndToolTips = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
// don't destroy the himl 'cause it's given to us by app
|
||
|
|
||
|
SetWindowInt(prb->ci.hwnd, 0, 0);
|
||
|
LocalFree((HLOCAL) prb);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// RBInitPaletteHack
|
||
|
|
||
|
// this is a hack to use the halftone palette until we have a way of asking
|
||
|
// the client what palette they are using
|
||
|
|
||
|
|
||
|
BOOL NEAR PASCAL RBInitPaletteHack(PRB prb)
|
||
|
{
|
||
|
HDC hdc = CreateCompatibleDC(NULL);
|
||
|
if (!hdc)
|
||
|
return(FALSE);
|
||
|
if (GetDeviceCaps(hdc, BITSPIXEL) <= 8)
|
||
|
prb->hpal = CreateHalftonePalette(hdc); // this is a hack
|
||
|
DeleteDC(hdc);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
LRESULT CALLBACK ReBarWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
PRB prb = (PRB) GetWindowInt(hwnd, 0);
|
||
|
int iBand;
|
||
|
|
||
|
switch (wMsg)
|
||
|
{
|
||
|
case WM_NCCREATE:
|
||
|
#define lpcs ((LPCREATESTRUCT) lParam)
|
||
|
InitGlobalColors();
|
||
|
|
||
|
if (!(prb = (PRB) LocalAlloc(LPTR, sizeof(RB))))
|
||
|
return(0L);
|
||
|
|
||
|
SetWindowInt(hwnd, 0, (int) prb);
|
||
|
|
||
|
prb->iCapture = -1;
|
||
|
|
||
|
// note, zero init memory from above
|
||
|
CIInitialize(&prb->ci, hwnd, lpcs);
|
||
|
|
||
|
RBInitPaletteHack(prb);
|
||
|
|
||
|
if (!(prb->ci.style & (CCS_TOP | CCS_NOMOVEY | CCS_BOTTOM)))
|
||
|
{
|
||
|
prb->ci.style |= CCS_TOP;
|
||
|
SetWindowLong(hwnd, GWL_STYLE, prb->ci.style);
|
||
|
}
|
||
|
|
||
|
if (prb->ci.style & RBS_TOOLTIPS)
|
||
|
{
|
||
|
TOOLINFO ti;
|
||
|
// don't bother setting the rect because we'll do it below
|
||
|
// in FlushToolTipsMgr;
|
||
|
ti.cbSize = sizeof(ti);
|
||
|
ti.uFlags = TTF_IDISHWND;
|
||
|
ti.hwnd = hwnd;
|
||
|
ti.uId = (UINT)hwnd;
|
||
|
ti.lpszText = 0;
|
||
|
|
||
|
prb->hwndToolTips = CreateWindow(c_szSToolTipsClass, NULL,
|
||
|
WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||
|
hwnd, NULL, lpcs->hInstance, NULL);
|
||
|
|
||
|
SendMessage(prb->hwndToolTips, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO) &ti);
|
||
|
}
|
||
|
|
||
|
RBSetFont(prb, 0);
|
||
|
|
||
|
if (lpcs->lpCreateParams)
|
||
|
RBSetBarInfo(prb, (LPREBARINFO) (lpcs->lpCreateParams));
|
||
|
#undef lpcs
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
RBDestroy(prb);
|
||
|
SetWindowInt(hwnd, 0, 0);
|
||
|
break;
|
||
|
|
||
|
case WM_NCHITTEST:
|
||
|
return HTCLIENT;
|
||
|
|
||
|
case WM_NCCALCSIZE:
|
||
|
if (prb && (prb->ci.style & WS_BORDER))
|
||
|
{
|
||
|
InflateRect((LPRECT) lParam, -g_cxEdge, -g_cyEdge);
|
||
|
break;
|
||
|
}
|
||
|
goto CallDWP;
|
||
|
|
||
|
case WM_NCPAINT:
|
||
|
if (prb && (prb->ci.style & WS_BORDER))
|
||
|
{
|
||
|
RECT rc;
|
||
|
HDC hdc;
|
||
|
HWND hwndParent = GetParent(hwnd);
|
||
|
|
||
|
GetWindowRect(hwnd, &rc);
|
||
|
MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rc, 2);
|
||
|
hdc = GetWindowDC(hwnd);
|
||
|
DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT);
|
||
|
ReleaseDC(hwnd, hdc);
|
||
|
break;
|
||
|
}
|
||
|
goto CallDWP;
|
||
|
|
||
|
case WM_PAINT:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
case WM_PRINTCLIENT:
|
||
|
RBPaint(prb, (HDC)wParam);
|
||
|
break;
|
||
|
|
||
|
case WM_ERASEBKGND:
|
||
|
if (RBEraseBkgnd(prb, (HDC) wParam, -1))
|
||
|
return(TRUE);
|
||
|
goto CallDWP;
|
||
|
|
||
|
case WM_SYSCOLORCHANGE:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
if (prb->hpal)
|
||
|
DeleteObject(prb->hpal);
|
||
|
|
||
|
RBInitPaletteHack(prb);
|
||
|
|
||
|
if (prb->hwndToolTips)
|
||
|
SendMessage(prb->hwndToolTips, wMsg, wParam, lParam);
|
||
|
|
||
|
ReInitGlobalColors();
|
||
|
break;
|
||
|
|
||
|
case WM_SIZE:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
RBResize(prb, FALSE);
|
||
|
break;
|
||
|
|
||
|
case WM_GETFONT:
|
||
|
return((LRESULT) (prb ? prb->hFont : NULL));
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
case WM_DRAWITEM:
|
||
|
case WM_MEASUREITEM:
|
||
|
case WM_VKEYTOITEM:
|
||
|
case WM_CHARTOITEM:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
SendMessage(prb->ci.hwndParent, wMsg, wParam, lParam);
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONDOWN:
|
||
|
if (prb)
|
||
|
{
|
||
|
RBHITTESTINFO rbht;
|
||
|
|
||
|
rbht.pt.x = GET_X_LPARAM(lParam);
|
||
|
rbht.pt.y = GET_Y_LPARAM(lParam);
|
||
|
|
||
|
RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
|
||
|
|
||
|
iBand = RBHitTest(prb, &rbht);
|
||
|
|
||
|
if ((iBand != -1) && (rbht.flags != RBHT_CLIENT) && RBCanBandMove(prb, prb->rbbList + iBand))
|
||
|
{
|
||
|
prb->iCapture = iBand;
|
||
|
prb->ptCapture.x = (prb->ci.style & CCS_VERT) ? rbht.pt.y : rbht.pt.x;
|
||
|
prb->ptCapture.y = (prb->ci.style & CCS_VERT) ? rbht.pt.x : rbht.pt.y;
|
||
|
prb->xStart = prb->rbbList[iBand].x;
|
||
|
SetCapture(hwnd);
|
||
|
prb->fFullOnDrag = FALSE;
|
||
|
//SendItemNotify(prb, iBand, RBN_BEGINDRAG);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_SETCURSOR:
|
||
|
if (prb)
|
||
|
{
|
||
|
// Give the parent first crack, if it sets the cursor then
|
||
|
// leave it at that. Otherwise if the cursor is over our
|
||
|
// window then set it to what we want it to be.
|
||
|
if (!DefWindowProc(hwnd, wMsg, wParam, lParam) &&
|
||
|
(hwnd == (HWND)wParam))
|
||
|
{
|
||
|
POINT pt;
|
||
|
lParam = GetMessagePos();
|
||
|
pt.x = ((prb->ci.style & CCS_VERT) ? GET_Y_LPARAM(lParam) : GET_X_LPARAM(lParam));
|
||
|
pt.y = ((prb->ci.style & CCS_VERT) ? GET_X_LPARAM(lParam) : GET_Y_LPARAM(lParam));
|
||
|
MapWindowPoints(NULL, prb->ci.hwnd, &pt, 1);
|
||
|
RBSetCursor(prb, pt.x, pt.y);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_MOUSEMOVE:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
|
||
|
|
||
|
if (prb->iCapture != -1)
|
||
|
{
|
||
|
// captured band -- mouse is down
|
||
|
if (hwnd != GetCapture())
|
||
|
{
|
||
|
//SendItemNotify(prb, ?, RBN_ENDDRAG);
|
||
|
prb->iCapture = -1;
|
||
|
}
|
||
|
else
|
||
|
RBDragBand(prb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||
|
}
|
||
|
// Don't set the cursor here. It is unecessary and will mess up our
|
||
|
// cursor processing code in the WM_SETCURSOR handler.
|
||
|
// else
|
||
|
// RBSetCursor(prb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONUP:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
|
||
|
|
||
|
if (prb->iCapture != -1)
|
||
|
{
|
||
|
ReleaseCapture();
|
||
|
// if there was no significant mouse motion, treat as a click
|
||
|
if (!prb->fFullOnDrag)
|
||
|
RBToggleBand(prb);
|
||
|
|
||
|
prb->rbbList[prb->iCapture].fStyle &= ~RBBS_DRAGBREAK;
|
||
|
prb->iCapture = -1;
|
||
|
}
|
||
|
break;
|
||
|
#ifdef IEWIN31_25
|
||
|
// Simulate WM_CONTEXTMENU commands on windows 3.1
|
||
|
case WM_RBUTTONUP:
|
||
|
{
|
||
|
POINT pt;
|
||
|
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
pt.x = LOWORD(lParam);
|
||
|
pt.y = HIWORD(lParam);
|
||
|
ClientToScreen(hwnd, &pt);
|
||
|
SendMessage(prb->ci.hwndParent, WM_CONTEXTMENU, (WPARAM)hwnd, MAKELONG(pt.x, pt.y));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Pass on context menus from children on to our parent
|
||
|
case WM_CONTEXTMENU:
|
||
|
{
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
SendMessage(prb->ci.hwndParent, WM_CONTEXTMENU, wParam, lParam);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
case WM_WININICHANGE:
|
||
|
InitGlobalMetrics(wParam);
|
||
|
RBSetFont(prb, wParam);
|
||
|
|
||
|
if (prb->hwndToolTips)
|
||
|
SendMessage(prb->hwndToolTips, wMsg, wParam, lParam);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_NOTIFYFORMAT:
|
||
|
return(CIHandleNotifyFormat(&prb->ci, lParam));
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
// We are just going to pass this on to the real parent
|
||
|
// Note that -1 is used as the hwndFrom. This prevents SendNotifyEx
|
||
|
// from updating the NMHDR structure.
|
||
|
return(SendNotifyEx(prb->ci.hwndParent, (HWND) -1,
|
||
|
((LPNMHDR) lParam)->code, (LPNMHDR) lParam, prb->ci.bUnicode));
|
||
|
|
||
|
case WM_STYLECHANGED:
|
||
|
#define lpss ((LPSTYLESTRUCT) lParam)
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
if (wParam == GWL_STYLE)
|
||
|
{
|
||
|
prb->ci.style = ((LPSTYLESTRUCT)lParam)->styleNew;
|
||
|
// update to reflect style change
|
||
|
#ifndef WINNT
|
||
|
DebugMsg(DM_TRACE, TEXT("rebar window style changed %x"), prb->ci.style);
|
||
|
#endif
|
||
|
if ((lpss->styleOld & CCS_VERT) != (lpss->styleNew & CCS_VERT))
|
||
|
{
|
||
|
UINT i;
|
||
|
for (i = 0; i < prb->cBands; i++)
|
||
|
RBBCalcMinWidth(prb,(PRBB)&(prb->rbbList[i]));
|
||
|
RBResize(prb, TRUE);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
case RB_INSERTBANDA:
|
||
|
{
|
||
|
LPWSTR lpStrings;
|
||
|
UINT uiCount;
|
||
|
LPSTR lpAnsiString;
|
||
|
int iResult;
|
||
|
|
||
|
if (!prb )
|
||
|
break;
|
||
|
|
||
|
if (!(((LPREBARBANDINFOA)lParam)->fMask & RBBIM_TEXT))
|
||
|
return RBInsertBand(prb, (UINT) wParam, (LPREBARBANDINFO) lParam);
|
||
|
|
||
|
lpAnsiString = ((LPREBARBANDINFOA)lParam)->lpText;
|
||
|
uiCount = lstrlenA(lpAnsiString)+1;
|
||
|
|
||
|
lpStrings = GlobalAlloc (GPTR, uiCount * sizeof(TCHAR));
|
||
|
|
||
|
if (!lpStrings)
|
||
|
return -1;
|
||
|
|
||
|
MultiByteToWideChar(CP_ACP, 0, (LPCSTR) ((LPREBARBANDINFOA)lParam)->lpText, uiCount,
|
||
|
lpStrings, uiCount);
|
||
|
|
||
|
((LPREBARBANDINFOA)lParam)->lpText = (LPSTR)lpStrings;
|
||
|
iResult = RBInsertBand(prb, (UINT) wParam, (LPREBARBANDINFO) lParam);
|
||
|
((LPREBARBANDINFOA)lParam)->lpText = lpAnsiString;
|
||
|
|
||
|
GlobalFree(lpStrings);
|
||
|
|
||
|
return iResult;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
case RB_INSERTBAND:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
return(RBInsertBand(prb, (UINT) wParam, (LPREBARBANDINFO) lParam));
|
||
|
|
||
|
case RB_DELETEBAND:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
return(RBDeleteBand(prb, (UINT) wParam));
|
||
|
|
||
|
case RB_GETBANDINFO:
|
||
|
return(RBGetBandInfo(prb, (UINT) wParam, (LPREBARBANDINFO) lParam));
|
||
|
|
||
|
case RB_GETROWCOUNT:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
return(RBGetRowCount(prb));
|
||
|
|
||
|
case RB_GETROWHEIGHT:
|
||
|
if (prb && (wParam < prb->cBands))
|
||
|
{
|
||
|
UINT i, j;
|
||
|
i = (UINT) wParam;
|
||
|
j = i;
|
||
|
|
||
|
// move back to start of line
|
||
|
while (prb->rbbList[i].x)
|
||
|
i--;
|
||
|
|
||
|
while ((j + 1) < prb->cBands)
|
||
|
{
|
||
|
if (!prb->rbbList[j].x)
|
||
|
break;
|
||
|
|
||
|
j++;
|
||
|
}
|
||
|
|
||
|
return(RBGetLineHeight(prb, i, j));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case RB_GETBANDCOUNT:
|
||
|
if (!prb)
|
||
|
break;
|
||
|
|
||
|
return(prb->cBands);
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
case RB_SETBANDINFOA: {
|
||
|
LPWSTR lpStrings;
|
||
|
UINT uiCount;
|
||
|
LPSTR lpAnsiString = ((LPREBARBANDINFOA)lParam)->lpText;
|
||
|
int iResult;
|
||
|
|
||
|
if (!prb )
|
||
|
break;
|
||
|
|
||
|
if (!(((LPREBARBANDINFOA)lParam)->fMask & RBBIM_TEXT))
|
||
|
return RBSetBandInfo(prb, (UINT) wParam, (LPREBARBANDINFO) lParam);
|
||
|
|
||
|
uiCount = lstrlenA(lpAnsiString)+1;
|
||
|
|
||
|
lpStrings = GlobalAlloc (GPTR, uiCount * sizeof(TCHAR));
|
||
|
|
||
|
if (!lpStrings)
|
||
|
return -1;
|
||
|
|
||
|
MultiByteToWideChar(CP_ACP, 0, (LPCSTR) ((LPREBARBANDINFOA)lParam)->lpText, uiCount,
|
||
|
lpStrings, uiCount);
|
||
|
|
||
|
((LPREBARBANDINFOA)lParam)->lpText = (LPSTR)lpStrings;
|
||
|
iResult = RBSetBandInfo(prb, (UINT) wParam, (LPREBARBANDINFO) lParam);
|
||
|
((LPREBARBANDINFOA)lParam)->lpText = lpAnsiString;
|
||
|
|
||
|
GlobalFree(lpStrings);
|
||
|
|
||
|
return iResult;
|
||
|
}
|
||
|
|
||
|
#endif // UNICODE
|
||
|
case RB_SETBANDINFO:
|
||
|
return(RBSetBandInfo(prb, (UINT) wParam, (LPREBARBANDINFO) lParam));
|
||
|
|
||
|
case RB_GETBARINFO:
|
||
|
return(RBGetBarInfo(prb, (LPREBARINFO) lParam));
|
||
|
|
||
|
case RB_SETBARINFO:
|
||
|
return(RBSetBarInfo(prb, (LPREBARINFO) lParam));
|
||
|
|
||
|
case RB_SETPARENT:
|
||
|
if (prb)
|
||
|
{
|
||
|
HWND hwndOld = prb->ci.hwndParent;
|
||
|
prb->ci.hwndParent = (HWND) wParam;
|
||
|
return((LRESULT)(UINT) hwndOld);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case RB_GETRECT:
|
||
|
if (prb && (wParam < prb->cBands))
|
||
|
{
|
||
|
PRBB prbb = prb->rbbList + wParam;
|
||
|
LPRECT lprc = (LPRECT) lParam;
|
||
|
|
||
|
lprc->left = prbb->x;
|
||
|
lprc->top = prbb->y;
|
||
|
lprc->right = prbb->x + prbb->cx;
|
||
|
lprc->bottom = prbb->y + prbb->cy;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case RB_HITTEST:
|
||
|
if (!prb)
|
||
|
{
|
||
|
LPRBHITTESTINFO prbht = (LPRBHITTESTINFO) lParam;
|
||
|
prbht->flags = RBHT_NOWHERE;
|
||
|
prbht->iBand = -1;
|
||
|
return(-1);
|
||
|
}
|
||
|
return(RBHitTest(prb, (LPRBHITTESTINFO) lParam));
|
||
|
|
||
|
default:
|
||
|
CallDWP:
|
||
|
return(DefWindowProc(hwnd, wMsg, wParam, lParam));
|
||
|
}
|
||
|
|
||
|
return(0L);
|
||
|
}
|