📄 rebar.c
字号:
lpBand->fDraw &= ~NTF_INVALIDATE;
work = lpBand->rcBand;
if (lpBand->fDraw & DRAW_RIGHTSEP) work.bottom += SEP_WIDTH_SIZE;
if (lpBand->fDraw & DRAW_BOTTOMSEP) work.right += SEP_WIDTH_SIZE;
InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
}
}
}
static VOID
REBAR_ForceResize (REBAR_INFO *infoPtr)
/* Function: This changes the size of the REBAR window to that */
/* calculated by REBAR_Layout. */
{
RECT rc;
INT x, y, width, height;
INT xedge = GetSystemMetrics(SM_CXEDGE);
INT yedge = GetSystemMetrics(SM_CYEDGE);
GetClientRect (infoPtr->hwndSelf, &rc);
TRACE( " old [%d x %d], new [%d x %d], client [%d x %d]\n",
infoPtr->oldSize.cx, infoPtr->oldSize.cy,
infoPtr->calcSize.cx, infoPtr->calcSize.cy,
rc.right, rc.bottom);
/* If we need to shrink client, then skip size test */
if ((infoPtr->calcSize.cy >= rc.bottom) &&
(infoPtr->calcSize.cx >= rc.right)) {
/* if size did not change then skip process */
if ((infoPtr->oldSize.cx == infoPtr->calcSize.cx) &&
(infoPtr->oldSize.cy == infoPtr->calcSize.cy) &&
!(infoPtr->fStatus & RESIZE_ANYHOW))
{
TRACE("skipping reset\n");
return;
}
}
infoPtr->fStatus &= ~RESIZE_ANYHOW;
/* Set flag to ignore next WM_SIZE message */
infoPtr->fStatus |= AUTO_RESIZE;
width = 0;
height = 0;
x = 0;
y = 0;
if (infoPtr->dwStyle & WS_BORDER) {
width = 2 * xedge;
height = 2 * yedge;
}
if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) {
INT mode = infoPtr->dwStyle & (CCS_VERT | CCS_TOP | CCS_BOTTOM);
RECT rcPcl;
GetClientRect(GetParent(infoPtr->hwndSelf), &rcPcl);
switch (mode) {
case CCS_TOP:
/* _TOP sets width to parents width */
width += (rcPcl.right - rcPcl.left);
height += infoPtr->calcSize.cy;
x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
y += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
break;
case CCS_BOTTOM:
/* FIXME: wrong wrong wrong */
/* _BOTTOM sets width to parents width */
width += (rcPcl.right - rcPcl.left);
height += infoPtr->calcSize.cy;
x += -xedge;
y = rcPcl.bottom - height + 1;
break;
case CCS_LEFT:
/* _LEFT sets height to parents height */
width += infoPtr->calcSize.cx;
height += (rcPcl.bottom - rcPcl.top);
x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
x += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
break;
case CCS_RIGHT:
/* FIXME: wrong wrong wrong */
/* _RIGHT sets height to parents height */
width += infoPtr->calcSize.cx;
height += (rcPcl.bottom - rcPcl.top);
x = rcPcl.right - width + 1;
y = -yedge;
break;
default:
width += infoPtr->calcSize.cx;
height += infoPtr->calcSize.cy;
}
}
else {
width += infoPtr->calcSize.cx;
height += infoPtr->calcSize.cy;
x = infoPtr->origin.x;
y = infoPtr->origin.y;
}
TRACE("hwnd %p, style=%08x, setting at (%d,%d) for (%d,%d)\n",
infoPtr->hwndSelf, infoPtr->dwStyle,
x, y, width, height);
SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height,
SWP_NOZORDER);
infoPtr->fStatus &= ~AUTO_RESIZE;
}
static VOID
REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
{
static const WCHAR strComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
REBAR_BAND *lpBand;
WCHAR szClassName[40];
UINT i;
NMREBARCHILDSIZE rbcz;
NMHDR heightchange;
HDWP deferpos;
if (!(deferpos = BeginDeferWindowPos(infoPtr->uNumBands)))
ERR("BeginDeferWindowPos returned NULL\n");
for (i = start; i < endplus; i++) {
lpBand = &infoPtr->bands[i];
if (HIDDENBAND(lpBand)) continue;
if (lpBand->hwndChild) {
TRACE("hwndChild = %p\n", lpBand->hwndChild);
/* Always geterate the RBN_CHILDSIZE even it child
did not change */
rbcz.uBand = i;
rbcz.wID = lpBand->wID;
rbcz.rcChild = lpBand->rcChild;
rbcz.rcBand = lpBand->rcBand;
if (infoPtr->dwStyle & CCS_VERT)
rbcz.rcBand.top += lpBand->cxHeader;
else
rbcz.rcBand.left += lpBand->cxHeader;
REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
TRACE("Child rect changed by NOTIFY for band %u\n", i);
TRACE(" from (%d,%d)-(%d,%d) to (%d,%d)-(%d,%d)\n",
lpBand->rcChild.left, lpBand->rcChild.top,
lpBand->rcChild.right, lpBand->rcChild.bottom,
rbcz.rcChild.left, rbcz.rcChild.top,
rbcz.rcChild.right, rbcz.rcChild.bottom);
lpBand->rcChild = rbcz.rcChild; /* *** ??? */
}
/* native (IE4 in "Favorites" frame **1) does:
* SetRect (&rc, -1, -1, -1, -1)
* EqualRect (&rc,band->rc???)
* if ret==0
* CopyRect (band->rc????, &rc)
* set flag outside of loop
*/
GetClassNameW (lpBand->hwndChild, szClassName, sizeof(szClassName)/sizeof(szClassName[0]));
if (!lstrcmpW (szClassName, strComboBox) ||
!lstrcmpW (szClassName, WC_COMBOBOXEXW)) {
INT nEditHeight, yPos;
RECT rc;
/* special placement code for combo or comboex box */
/* get size of edit line */
GetWindowRect (lpBand->hwndChild, &rc);
nEditHeight = rc.bottom - rc.top;
yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
/* center combo box inside child area */
TRACE("moving child (Combo(Ex)) %p to (%d,%d) for (%d,%d)\n",
lpBand->hwndChild,
lpBand->rcChild.left, yPos,
lpBand->rcChild.right - lpBand->rcChild.left,
nEditHeight);
deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
lpBand->rcChild.left,
/*lpBand->rcChild.top*/ yPos,
lpBand->rcChild.right - lpBand->rcChild.left,
nEditHeight,
SWP_NOZORDER);
if (!deferpos)
ERR("DeferWindowPos returned NULL\n");
}
else {
TRACE("moving child (Other) %p to (%d,%d) for (%d,%d)\n",
lpBand->hwndChild,
lpBand->rcChild.left, lpBand->rcChild.top,
lpBand->rcChild.right - lpBand->rcChild.left,
lpBand->rcChild.bottom - lpBand->rcChild.top);
deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
lpBand->rcChild.left,
lpBand->rcChild.top,
lpBand->rcChild.right - lpBand->rcChild.left,
lpBand->rcChild.bottom - lpBand->rcChild.top,
SWP_NOZORDER);
if (!deferpos)
ERR("DeferWindowPos returned NULL\n");
}
}
}
if (!EndDeferWindowPos(deferpos))
ERR("EndDeferWindowPos returned NULL\n");
if (infoPtr->DoRedraw)
UpdateWindow (infoPtr->hwndSelf);
if (infoPtr->fStatus & NTF_HGHTCHG) {
infoPtr->fStatus &= ~NTF_HGHTCHG;
/*
* We need to force a resize here, because some applications
* try to get the rebar size during processing of the
* RBN_HEIGHTCHANGE notification.
*/
REBAR_ForceResize (infoPtr);
REBAR_Notify (&heightchange, infoPtr, RBN_HEIGHTCHANGE);
}
/* native (from **1 above) does:
* UpdateWindow(rebar)
* REBAR_ForceResize
* RBN_HEIGHTCHANGE if necessary
* if ret from any EqualRect was 0
* Goto "BeginDeferWindowPos"
*/
}
static VOID
REBAR_Layout (REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify, BOOL resetclient)
/* Function: This routine is resposible for laying out all */
/* the bands in a rebar. It assigns each band to a row and*/
/* determines when to start a new row. */
{
REBAR_BAND *lpBand, *prevBand;
RECT rcClient, rcAdj;
INT initx, inity, x, y, cx, cxsep, mmcy, mcy, clientcx, clientcy;
INT adjcx, adjcy, row, rightx, bottomy, origheight;
UINT i, j, rowstart, origrows, cntonrow;
BOOL dobreak;
if (!(infoPtr->fStatus & BAND_NEEDS_LAYOUT)) {
TRACE("no layout done. No band changed.\n");
REBAR_DumpBand (infoPtr);
return;
}
infoPtr->fStatus &= ~BAND_NEEDS_LAYOUT;
if (!infoPtr->DoRedraw) infoPtr->fStatus |= BAND_NEEDS_REDRAW;
GetClientRect (infoPtr->hwndSelf, &rcClient);
TRACE("Client is (%d,%d)-(%d,%d)\n",
rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
if (lpRect) {
rcAdj = *lpRect;
TRACE("adjustment rect is (%d,%d)-(%d,%d)\n",
rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
}
else {
CopyRect (&rcAdj, &rcClient);
}
clientcx = rcClient.right - rcClient.left;
clientcy = rcClient.bottom - rcClient.top;
adjcx = rcAdj.right - rcAdj.left;
adjcy = rcAdj.bottom - rcAdj.top;
if (resetclient) {
TRACE("window client rect will be set to adj rect\n");
clientcx = adjcx;
clientcy = adjcy;
}
if (!infoPtr->DoRedraw && (clientcx == 0) && (clientcy == 0)) {
ERR("no redraw and client is zero, skip layout\n");
infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
return;
}
/* save height of original control */
if (infoPtr->dwStyle & CCS_VERT)
origheight = infoPtr->calcSize.cx;
else
origheight = infoPtr->calcSize.cy;
origrows = infoPtr->uNumRows;
initx = 0;
inity = 0;
/* ******* Start Phase 1 - all bands on row at minimum size ******* */
TRACE("band loop constants, clientcx=%d, clientcy=%d, adjcx=%d, adjcy=%d\n",
clientcx, clientcy, adjcx, adjcy);
x = initx;
y = inity;
row = 0;
cx = 0;
mcy = 0;
rowstart = 0;
prevBand = NULL;
cntonrow = 0;
for (i = 0; i < infoPtr->uNumBands; i++) {
lpBand = &infoPtr->bands[i];
lpBand->fDraw = 0;
lpBand->iRow = row;
SetRectEmpty(&lpBand->rcChevron);
if (HIDDENBAND(lpBand)) continue;
lpBand->rcoldBand = lpBand->rcBand;
/* Set the offset of the child window */
if ((lpBand->fMask & RBBIM_CHILD) &&
!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
lpBand->offChild.cx = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 4 : 0);
}
lpBand->offChild.cy = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 2 : 0);
/* separator from previous band */
cxsep = (cntonrow == 0) ? 0 : SEP_WIDTH;
cx = lpBand->lcx;
/* In native, 0 as one of the coordinates means no limit */
if (infoPtr->dwStyle & CCS_VERT)
dobreak = (adjcy && (y + cx + cxsep > adjcy));
else
dobreak = (adjcx && (x + cx + cxsep > adjcx));
/* This is the check for whether we need to start a new row */
if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
( ((infoPtr->dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
for (j = rowstart; j < i; j++) {
REBAR_BAND *lpB;
lpB = &infoPtr->bands[j];
if (infoPtr->dwStyle & CCS_VERT) {
lpB->rcBand.right = lpB->rcBand.left + mcy;
}
else {
lpB->rcBand.bottom = lpB->rcBand.top + mcy;
}
}
TRACE("P1 Spliting to new row %d on band %u\n", row+1, i);
if (infoPtr->dwStyle & CCS_VERT) {
y = inity;
x += (mcy + SEP_WIDTH);
}
else {
x = initx;
y += (mcy + SEP_WIDTH);
}
mcy = 0;
cxsep = 0;
row++;
lpBand->iRow = row;
prevBand = NULL;
rowstart = i;
cntonrow = 0;
}
if (mcy < lpBand->lcy + REBARSPACE(lpBand))
mcy = lpBand->lcy + REBARSPACE(lpBand);
/* if boundary rect specified then limit mcy */
if (lpRect) {
if (infoPtr->dwStyle & CCS_VERT) {
if (adjcx && (x+mcy > adjcx)) {
mcy = adjcx - x;
TRACE("P1 row %u limiting mcy=%d, adjcx=%d, x=%d\n",
i, mcy, adjcx, x);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -