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

📄 tab.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
 * the window rectangle given the requested display rectangle.
 */
static LRESULT TAB_AdjustRect(
  TAB_INFO *infoPtr,
  WPARAM fLarger,
  LPRECT prc)
{
    DWORD lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
    LONG *iRightBottom, *iLeftTop;

    TRACE ("hwnd=%p fLarger=%d (%d,%d)-(%d,%d)\n", infoPtr->hwnd, fLarger, prc->left, prc->top, prc->right, prc->bottom);

    if(lStyle & TCS_VERTICAL)
    {
	iRightBottom = &(prc->right);
	iLeftTop     = &(prc->left);
    }
    else
    {
	iRightBottom = &(prc->bottom);
	iLeftTop     = &(prc->top);
    }

    if (fLarger) /* Go from display rectangle */
    {
        /* Add the height of the tabs. */
	if (lStyle & TCS_BOTTOM)
	    *iRightBottom += infoPtr->tabHeight * infoPtr->uNumRows;
	else
	    *iLeftTop -= infoPtr->tabHeight * infoPtr->uNumRows +
			 ((lStyle & TCS_BUTTONS)? 3 * (infoPtr->uNumRows - 1) : 0);

	/* Inflate the rectangle for the padding */
	InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY); 

	/* Inflate for the border */
	InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEY);
    }
    else /* Go from window rectangle. */
    {
	/* Deflate the rectangle for the border */
	InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEY);

	/* Deflate the rectangle for the padding */
	InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY);

	/* Remove the height of the tabs. */
	if (lStyle & TCS_BOTTOM)
	    *iRightBottom -= infoPtr->tabHeight * infoPtr->uNumRows;
	else
	    *iLeftTop += (infoPtr->tabHeight) * infoPtr->uNumRows +
			 ((lStyle & TCS_BUTTONS)? 3 * (infoPtr->uNumRows - 1) : 0);
    }

  return 0;
}

/******************************************************************************
 * TAB_OnHScroll
 *
 * This method will handle the notification from the scroll control and
 * perform the scrolling operation on the tab control.
 */
static LRESULT TAB_OnHScroll(
  TAB_INFO *infoPtr,
  int     nScrollCode,
  int     nPos,
  HWND    hwndScroll)
{
  if(nScrollCode == SB_THUMBPOSITION && nPos != infoPtr->leftmostVisible)
  {
     if(nPos < infoPtr->leftmostVisible)
        infoPtr->leftmostVisible--;
     else
        infoPtr->leftmostVisible++;

     TAB_RecalcHotTrack(infoPtr, NULL, NULL, NULL);
     TAB_InvalidateTabArea(infoPtr);
     SendMessageW(infoPtr->hwndUpDown, UDM_SETPOS, 0,
                   MAKELONG(infoPtr->leftmostVisible, 0));
   }

   return 0;
}

/******************************************************************************
 * TAB_SetupScrolling
 *
 * This method will check the current scrolling state and make sure the
 * scrolling control is displayed (or not).
 */
static void TAB_SetupScrolling(
  HWND        hwnd,
  TAB_INFO*   infoPtr,
  const RECT* clientRect)
{
  static const WCHAR msctls_updown32W[] = { 'm','s','c','t','l','s','_','u','p','d','o','w','n','3','2',0 };
  static const WCHAR emptyW[] = { 0 };
  INT maxRange = 0;
  DWORD lStyle = GetWindowLongW(hwnd, GWL_STYLE);

  if (infoPtr->needsScrolling)
  {
    RECT controlPos;
    INT vsize, tabwidth;

    /*
     * Calculate the position of the scroll control.
     */
    if(lStyle & TCS_VERTICAL)
    {
      controlPos.right = clientRect->right;
      controlPos.left  = controlPos.right - 2 * GetSystemMetrics(SM_CXHSCROLL);

      if (lStyle & TCS_BOTTOM)
      {
        controlPos.top    = clientRect->bottom - infoPtr->tabHeight;
        controlPos.bottom = controlPos.top + GetSystemMetrics(SM_CYHSCROLL);
      }
      else
      {
        controlPos.bottom = clientRect->top + infoPtr->tabHeight;
        controlPos.top    = controlPos.bottom - GetSystemMetrics(SM_CYHSCROLL);
      }
    }
    else
    {
      controlPos.right = clientRect->right;
      controlPos.left  = controlPos.right - 2 * GetSystemMetrics(SM_CXHSCROLL);

      if (lStyle & TCS_BOTTOM)
      {
        controlPos.top    = clientRect->bottom - infoPtr->tabHeight;
        controlPos.bottom = controlPos.top + GetSystemMetrics(SM_CYHSCROLL);
      }
      else
      {
        controlPos.bottom = clientRect->top + infoPtr->tabHeight;
        controlPos.top    = controlPos.bottom - GetSystemMetrics(SM_CYHSCROLL);
      }
    }

    /*
     * If we don't have a scroll control yet, we want to create one.
     * If we have one, we want to make sure it's positioned properly.
     */
    if (infoPtr->hwndUpDown==0)
    {
      infoPtr->hwndUpDown = CreateWindowW(msctls_updown32W, emptyW,
					  WS_VISIBLE | WS_CHILD | UDS_HORZ,
					  controlPos.left, controlPos.top,
					  controlPos.right - controlPos.left,
					  controlPos.bottom - controlPos.top,
					  hwnd, NULL, NULL, NULL);
    }
    else
    {
      SetWindowPos(infoPtr->hwndUpDown,
		   NULL,
		   controlPos.left, controlPos.top,
		   controlPos.right - controlPos.left,
		   controlPos.bottom - controlPos.top,
		   SWP_SHOWWINDOW | SWP_NOZORDER);
    }

    /* Now calculate upper limit of the updown control range.
     * We do this by calculating how many tabs will be offscreen when the
     * last tab is visible.
     */
    if(infoPtr->uNumItem)
    {
       vsize = clientRect->right - (controlPos.right - controlPos.left + 1);
       maxRange = infoPtr->uNumItem;
       tabwidth = TAB_GetItem(infoPtr, infoPtr->uNumItem - 1)->rect.right;

       for(; maxRange > 0; maxRange--)
       {
          if(tabwidth - TAB_GetItem(infoPtr,maxRange - 1)->rect.left > vsize)
             break;
       }

       if(maxRange == infoPtr->uNumItem)
          maxRange--;
    }
  }
  else
  {
    /* If we once had a scroll control... hide it */
    if (infoPtr->hwndUpDown!=0)
      ShowWindow(infoPtr->hwndUpDown, SW_HIDE);
  }
  if (infoPtr->hwndUpDown)
     SendMessageW(infoPtr->hwndUpDown, UDM_SETRANGE32, 0, maxRange);
}

/******************************************************************************
 * TAB_SetItemBounds
 *
 * This method will calculate the position rectangles of all the items in the
 * control. The rectangle calculated starts at 0 for the first item in the
 * list and ignores scrolling and selection.
 * It also uses the current font to determine the height of the tab row and
 * it checks if all the tabs fit in the client area of the window. If they
 * don't, a scrolling control is added.
 */
static void TAB_SetItemBounds (TAB_INFO *infoPtr)
{
  LONG        lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
  TEXTMETRICW fontMetrics;
  UINT        curItem;
  INT         curItemLeftPos;
  INT         curItemRowCount;
  HFONT       hFont, hOldFont;
  HDC         hdc;
  RECT        clientRect;
  INT         iTemp;
  RECT*       rcItem;
  INT         iIndex;
  INT         icon_width = 0;

  /*
   * We need to get text information so we need a DC and we need to select
   * a font.
   */
  hdc = GetDC(infoPtr->hwnd);

  hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
  hOldFont = SelectObject (hdc, hFont);

  /*
   * We will base the rectangle calculations on the client rectangle
   * of the control.
   */
  GetClientRect(infoPtr->hwnd, &clientRect);

  /* if TCS_VERTICAL then swap the height and width so this code places the
     tabs along the top of the rectangle and we can just rotate them after
     rather than duplicate all of the below code */
  if(lStyle & TCS_VERTICAL)
  {
     iTemp = clientRect.bottom;
     clientRect.bottom = clientRect.right;
     clientRect.right = iTemp;
  }

  /* Now use hPadding and vPadding */
  infoPtr->uHItemPadding = infoPtr->uHItemPadding_s;
  infoPtr->uVItemPadding = infoPtr->uVItemPadding_s;
  
  /* The leftmost item will be "0" aligned */
  curItemLeftPos = 0;
  curItemRowCount = infoPtr->uNumItem ? 1 : 0;

  if (!(infoPtr->fHeightSet))
  {
    int item_height;
    int icon_height = 0;

    /* Use the current font to determine the height of a tab. */
    GetTextMetricsW(hdc, &fontMetrics);

    /* Get the icon height */
    if (infoPtr->himl)
      ImageList_GetIconSize(infoPtr->himl, 0, &icon_height);

    /* Take the highest between font or icon */
    if (fontMetrics.tmHeight > icon_height)
      item_height = fontMetrics.tmHeight + 2;
    else
      item_height = icon_height;

    /*
     * Make sure there is enough space for the letters + icon + growing the
     * selected item + extra space for the selected item.
     */
    infoPtr->tabHeight = item_height + 
	                 ((lStyle & TCS_BUTTONS) ? 2 : 1) *
                          infoPtr->uVItemPadding;

    TRACE("tabH=%d, tmH=%d, iconh=%d\n",
	  infoPtr->tabHeight, fontMetrics.tmHeight, icon_height);
  }

  TRACE("client right=%d\n", clientRect.right);

  /* Get the icon width */
  if (infoPtr->himl)
  {
    ImageList_GetIconSize(infoPtr->himl, &icon_width, 0);

    if (lStyle & TCS_FIXEDWIDTH)
      icon_width += 4;
    else
      /* Add padding if icon is present */
      icon_width += infoPtr->uHItemPadding;
  }

  for (curItem = 0; curItem < infoPtr->uNumItem; curItem++)
  {
    TAB_ITEM *curr = TAB_GetItem(infoPtr, curItem);
	
    /* Set the leftmost position of the tab. */
    curr->rect.left = curItemLeftPos;

    if (lStyle & TCS_FIXEDWIDTH)
    {
      curr->rect.right = curr->rect.left +
        max(infoPtr->tabWidth, icon_width);
    }
    else if (!curr->pszText)
    {
      /* If no text use minimum tab width including padding. */
      if (infoPtr->tabMinWidth < 0)
        curr->rect.right = curr->rect.left + GET_DEFAULT_MIN_TAB_WIDTH(infoPtr);
      else
      {
        curr->rect.right = curr->rect.left + infoPtr->tabMinWidth;

        /* Add extra padding if icon is present */
        if (infoPtr->himl && infoPtr->tabMinWidth > 0 && infoPtr->tabMinWidth < DEFAULT_MIN_TAB_WIDTH
            && infoPtr->uHItemPadding > 1)
          curr->rect.right += EXTRA_ICON_PADDING * (infoPtr->uHItemPadding-1);
      }
    }
    else
    {
      int tabwidth;
      SIZE size;
      /* Calculate how wide the tab is depending on the text it contains */
      GetTextExtentPoint32W(hdc, curr->pszText,
                            lstrlenW(curr->pszText), &size);

      tabwidth = size.cx + icon_width + 2 * infoPtr->uHItemPadding;

      if (infoPtr->tabMinWidth < 0)
        tabwidth = max(tabwidth, GET_DEFAULT_MIN_TAB_WIDTH(infoPtr));
      else
        tabwidth = max(tabwidth, infoPtr->tabMinWidth);

      curr->rect.right = curr->rect.left + tabwidth;
      TRACE("for <%s>, l,r=%d,%d\n",
	  debugstr_w(curr->pszText), curr->rect.left, curr->rect.right);
    }

    /*
     * Check if this is a multiline tab control and if so
     * check to see if we should wrap the tabs
     *
     * Wrap all these tabs. We will arrange them evenly later.
     *
     */

    if (((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) &&
        (curr->rect.right > 
	(clientRect.right - CONTROL_BORDER_SIZEX - DISPLAY_AREA_PADDINGX)))
    {
        curr->rect.right -= curr->rect.left;

	curr->rect.left = 0;
        curItemRowCount++;
	TRACE("wrapping <%s>, l,r=%d,%d\n", debugstr_w(curr->pszText),
	    curr->rect.left, curr->rect.right);
    }

    curr->rect.bottom = 0;
    curr->rect.top = curItemRowCount - 1;

    TRACE("Rect: T %i, L %i, B %i, R %i\n", curr->rect.top,
	  curr->rect.left, curr->rect.bottom, curr->rect.right);

    /*
     * The leftmost position of the next item is the rightmost position
     * of this one.
     */
    if (lStyle & TCS_BUTTONS)
    {
      curItemLeftPos = curr->rect.right + BUTTON_SPACINGX;
      if (lStyle & TCS_FLATBUTTONS)
        curItemLeftPos += FLAT_BTN_SPACINGX;
    }
    else
      curItemLeftPos = curr->rect.right;
  }

  if (!((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)))
  {
    /*
     * Check if we need a scrolling control.
     */
    infoPtr->needsScrolling = (curItemLeftPos + (2 * SELECTED_TAB_OFFSET) >
                               clientRect.right);

    /* Don't need scrolling, then update infoPtr->leftmostVisible */
    if(!infoPtr->needsScrolling)
      infoPtr->leftmostVisible = 0;
  }
  else
  {
    /*
     * No scrolling in Multiline or Vertical styles.
     */
    infoPtr->needsScrolling = FALSE;
    infoPtr->leftmostVisible = 0;
  }
  TAB_SetupScrolling(infoPtr->hwnd, infoPtr, &clientRect);

  /* Set the number of rows */
  infoPtr->uNumRows = curItemRowCount;

  /* Arrange all tabs evenly if style says so */
   if (!(lStyle & TCS_RAGGEDRIGHT) &&
       ((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) &&
       (infoPtr->uNumItem > 0) &&
       (infoPtr->uNumRows > 1))
   {
      INT tabPerRow,remTab,iRow;
      UINT iItm;
      INT iCount=0;

      /*
       * Ok windows tries to even out the rows. place the same
       * number of tabs in each row. So lets give that a shot
       */

      tabPerRow = infoPtr->uNumItem / (infoPtr->uNumRows);
      remTab = infoPtr->uNumItem % (infoPtr->uNumRows);

      for (iItm=0,iRow=0,iCount=0,curItemLeftPos=0;
           iItm<infoPtr->uNumItem;
           iItm++,iCount++)
      {
          /* normalize the current rect */
          TAB_ITEM *curr = TAB_GetItem(infoPtr, iItm);
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -