📄 tab.c
字号:
/* shift the item to the left side of the clientRect */
curr->rect.right -= curr->rect.left;
curr->rect.left = 0;
TRACE("r=%d, cl=%d, cl.r=%d, iCount=%d, iRow=%d, uNumRows=%d, remTab=%d, tabPerRow=%d\n",
curr->rect.right, curItemLeftPos, clientRect.right,
iCount, iRow, infoPtr->uNumRows, remTab, tabPerRow);
/* if we have reached the maximum number of tabs on this row */
/* move to the next row, reset our current item left position and */
/* the count of items on this row */
if (lStyle & TCS_VERTICAL) {
/* Vert: Add the remaining tabs in the *last* remainder rows */
if (iCount >= ((iRow>=(INT)infoPtr->uNumRows - remTab)?tabPerRow + 1:tabPerRow)) {
iRow++;
curItemLeftPos = 0;
iCount = 0;
}
} else {
/* Horz: Add the remaining tabs in the *first* remainder rows */
if (iCount >= ((iRow<remTab)?tabPerRow + 1:tabPerRow)) {
iRow++;
curItemLeftPos = 0;
iCount = 0;
}
}
/* shift the item to the right to place it as the next item in this row */
curr->rect.left += curItemLeftPos;
curr->rect.right += curItemLeftPos;
curr->rect.top = iRow;
if (lStyle & TCS_BUTTONS)
{
curItemLeftPos = curr->rect.right + 1;
if (lStyle & TCS_FLATBUTTONS)
curItemLeftPos += FLAT_BTN_SPACINGX;
}
else
curItemLeftPos = curr->rect.right;
TRACE("arranging <%s>, l,r=%d,%d, row=%d\n",
debugstr_w(curr->pszText), curr->rect.left,
curr->rect.right, curr->rect.top);
}
/*
* Justify the rows
*/
{
INT widthDiff, iIndexStart=0, iIndexEnd=0;
INT remainder;
INT iCount=0;
while(iIndexStart < infoPtr->uNumItem)
{
TAB_ITEM *start = TAB_GetItem(infoPtr, iIndexStart);
/*
* find the index of the row
*/
/* find the first item on the next row */
for (iIndexEnd=iIndexStart;
(iIndexEnd < infoPtr->uNumItem) &&
(TAB_GetItem(infoPtr, iIndexEnd)->rect.top ==
start->rect.top) ;
iIndexEnd++)
/* intentionally blank */;
/*
* we need to justify these tabs so they fill the whole given
* client area
*
*/
/* find the amount of space remaining on this row */
widthDiff = clientRect.right - (2 * SELECTED_TAB_OFFSET) -
TAB_GetItem(infoPtr, iIndexEnd - 1)->rect.right;
/* iCount is the number of tab items on this row */
iCount = iIndexEnd - iIndexStart;
if (iCount > 1)
{
remainder = widthDiff % iCount;
widthDiff = widthDiff / iCount;
/* add widthDiff/iCount, or extra space/items on row, to each item on this row */
for (iIndex=iIndexStart, iCount=0; iIndex < iIndexEnd; iIndex++, iCount++)
{
TAB_ITEM *item = TAB_GetItem(infoPtr, iIndex);
item->rect.left += iCount * widthDiff;
item->rect.right += (iCount + 1) * widthDiff;
TRACE("adjusting 1 <%s>, l,r=%d,%d\n",
debugstr_w(item->pszText),
item->rect.left, item->rect.right);
}
TAB_GetItem(infoPtr, iIndex - 1)->rect.right += remainder;
}
else /* we have only one item on this row, make it take up the entire row */
{
start->rect.left = clientRect.left;
start->rect.right = clientRect.right - 4;
TRACE("adjusting 2 <%s>, l,r=%d,%d\n",
debugstr_w(start->pszText),
start->rect.left, start->rect.right);
}
iIndexStart = iIndexEnd;
}
}
}
/* if TCS_VERTICAL rotate the tabs so they are along the side of the clientRect */
if(lStyle & TCS_VERTICAL)
{
RECT rcOriginal;
for(iIndex = 0; iIndex < infoPtr->uNumItem; iIndex++)
{
rcItem = &TAB_GetItem(infoPtr, iIndex)->rect;
rcOriginal = *rcItem;
/* this is rotating the items by 90 degrees clockwise around the center of the control */
rcItem->top = (rcOriginal.left - clientRect.left);
rcItem->bottom = rcItem->top + (rcOriginal.right - rcOriginal.left);
rcItem->left = rcOriginal.top;
rcItem->right = rcOriginal.bottom;
}
}
TAB_EnsureSelectionVisible(infoPtr);
TAB_RecalcHotTrack(infoPtr, NULL, NULL, NULL);
/* Cleanup */
SelectObject (hdc, hOldFont);
ReleaseDC (infoPtr->hwnd, hdc);
}
static void
TAB_EraseTabInterior
(
TAB_INFO* infoPtr,
HDC hdc,
INT iItem,
RECT* drawRect
)
{
LONG lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
HBRUSH hbr = CreateSolidBrush (comctl32_color.clrBtnFace);
BOOL deleteBrush = TRUE;
RECT rTemp = *drawRect;
InflateRect(&rTemp, -2, -2);
if (lStyle & TCS_BUTTONS)
{
if (iItem == infoPtr->iSelected)
{
/* Background color */
if (!(lStyle & TCS_OWNERDRAWFIXED))
{
DeleteObject(hbr);
hbr = GetSysColorBrush(COLOR_SCROLLBAR);
SetTextColor(hdc, comctl32_color.clr3dFace);
SetBkColor(hdc, comctl32_color.clr3dHilight);
/* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
* we better use 0x55aa bitmap brush to make scrollbar's background
* look different from the window background.
*/
if (comctl32_color.clr3dHilight == comctl32_color.clrWindow)
hbr = COMCTL32_hPattern55AABrush;
deleteBrush = FALSE;
}
FillRect(hdc, &rTemp, hbr);
}
else /* ! selected */
{
if (lStyle & TCS_FLATBUTTONS)
{
FillRect(hdc, drawRect, hbr);
if (iItem == infoPtr->iHotTracked)
DrawEdge(hdc, drawRect, EDGE_RAISED, BF_SOFT|BF_RECT);
}
else
FillRect(hdc, &rTemp, hbr);
}
}
else /* !TCS_BUTTONS */
{
if (!GetWindowTheme (infoPtr->hwnd))
FillRect(hdc, &rTemp, hbr);
}
/* Cleanup */
if (deleteBrush) DeleteObject(hbr);
}
/******************************************************************************
* TAB_DrawItemInterior
*
* This method is used to draw the interior (text and icon) of a single tab
* into the tab control.
*/
static void
TAB_DrawItemInterior
(
TAB_INFO* infoPtr,
HDC hdc,
INT iItem,
RECT* drawRect
)
{
LONG lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
RECT localRect;
HPEN htextPen;
HPEN holdPen;
INT oldBkMode;
HFONT hOldFont;
/* if (drawRect == NULL) */
{
BOOL isVisible;
RECT itemRect;
RECT selectedRect;
/*
* Get the rectangle for the item.
*/
isVisible = TAB_InternalGetItemRect(infoPtr, iItem, &itemRect, &selectedRect);
if (!isVisible)
return;
/*
* Make sure drawRect points to something valid; simplifies code.
*/
drawRect = &localRect;
/*
* This logic copied from the part of TAB_DrawItem which draws
* the tab background. It's important to keep it in sync. I
* would have liked to avoid code duplication, but couldn't figure
* out how without making spaghetti of TAB_DrawItem.
*/
if (iItem == infoPtr->iSelected)
*drawRect = selectedRect;
else
*drawRect = itemRect;
if (lStyle & TCS_BUTTONS)
{
if (iItem == infoPtr->iSelected)
{
drawRect->left += 4;
drawRect->top += 4;
drawRect->right -= 4;
drawRect->bottom -= 1;
}
else
{
drawRect->left += 2;
drawRect->top += 2;
drawRect->right -= 2;
drawRect->bottom -= 2;
}
}
else
{
if ((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM))
{
if (iItem != infoPtr->iSelected)
{
drawRect->left += 2;
drawRect->top += 2;
drawRect->bottom -= 2;
}
}
else if (lStyle & TCS_VERTICAL)
{
if (iItem == infoPtr->iSelected)
{
drawRect->right += 1;
}
else
{
drawRect->top += 2;
drawRect->right -= 2;
drawRect->bottom -= 2;
}
}
else if (lStyle & TCS_BOTTOM)
{
if (iItem == infoPtr->iSelected)
{
drawRect->top -= 2;
}
else
{
InflateRect(drawRect, -2, -2);
drawRect->bottom += 2;
}
}
else
{
if (iItem == infoPtr->iSelected)
{
drawRect->bottom += 3;
}
else
{
drawRect->bottom -= 2;
InflateRect(drawRect, -2, 0);
}
}
}
}
TRACE("drawRect=(%d,%d)-(%d,%d)\n",
drawRect->left, drawRect->top, drawRect->right, drawRect->bottom);
/* Clear interior */
TAB_EraseTabInterior (infoPtr, hdc, iItem, drawRect);
/* Draw the focus rectangle */
if (!(lStyle & TCS_FOCUSNEVER) &&
(GetFocus() == infoPtr->hwnd) &&
(iItem == infoPtr->uFocus) )
{
RECT rFocus = *drawRect;
InflateRect(&rFocus, -3, -3);
if (lStyle & TCS_BOTTOM && !(lStyle & TCS_VERTICAL))
rFocus.top -= 3;
if (lStyle & TCS_BUTTONS)
{
rFocus.left -= 3;
rFocus.top -= 3;
}
DrawFocusRect(hdc, &rFocus);
}
/*
* Text pen
*/
htextPen = CreatePen( PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT) );
holdPen = SelectObject(hdc, htextPen);
hOldFont = SelectObject(hdc, infoPtr->hFont);
/*
* Setup for text output
*/
oldBkMode = SetBkMode(hdc, TRANSPARENT);
if (!GetWindowTheme (infoPtr->hwnd) || (lStyle & TCS_BUTTONS))
SetTextColor(hdc, (((lStyle & TCS_HOTTRACK) && (iItem == infoPtr->iHotTracked)
&& !(lStyle & TCS_FLATBUTTONS))
| (TAB_GetItem(infoPtr, iItem)->dwState & TCIS_HIGHLIGHTED)) ?
comctl32_color.clrHighlight : comctl32_color.clrBtnText);
/*
* if owner draw, tell the owner to draw
*/
if ((lStyle & TCS_OWNERDRAWFIXED) && GetParent(infoPtr->hwnd))
{
DRAWITEMSTRUCT dis;
UINT id;
drawRect->top += 2;
drawRect->right -= 1;
if ( iItem == infoPtr->iSelected )
{
drawRect->right -= 1;
drawRect->left += 1;
}
/*
* get the control id
*/
id = (UINT)GetWindowLongPtrW( infoPtr->hwnd, GWLP_ID );
/*
* put together the DRAWITEMSTRUCT
*/
dis.CtlType = ODT_TAB;
dis.CtlID = id;
dis.itemID = iItem;
dis.itemAction = ODA_DRAWENTIRE;
dis.itemState = 0;
if ( iItem == infoPtr->iSelected )
dis.itemState |= ODS_SELECTED;
if (infoPtr->uFocus == iItem)
dis.itemState |= ODS_FOCUS;
dis.hwndItem = infoPtr->hwnd;
dis.hDC = hdc;
CopyRect(&dis.rcItem,drawRect);
dis.itemData = (ULONG_PTR)TAB_GetItem(infoPtr, iItem)->extra;
/*
* send the draw message
*/
SendMessageW( infoPtr->hwndNotify, WM_DRAWITEM, (WPARAM)id, (LPARAM)&dis );
}
else
{
TAB_ITEM *item = TAB_GetItem(infoPtr, iItem);
RECT rcTemp;
RECT rcImage;
/* used to center the icon and text in the tab */
RECT rcText;
INT center_offset_h, center_offset_v;
/* set rcImage to drawRect, we will use top & left in our ImageList_Draw call */
rcImage = *drawRect;
rcTemp = *drawRect;
rcText.left = rcText.top = rcText.right = rcText.bottom = 0;
/* get the rectangle that the text fits in */
if (item->pszText)
{
DrawTextW(hdc, item->pszText, -1, &rcText, DT_CALCRECT);
}
/*
* If not owner draw, then do the drawing ourselves.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -