📄 tab.c
字号:
*
* Draw the icon.
*/
if (infoPtr->himl && (item->mask & TCIF_IMAGE))
{
INT cx;
INT cy;
ImageList_GetIconSize(infoPtr->himl, &cx, &cy);
if(lStyle & TCS_VERTICAL)
{
center_offset_h = ((drawRect->bottom - drawRect->top) - (cy + infoPtr->uHItemPadding + (rcText.right - rcText.left))) / 2;
center_offset_v = (drawRect->left + (drawRect->right - drawRect->left) - cx) / 2;
}
else
{
center_offset_h = ((drawRect->right - drawRect->left) - (cx + infoPtr->uHItemPadding + (rcText.right - rcText.left))) / 2;
center_offset_v = (drawRect->top + (drawRect->bottom - drawRect->top) - cy) / 2;
}
/* if an item is selected, the icon is shifted up instead of down */
if (iItem == infoPtr->iSelected)
center_offset_v -= infoPtr->uVItemPadding / 2;
else
center_offset_v += infoPtr->uVItemPadding / 2;
if (lStyle & TCS_FIXEDWIDTH && lStyle & (TCS_FORCELABELLEFT | TCS_FORCEICONLEFT))
center_offset_h = infoPtr->uHItemPadding;
if (center_offset_h < 2)
center_offset_h = 2;
if (center_offset_v < 0)
center_offset_v = 0;
TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%d,%d)-(%d,%d), textlen=%d\n",
debugstr_w(item->pszText), center_offset_h, center_offset_v,
drawRect->left, drawRect->top, drawRect->right, drawRect->bottom,
(rcText.right-rcText.left));
if((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM))
{
rcImage.top = drawRect->top + center_offset_h;
/* if tab is TCS_VERTICAL and TCS_BOTTOM, the text is drawn from the */
/* right side of the tab, but the image still uses the left as its x position */
/* this keeps the image always drawn off of the same side of the tab */
rcImage.left = drawRect->right - cx - center_offset_v;
drawRect->top += cy + infoPtr->uHItemPadding;
}
else if(lStyle & TCS_VERTICAL)
{
rcImage.top = drawRect->bottom - cy - center_offset_h;
rcImage.left = drawRect->left + center_offset_v;
drawRect->bottom -= cy + infoPtr->uHItemPadding;
}
else /* normal style, whether TCS_BOTTOM or not */
{
rcImage.left = drawRect->left + center_offset_h;
rcImage.top = drawRect->top + center_offset_v;
drawRect->left += cx + infoPtr->uHItemPadding;
}
TRACE("drawing image=%d, left=%d, top=%d\n",
item->iImage, rcImage.left, rcImage.top-1);
ImageList_Draw
(
infoPtr->himl,
item->iImage,
hdc,
rcImage.left,
rcImage.top,
ILD_NORMAL
);
}
/* Now position text */
if (lStyle & TCS_FIXEDWIDTH && lStyle & TCS_FORCELABELLEFT)
center_offset_h = infoPtr->uHItemPadding;
else
if(lStyle & TCS_VERTICAL)
center_offset_h = ((drawRect->bottom - drawRect->top) - (rcText.right - rcText.left)) / 2;
else
center_offset_h = ((drawRect->right - drawRect->left) - (rcText.right - rcText.left)) / 2;
if(lStyle & TCS_VERTICAL)
{
if(lStyle & TCS_BOTTOM)
drawRect->top+=center_offset_h;
else
drawRect->bottom-=center_offset_h;
center_offset_v = ((drawRect->right - drawRect->left) - (rcText.bottom - rcText.top)) / 2;
}
else
{
drawRect->left += center_offset_h;
center_offset_v = ((drawRect->bottom - drawRect->top) - (rcText.bottom - rcText.top)) / 2;
}
/* if an item is selected, the text is shifted up instead of down */
if (iItem == infoPtr->iSelected)
center_offset_v -= infoPtr->uVItemPadding / 2;
else
center_offset_v += infoPtr->uVItemPadding / 2;
if (center_offset_v < 0)
center_offset_v = 0;
if(lStyle & TCS_VERTICAL)
drawRect->left += center_offset_v;
else
drawRect->top += center_offset_v;
/* Draw the text */
if(lStyle & TCS_VERTICAL) /* if we are vertical rotate the text and each character */
{
static const WCHAR ArialW[] = { 'A','r','i','a','l',0 };
LOGFONTW logfont;
HFONT hFont = 0;
INT nEscapement = 900;
INT nOrientation = 900;
if(lStyle & TCS_BOTTOM)
{
nEscapement = -900;
nOrientation = -900;
}
/* to get a font with the escapement and orientation we are looking for, we need to */
/* call CreateFontIndirectA, which requires us to set the values of the logfont we pass in */
if (!GetObjectW((infoPtr->hFont) ?
infoPtr->hFont : GetStockObject(SYSTEM_FONT),
sizeof(LOGFONTW),&logfont))
{
INT iPointSize = 9;
lstrcpyW(logfont.lfFaceName, ArialW);
logfont.lfHeight = -MulDiv(iPointSize, GetDeviceCaps(hdc, LOGPIXELSY),
72);
logfont.lfWeight = FW_NORMAL;
logfont.lfItalic = 0;
logfont.lfUnderline = 0;
logfont.lfStrikeOut = 0;
}
logfont.lfEscapement = nEscapement;
logfont.lfOrientation = nOrientation;
hFont = CreateFontIndirectW(&logfont);
SelectObject(hdc, hFont);
if (item->pszText)
{
ExtTextOutW(hdc,
(lStyle & TCS_BOTTOM) ? drawRect->right : drawRect->left,
(!(lStyle & TCS_BOTTOM)) ? drawRect->bottom : drawRect->top,
ETO_CLIPPED,
drawRect,
item->pszText,
lstrlenW(item->pszText),
0);
}
DeleteObject(hFont);
}
else
{
TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%d,%d)-(%d,%d), textlen=%d\n",
debugstr_w(item->pszText), center_offset_h, center_offset_v,
drawRect->left, drawRect->top, drawRect->right, drawRect->bottom,
(rcText.right-rcText.left));
if (item->pszText)
{
DrawTextW
(
hdc,
item->pszText,
lstrlenW(item->pszText),
drawRect,
DT_LEFT | DT_SINGLELINE
);
}
}
*drawRect = rcTemp; /* restore drawRect */
}
/*
* Cleanup
*/
SelectObject(hdc, hOldFont);
SetBkMode(hdc, oldBkMode);
SelectObject(hdc, holdPen);
DeleteObject( htextPen );
}
/******************************************************************************
* TAB_DrawItem
*
* This method is used to draw a single tab into the tab control.
*/
static void TAB_DrawItem(
TAB_INFO *infoPtr,
HDC hdc,
INT iItem)
{
LONG lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
RECT itemRect;
RECT selectedRect;
BOOL isVisible;
RECT r, fillRect, r1;
INT clRight = 0;
INT clBottom = 0;
COLORREF bkgnd, corner;
HTHEME theme;
/*
* Get the rectangle for the item.
*/
isVisible = TAB_InternalGetItemRect(infoPtr,
iItem,
&itemRect,
&selectedRect);
if (isVisible)
{
RECT rUD, rC;
/* Clip UpDown control to not draw over it */
if (infoPtr->needsScrolling)
{
GetWindowRect(infoPtr->hwnd, &rC);
GetWindowRect(infoPtr->hwndUpDown, &rUD);
ExcludeClipRect(hdc, rUD.left - rC.left, rUD.top - rC.top, rUD.right - rC.left, rUD.bottom - rC.top);
}
/* If you need to see what the control is doing,
* then override these variables. They will change what
* fill colors are used for filling the tabs, and the
* corners when drawing the edge.
*/
bkgnd = comctl32_color.clrBtnFace;
corner = comctl32_color.clrBtnFace;
if (lStyle & TCS_BUTTONS)
{
/* Get item rectangle */
r = itemRect;
/* Separators between flat buttons */
if (lStyle & TCS_FLATBUTTONS)
{
r1 = r;
r1.right += (FLAT_BTN_SPACINGX -2);
DrawEdge(hdc, &r1, EDGE_ETCHED, BF_RIGHT);
}
if (iItem == infoPtr->iSelected)
{
DrawEdge(hdc, &r, EDGE_SUNKEN, BF_SOFT|BF_RECT);
OffsetRect(&r, 1, 1);
}
else /* ! selected */
{
if (!(lStyle & TCS_FLATBUTTONS))
DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_RECT);
}
}
else /* !TCS_BUTTONS */
{
/* We draw a rectangle of different sizes depending on the selection
* state. */
if (iItem == infoPtr->iSelected) {
RECT rect;
GetClientRect (infoPtr->hwnd, &rect);
clRight = rect.right;
clBottom = rect.bottom;
r = selectedRect;
}
else
r = itemRect;
/*
* Erase the background. (Delay it but setup rectangle.)
* This is necessary when drawing the selected item since it is larger
* than the others, it might overlap with stuff already drawn by the
* other tabs
*/
fillRect = r;
/* Draw themed tabs - but only if they are at the top.
* Windows draws even side or bottom tabs themed, with wacky results.
* However, since in Wine apps may get themed that did not opt in via
* a manifest avoid theming when we know the result will be wrong */
if ((theme = GetWindowTheme (infoPtr->hwnd))
&& ((lStyle & (TCS_VERTICAL | TCS_BOTTOM)) == 0))
{
static const int partIds[8] = {
/* Normal item */
TABP_TABITEM,
TABP_TABITEMLEFTEDGE,
TABP_TABITEMRIGHTEDGE,
TABP_TABITEMBOTHEDGE,
/* Selected tab */
TABP_TOPTABITEM,
TABP_TOPTABITEMLEFTEDGE,
TABP_TOPTABITEMRIGHTEDGE,
TABP_TOPTABITEMBOTHEDGE,
};
int partIndex = 0;
int stateId = TIS_NORMAL;
/* selected and unselected tabs have different parts */
if (iItem == infoPtr->iSelected)
partIndex += 4;
/* The part also differs on the position of a tab on a line.
* "Visually" determining the position works well enough. */
if(selectedRect.left == 0)
partIndex += 1;
if(selectedRect.right == clRight)
partIndex += 2;
if (iItem == infoPtr->iSelected)
stateId = TIS_SELECTED;
else if (iItem == infoPtr->iHotTracked)
stateId = TIS_HOT;
else if (iItem == infoPtr->uFocus)
stateId = TIS_FOCUSED;
/* Adjust rectangle for bottommost row */
if (TAB_GetItem(infoPtr, iItem)->rect.top == infoPtr->uNumRows-1)
r.bottom += 3;
DrawThemeBackground (theme, hdc, partIds[partIndex], stateId, &r, NULL);
GetThemeBackgroundContentRect (theme, hdc, partIds[partIndex], stateId, &r, &r);
}
else if(lStyle & TCS_VERTICAL)
{
/* These are for adjusting the drawing of a Selected tab */
/* The initial values are for the normal case of non-Selected */
int ZZ = 1; /* Do not strech if selected */
if (iItem == infoPtr->iSelected) {
ZZ = 0;
/* if leftmost draw the line longer */
if(selectedRect.top == 0)
fillRect.top += CONTROL_BORDER_SIZEY;
/* if rightmost draw the line longer */
if(selectedRect.bottom == clBottom)
fillRect.bottom -= CONTROL_BORDER_SIZEY;
}
if (lStyle & TCS_BOTTOM)
{
/* Adjust both rectangles to match native */
r.left += (1-ZZ);
TRACE("<right> item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n",
iItem,
fillRect.left,fillRect.top,fillRect.right,fillRect.bottom,
r.left,r.top,r.right,r.bottom);
/* Clear interior */
SetBkColor(hdc, bkgnd);
ExtTextOutW(hdc, 0, 0, 2, &fillRect, NULL, 0, 0);
/* Draw rectangular edge around tab */
DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_RIGHT|BF_TOP|BF_BOTTOM);
/* Now erase the top corner and draw diagonal edge */
SetBkColor(hdc, corner);
r1.left = r.right - ROUND_CORNER_SIZE - 1;
r1.top = r.top;
r1.right = r.right;
r1.bottom = r1.top + ROUND_CORNER_SIZE;
ExtTextOutW(hdc, 0, 0, 2, &r1, NULL, 0, 0);
r1.right--;
DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPLEFT);
/* Now erase the bottom corner and draw diagonal edge */
r1.left = r.right - ROUND_CORNER_SIZE - 1;
r1.bottom = r.bottom;
r1.right = r.right;
r1.top = r1.bottom - ROUND_CORNER_SIZE;
ExtTextOutW(hdc, 0, 0, 2, &r1, NULL, 0, 0);
r1.right--;
DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDBOTTOMLEFT);
if ((iItem == infoPtr->iSelected) && (selectedRect.top == 0)) {
r1 = r;
r1.right = r1.left;
r1.left--;
DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_TOP);
}
}
else
{
TRACE("<left> item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n",
iItem,
fillRect.left,fillRect.top,fillRect.right,fillRect.bottom,
r.left,r.top,r.right,r.bottom);
/* Clear interior */
SetBkColor(hdc, bkgnd);
ExtTextOutW(hdc, 0, 0, 2, &fillRect, NULL, 0, 0);
/* Draw rectangular edge around tab */
DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_LEFT|BF_TOP|BF_BOTTOM);
/* Now erase the top corner and draw diagonal edge */
SetBkColor(hdc, corner);
r1.left = r.left;
r1.top = r.top;
r1.right = r1.left + ROUND_CORNER_SIZE + 1;
r1.bottom = r1.top + ROUND_CORNER_SIZE;
ExtTextOutW(hdc, 0, 0, 2, &r1, NULL, 0, 0);
r1.left++;
DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPRIGHT);
/* Now erase the bottom corner and draw diagonal edge */
r1.left = r.left;
r1.bottom = r.bottom;
r1.right = r1.left + ROUND_CORNER_SIZE + 1;
r1.top = r1.bottom - ROUND_CORNER_SIZE;
ExtTextOutW(hdc, 0, 0, 2, &r1, NULL, 0, 0);
r1.left++;
DrawEdge(hdc, &r1, EDGE_SUNKEN, BF_DIAGONAL_ENDTOPLEFT);
}
}
else /* ! TCS_VERTICAL */
{
/* These are f
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -