📄 rebar.c
字号:
}
}
else {
SetRect (&lpBand->rcChild,
lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
lpBand->rcBand.right, lpBand->rcBand.bottom);
}
/* flag if notify required and invalidate rectangle */
if (lpBand->fDraw & NTF_INVALIDATE) {
TRACE("invalidating (%d,%d)-(%d,%d)\n",
lpBand->rcBand.left,
lpBand->rcBand.top,
lpBand->rcBand.right + SEP_WIDTH,
lpBand->rcBand.bottom + SEP_WIDTH);
lpBand->fDraw &= ~NTF_INVALIDATE;
work = lpBand->rcBand;
work.right += SEP_WIDTH;
work.bottom += SEP_WIDTH;
InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
}
}
}
static VOID
REBAR_CalcVertBand (const REBAR_INFO *infoPtr, UINT rstart, UINT rend)
/* Function: this routine initializes all the rectangles in */
/* each band in a row to fit in the adjusted rcBand rect. */
/* *** Supports only Vertical bars. *** */
{
REBAR_BAND *lpBand;
UINT i, xoff;
RECT work;
for(i=rstart; i<rend; i++){
RECT rcBand;
lpBand = &infoPtr->bands[i];
if (HIDDENBAND(lpBand)) continue;
translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
/* set initial gripper rectangle */
SetRect (&lpBand->rcGripper, rcBand.left, rcBand.top, rcBand.right, rcBand.top);
/* calculate gripper rectangle */
if (lpBand->fStatus & HAS_GRIPPER) {
lpBand->fDraw |= DRAW_GRIPPER;
if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) {
/* vertical gripper */
lpBand->rcGripper.left += 3;
lpBand->rcGripper.right = lpBand->rcGripper.left + GRIPPER_WIDTH;
lpBand->rcGripper.top += REBAR_PRE_GRIPPER;
lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
/* initialize Caption image rectangle */
SetRect (&lpBand->rcCapImage, rcBand.left,
lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
rcBand.right,
lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
}
else {
/* horizontal gripper */
lpBand->rcGripper.left += 2;
lpBand->rcGripper.right -= 2;
lpBand->rcGripper.top += REBAR_PRE_GRIPPER;
lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_WIDTH;
/* initialize Caption image rectangle */
SetRect (&lpBand->rcCapImage, rcBand.left,
lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
rcBand.right,
lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
}
}
else { /* no gripper will be drawn */
xoff = 0;
if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
/* if no gripper but either image or text, then leave space */
xoff = REBAR_ALWAYS_SPACE;
/* initialize Caption image rectangle */
SetRect (&lpBand->rcCapImage,
rcBand.left, rcBand.top+xoff,
rcBand.right, rcBand.top+xoff);
}
/* image is visible */
if (lpBand->fStatus & HAS_IMAGE) {
lpBand->fDraw |= DRAW_IMAGE;
lpBand->rcCapImage.right = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;
/* set initial caption text rectangle */
SetRect (&lpBand->rcCapText,
rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
rcBand.right, rcBand.top+lpBand->cxHeader);
}
else {
/* set initial caption text rectangle */
SetRect (&lpBand->rcCapText,
rcBand.left, lpBand->rcCapImage.bottom,
rcBand.right, rcBand.top+lpBand->cxHeader);
}
/* text is visible */
if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
lpBand->fDraw |= DRAW_TEXT;
lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
lpBand->rcCapText.bottom);
}
/* set initial child window rectangle if there is a child */
if (lpBand->hwndChild != NULL) {
int cxBand = rcBand.right - rcBand.left;
xoff = (cxBand - lpBand->cyChild) / 2;
SetRect (&lpBand->rcChild,
rcBand.left + xoff, rcBand.top + lpBand->cxHeader,
rcBand.left + xoff + lpBand->cyChild, rcBand.bottom - REBAR_POST_CHILD);
}
else {
SetRect (&lpBand->rcChild,
rcBand.left, rcBand.top+lpBand->cxHeader,
rcBand.right, rcBand.bottom);
}
if (lpBand->fDraw & NTF_INVALIDATE) {
TRACE("invalidating (%d,%d)-(%d,%d)\n",
rcBand.left,
rcBand.top,
rcBand.right + SEP_WIDTH,
rcBand.bottom + SEP_WIDTH);
lpBand->fDraw &= ~NTF_INVALIDATE;
work = rcBand;
work.bottom += SEP_WIDTH;
work.right += SEP_WIDTH;
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. */
{
INT x, y, width, height;
INT xedge = 0, yedge = 0;
RECT rcSelf;
TRACE("new size [%d x %d]\n", infoPtr->calcSize.cx, infoPtr->calcSize.cy);
if (infoPtr->dwStyle & CCS_NORESIZE)
return;
if (infoPtr->dwStyle & WS_BORDER)
{
xedge = GetSystemMetrics(SM_CXEDGE);
yedge = GetSystemMetrics(SM_CYEDGE);
/* swap for CCS_VERT? */
}
/* compute rebar window rect in parent client coordinates */
GetWindowRect(infoPtr->hwndSelf, &rcSelf);
MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->hwndSelf), (LPPOINT)&rcSelf, 2);
translate_rect(infoPtr, &rcSelf, &rcSelf);
height = infoPtr->calcSize.cy + 2*yedge;
if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) {
RECT rcParent;
x = -xedge;
width = infoPtr->calcSize.cx + 2*xedge;
y = 0; /* quiet compiler warning */
switch ( infoPtr->dwStyle & CCS_LAYOUT_MASK) {
case 0: /* shouldn't happen - see NCCreate */
case CCS_TOP:
y = ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER) - yedge;
break;
case CCS_NOMOVEY:
y = rcSelf.top;
break;
case CCS_BOTTOM:
GetClientRect(GetParent(infoPtr->hwndSelf), &rcParent);
translate_rect(infoPtr, &rcParent, &rcParent);
y = rcParent.bottom - infoPtr->calcSize.cy - yedge;
break;
}
}
else {
x = rcSelf.left;
/* As on Windows if the CCS_NODIVIDER is not present the control will move
* 2 pixel down after every layout */
y = rcSelf.top + ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
width = rcSelf.right - rcSelf.left;
}
TRACE("hwnd %p, style=%08x, setting at (%d,%d) for (%d,%d)\n",
infoPtr->hwndSelf, infoPtr->dwStyle, x, y, width, height);
/* Set flag to ignore next WM_SIZE message and resize the window */
infoPtr->fStatus |= AUTO_RESIZE;
if ((infoPtr->dwStyle & CCS_VERT) == 0)
SetWindowPos(infoPtr->hwndSelf, 0, x, y, width, height, SWP_NOZORDER);
else
SetWindowPos(infoPtr->hwndSelf, 0, y, x, height, width, SWP_NOZORDER);
infoPtr->fStatus &= ~AUTO_RESIZE;
}
static VOID
REBAR_MoveChildWindows (const 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;
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;
translate_rect(infoPtr, &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);
/* native (from **1 above) does:
* UpdateWindow(rebar)
* REBAR_ForceResize
* RBN_HEIGHTCHANGE if necessary
* if ret from any EqualRect was 0
* Goto "BeginDeferWindowPos"
*/
}
static int next_band(const REBAR_INFO *infoPtr, int i)
{
int n;
for (n = i + 1; n < infoPtr->uNumBands; n++)
if (!HIDDENBAND(&infoPtr->bands[n]))
break;
return n;
}
static int prev_band(const REBAR_INFO *infoPtr, int i)
{
int n;
for (n = i - 1; n >= 0; n--)
if (!HIDDENBAND(&infoPtr->bands[n]))
break;
return n;
}
static int get_row_begin_for_band(const REBAR_INFO *infoPtr, INT iBand)
{
int iLastBand = iBand;
int iRow = infoPtr->bands[iBand].iRow;
while ((iBand = prev_band(infoPtr, iBand)) >= 0) {
if (infoPtr->bands[iBand].iRow != iRow)
break;
else
iLastBand = iBand;
}
return iLastBand;
}
static int get_row_end_for_band(const REBAR_INFO *infoPtr, INT iBand)
{
int iRow = infoPtr->bands[iBand].iRow;
while ((iBand = next_band(infoPtr, iBand)) < infoPtr->uNumBands)
if (infoPtr->bands[iBand].iRow != iRow)
break;
return iBand;
}
static void REBAR_SetRowRectsX(const REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand)
{
int xPos = 0, i;
for (i = iBeginBand; i < iEndBand; i = next_band(infoPtr, i))
{
REBAR_BAND *lpBand = &infoPtr->bands[i];
lpBand = &infoPtr->bands[i];
if (lpBand->rcBand.left != xPos || lpBand->rcBand.right != xPos + lpBand->cxEffective) {
lpBand->fDraw |= NTF_INVALIDATE;
TRACE("Setting rect %d to %d,%d\n", i, xPos, xPos + lpBand->cxEffective);
lpBand->rcBand.left = xPos;
lpBand->rcBand.right = xPos + lpBand->cxEffective;
}
xPos += lpBand->cxEffective + SEP_WIDTH;
}
}
/* The rationale of this function is probably as follows: if we have some space
* to distribute we want to add it to a band on the right. However we don't want
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -