⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rebar.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	  }
      }
      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 + -