📄 toolbar.c
字号:
DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE);
else
DrawEdge (hdc, &rc, EDGE_RAISED,
BF_SOFT | BF_RECT | BF_MIDDLE);
}
}
static void
TOOLBAR_DrawSepDDArrow(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd, RECT *rcArrow, BOOL bDropDownPressed, DWORD dwItemCDFlag)
{
HDC hdc = tbcd->nmcd.hdc;
int offset = 0;
BOOL pressed = bDropDownPressed ||
(tbcd->nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED));
if (infoPtr->dwStyle & TBSTYLE_FLAT)
{
if (pressed)
DrawEdge (hdc, rcArrow, BDR_SUNKENOUTER, BF_RECT);
else if ( (tbcd->nmcd.uItemState & CDIS_HOT) &&
!(tbcd->nmcd.uItemState & CDIS_DISABLED) &&
!(tbcd->nmcd.uItemState & CDIS_INDETERMINATE))
DrawEdge (hdc, rcArrow, BDR_RAISEDINNER, BF_RECT);
}
else
{
if (pressed)
DrawEdge (hdc, rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE);
else
DrawEdge (hdc, rcArrow, EDGE_RAISED,
BF_SOFT | BF_RECT | BF_MIDDLE);
}
if (pressed)
offset = (dwItemCDFlag & TBCDRF_NOOFFSET) ? 0 : 1;
if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE))
{
TOOLBAR_DrawArrow(hdc, rcArrow->left+1, rcArrow->top+1 + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnHighlight);
TOOLBAR_DrawArrow(hdc, rcArrow->left, rcArrow->top + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clr3dShadow);
}
else
TOOLBAR_DrawArrow(hdc, rcArrow->left + offset, rcArrow->top + offset + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText);
}
/* draws a complete toolbar button */
static void
TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc, DWORD dwBaseCustDraw)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
DWORD dwStyle = infoPtr->dwStyle;
BOOL hasDropDownArrow = (TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
(btnPtr->fsStyle & BTNS_DROPDOWN)) ||
(btnPtr->fsStyle & BTNS_WHOLEDROPDOWN);
BOOL drawSepDropDownArrow = hasDropDownArrow &&
(~btnPtr->fsStyle & BTNS_WHOLEDROPDOWN);
RECT rc, rcArrow, rcBitmap, rcText;
LPWSTR lpText = NULL;
NMTBCUSTOMDRAW tbcd;
DWORD ntfret;
INT offset;
INT oldBkMode;
DWORD dwItemCustDraw;
DWORD dwItemCDFlag;
HTHEME theme = GetWindowTheme (hwnd);
rc = btnPtr->rect;
CopyRect (&rcArrow, &rc);
/* separator - doesn't send NM_CUSTOMDRAW */
if (btnPtr->fsStyle & BTNS_SEP) {
if (theme)
{
DrawThemeBackground (theme, hdc,
(dwStyle & CCS_VERT) ? TP_SEPARATORVERT : TP_SEPARATOR, 0,
&rc, NULL);
}
else
/* with the FLAT style, iBitmap is the width and has already */
/* been taken into consideration in calculating the width */
/* so now we need to draw the vertical separator */
/* empirical tests show that iBitmap can/will be non-zero */
/* when drawing the vertical bar... */
if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */) {
if (btnPtr->fsStyle & BTNS_DROPDOWN)
TOOLBAR_DrawDDFlatSeparator (&rc, hdc, btnPtr, infoPtr);
else
TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr);
}
else if (btnPtr->fsStyle != BTNS_SEP) {
FIXME("Draw some kind of separator: fsStyle=%x\n",
btnPtr->fsStyle);
}
return;
}
/* get a pointer to the text */
lpText = TOOLBAR_GetText(infoPtr, btnPtr);
if (hasDropDownArrow)
{
int right;
if (dwStyle & TBSTYLE_FLAT)
right = max(rc.left, rc.right - DDARROW_WIDTH);
else
right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
if (drawSepDropDownArrow)
rc.right = right;
rcArrow.left = right;
}
/* copy text & bitmap rects after adjusting for drop-down arrow
* so that text & bitmap is centred in the rectangle not containing
* the arrow */
CopyRect(&rcText, &rc);
CopyRect(&rcBitmap, &rc);
/* Center the bitmap horizontally and vertically */
if (dwStyle & TBSTYLE_LIST)
{
if (lpText &&
infoPtr->nMaxTextRows > 0 &&
(!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ||
(btnPtr->fsStyle & BTNS_SHOWTEXT)) )
rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->szPadding.cx / 2;
else
rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->iListGap / 2;
}
else
rcBitmap.left += ((rc.right - rc.left) - infoPtr->nBitmapWidth) / 2;
rcBitmap.top += infoPtr->szPadding.cy / 2;
TRACE("iBitmap=%d, start=(%d,%d) w=%d, h=%d\n",
btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,
infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
TRACE("Text=%s\n", debugstr_w(lpText));
TRACE("iListGap=%d, padding = { %d, %d }\n", infoPtr->iListGap, infoPtr->szPadding.cx, infoPtr->szPadding.cy);
/* calculate text position */
if (lpText)
{
rcText.left += GetSystemMetrics(SM_CXEDGE);
rcText.right -= GetSystemMetrics(SM_CXEDGE);
if (dwStyle & TBSTYLE_LIST)
{
if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
rcText.left += infoPtr->nBitmapWidth + infoPtr->iListGap + 2;
}
else
{
if (ImageList_GetImageCount(GETDEFIMAGELIST(infoPtr, 0)) > 0)
rcText.top += infoPtr->szPadding.cy/2 + infoPtr->nBitmapHeight + 1;
else
rcText.top += infoPtr->szPadding.cy/2 + 2;
}
}
/* Initialize fields in all cases, because we use these later
* NOTE: applications can and do alter these to customize their
* toolbars */
ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
tbcd.clrText = comctl32_color.clrBtnText;
tbcd.clrTextHighlight = comctl32_color.clrHighlightText;
tbcd.clrBtnFace = comctl32_color.clrBtnFace;
tbcd.clrBtnHighlight = comctl32_color.clrBtnHighlight;
tbcd.clrMark = comctl32_color.clrHighlight;
tbcd.clrHighlightHotTrack = 0;
tbcd.nStringBkMode = TRANSPARENT;
tbcd.nHLStringBkMode = OPAQUE;
/* MSDN says that this is the text rectangle.
* But (why always a but) tracing of v5.7 of native shows
* that this is really a *relative* rectangle based on the
* the nmcd.rc. Also the left and top are always 0 ignoring
* any bitmap that might be present. */
tbcd.rcText.left = 0;
tbcd.rcText.top = 0;
tbcd.rcText.right = rcText.right - rc.left;
tbcd.rcText.bottom = rcText.bottom - rc.top;
tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr);
tbcd.nmcd.hdc = hdc;
tbcd.nmcd.rc = rc;
tbcd.hbrMonoDither = COMCTL32_hPattern55AABrush;
/* FIXME: what are these used for? */
tbcd.hbrLines = 0;
tbcd.hpenLines = 0;
/* Issue Item Prepaint notify */
dwItemCustDraw = 0;
dwItemCDFlag = 0;
if (dwBaseCustDraw & CDRF_NOTIFYITEMDRAW)
{
tbcd.nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
tbcd.nmcd.dwItemSpec = btnPtr->idCommand;
tbcd.nmcd.lItemlParam = btnPtr->dwData;
ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
/* reset these fields so the user can't alter the behaviour like native */
tbcd.nmcd.hdc = hdc;
tbcd.nmcd.rc = rc;
dwItemCustDraw = ntfret & 0xffff;
dwItemCDFlag = ntfret & 0xffff0000;
if (dwItemCustDraw & CDRF_SKIPDEFAULT)
return;
/* save the only part of the rect that the user can change */
rcText.right = tbcd.rcText.right + rc.left;
rcText.bottom = tbcd.rcText.bottom + rc.top;
}
if (!(dwItemCDFlag & TBCDRF_NOOFFSET) &&
(btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED)))
OffsetRect(&rcText, 1, 1);
if (!(tbcd.nmcd.uItemState & CDIS_HOT) &&
((tbcd.nmcd.uItemState & CDIS_CHECKED) || (tbcd.nmcd.uItemState & CDIS_INDETERMINATE)))
TOOLBAR_DrawPattern (&rc, &tbcd);
if (((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf))
&& (tbcd.nmcd.uItemState & CDIS_HOT))
{
if ( dwItemCDFlag & TBCDRF_HILITEHOTTRACK )
{
COLORREF oldclr;
oldclr = SetBkColor(hdc, tbcd.clrHighlightHotTrack);
ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, 0);
if (hasDropDownArrow)
ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &rcArrow, NULL, 0, 0);
SetBkColor(hdc, oldclr);
}
}
if (theme)
{
int partId = drawSepDropDownArrow ? TP_SPLITBUTTON : TP_BUTTON;
int stateId = TS_NORMAL;
if (tbcd.nmcd.uItemState & CDIS_DISABLED)
stateId = TS_DISABLED;
else if (tbcd.nmcd.uItemState & CDIS_SELECTED)
stateId = TS_PRESSED;
else if (tbcd.nmcd.uItemState & CDIS_CHECKED)
stateId = (tbcd.nmcd.uItemState & CDIS_HOT) ? TS_HOTCHECKED : TS_HOT;
else if ((tbcd.nmcd.uItemState & CDIS_HOT)
|| (drawSepDropDownArrow && btnPtr->bDropDownPressed))
stateId = TS_HOT;
DrawThemeBackground (theme, hdc, partId, stateId, &tbcd.nmcd.rc, NULL);
}
else
TOOLBAR_DrawFrame(infoPtr, &tbcd, dwItemCDFlag);
if (drawSepDropDownArrow)
{
if (theme)
{
int stateId = TS_NORMAL;
if (tbcd.nmcd.uItemState & CDIS_DISABLED)
stateId = TS_DISABLED;
else if (btnPtr->bDropDownPressed || (tbcd.nmcd.uItemState & CDIS_SELECTED))
stateId = TS_PRESSED;
else if (tbcd.nmcd.uItemState & CDIS_CHECKED)
stateId = (tbcd.nmcd.uItemState & CDIS_HOT) ? TS_HOTCHECKED : TS_HOT;
else if (tbcd.nmcd.uItemState & CDIS_HOT)
stateId = TS_HOT;
DrawThemeBackground (theme, hdc, TP_DROPDOWNBUTTON, stateId, &rcArrow, NULL);
DrawThemeBackground (theme, hdc, TP_SPLITBUTTONDROPDOWN, stateId, &rcArrow, NULL);
}
else
TOOLBAR_DrawSepDDArrow(infoPtr, &tbcd, &rcArrow, btnPtr->bDropDownPressed, dwItemCDFlag);
}
oldBkMode = SetBkMode (hdc, tbcd.nStringBkMode);
if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT))
TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd, dwItemCDFlag);
SetBkMode (hdc, oldBkMode);
TOOLBAR_DrawImage(infoPtr, btnPtr, rcBitmap.left, rcBitmap.top, &tbcd, dwItemCDFlag);
if (hasDropDownArrow && !drawSepDropDownArrow)
{
if (tbcd.nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE))
{
TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1 + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnHighlight);
TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clr3dShadow);
}
else if (tbcd.nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED))
{
offset = (dwItemCDFlag & TBCDRF_NOOFFSET) ? 0 : 1;
TOOLBAR_DrawArrow(hdc, rcArrow.left + offset, rcArrow.top + offset + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText);
}
else
TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText);
}
if (dwItemCustDraw & CDRF_NOTIFYPOSTPAINT)
{
tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
}
}
static void
TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
TBUTTON_INFO *btnPtr;
INT i;
RECT rcTemp, rcClient;
NMTBCUSTOMDRAW tbcd;
DWORD ntfret;
DWORD dwBaseCustDraw;
/* the app has told us not to redraw the toolbar */
if (!infoPtr->bDoRedraw)
return;
/* if imagelist belongs to the app, it can be changed
by the app after setting it */
if (GETDEFIMAGELIST(infoPtr, 0) != infoPtr->himlInt)
{
infoPtr->nNumBitmaps = 0;
for (i = 0; i < infoPtr->cimlDef; i++)
infoPtr->nNumBitmaps += ImageList_GetImageCount(infoPtr->himlDef[i]->himl);
}
TOOLBAR_DumpToolbar (infoPtr, __LINE__);
/* change the imagelist icon size if we manage the list and it is necessary */
TOOLBAR_CheckImageListIconSize(infoPtr);
/* Send initial notify */
ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
tbcd.nmcd.dwDrawStage = CDDS_PREPAINT;
tbcd.nmcd.hdc = hdc;
tbcd.nmcd.rc = ps->rcPaint;
ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
dwBaseCustDraw = ntfret & 0xffff;
GetClientRect(hwnd, &rcClient);
/* redraw necessary buttons */
btnPtr = infoPtr->buttons;
for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
{
BOOL bDraw;
if (!RectVisible(hdc, &btnPtr->rect))
continue;
if (infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS)
{
IntersectRect(&rcTemp, &rcClient, &btnPtr->rect);
bDraw = EqualRect(&rcTemp, &btnPtr->rect);
}
else
bDraw = TRUE;
bDraw &= IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect));
bDraw = (btnPtr->fsState & TBSTATE_HIDDEN) ? FALSE : bDraw;
if (bDraw)
TOOLBAR_DrawButton(hwnd, btnPtr, hdc, dwBaseCustDraw);
}
/* draw insert mark if required */
if (infoPtr->tbim.iButton != -1)
{
RECT rcButton = infoPtr->buttons[infoPtr->tbim.iButton].rect;
RECT rcInsertMark;
rcInsertMark.top = rcButton.top;
rcInsertMark.bottom = rcButton.bottom;
if (infoPtr->tbim.dwFlags & TBIMHT_AFTER)
rcInsertMark.left = rcInsertMark.right = rcButton.right;
else
rcInsertMark.left = rcInsertMark.right = rcButton.left - INSERTMARK_WIDTH;
COMCTL32_DrawInsertMark(hdc, &rcInsertMark, infoPtr->clrInsertMark, FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -