📄 trackbar.c
字号:
DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
if (dwStyle & TBS_ENABLESELRANGE) { /* fill the channel */
FillRect (hdc, &rcChannel, GetStockObject(WHITE_BRUSH));
if (TRACKBAR_HasSelection(infoPtr))
FillRect (hdc, &infoPtr->rcSelection, GetSysColorBrush(COLOR_HIGHLIGHT));
}
}
}
static void
TRACKBAR_DrawOneTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
{
int x, y, ox, oy, range, side, indent = 0, len = 3;
int offsetthumb;
RECT rcTics;
if (flags & TBS_VERT) {
offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2;
rcTics.left = infoPtr->rcThumb.left - 2;
rcTics.right = infoPtr->rcThumb.right + 2;
rcTics.top = infoPtr->rcChannel.top + offsetthumb + 1;
rcTics.bottom = infoPtr->rcChannel.bottom - offsetthumb;
} else {
offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2;
rcTics.left = infoPtr->rcChannel.left + offsetthumb + 1;
rcTics.right = infoPtr->rcChannel.right - offsetthumb;
rcTics.top = infoPtr->rcThumb.top - 2;
rcTics.bottom = infoPtr->rcThumb.bottom + 2;
}
if (flags & (TBS_TOP | TBS_LEFT)) {
x = rcTics.left;
y = rcTics.top;
side = -1;
} else {
x = rcTics.right;
y = rcTics.bottom;
side = 1;
}
range = infoPtr->lRangeMax - infoPtr->lRangeMin;
if (range <= 0)
range = 1; /* to avoid division by zero */
if (flags & TIC_SELECTIONMARK) {
indent = (flags & TIC_SELECTIONMARKMIN) ? -1 : 1;
} else if (flags & TIC_EDGE) {
len++;
}
if (flags & TBS_VERT) {
int height = rcTics.bottom - rcTics.top;
y = rcTics.top + (height*(ticPos - infoPtr->lRangeMin))/range;
} else {
int width = rcTics.right - rcTics.left;
x = rcTics.left + (width*(ticPos - infoPtr->lRangeMin))/range;
}
ox = x;
oy = y;
MoveToEx(hdc, x, y, 0);
if (flags & TBS_VERT) x += len * side;
else y += len * side;
LineTo(hdc, x, y);
if (flags & TIC_SELECTIONMARK) {
if (flags & TBS_VERT) {
x -= side;
} else {
y -= side;
}
MoveToEx(hdc, x, y, 0);
if (flags & TBS_VERT) {
y += 2 * indent;
} else {
x += 2 * indent;
}
LineTo(hdc, x, y);
LineTo(hdc, ox, oy);
}
}
static inline void
TRACKBAR_DrawTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
{
if ((flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags | TBS_LEFT);
if (!(flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags & ~TBS_LEFT);
}
static void
TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
{
unsigned int i;
int ticFlags = dwStyle & 0x0f;
LOGPEN ticPen = { PS_SOLID, {1, 0}, GetSysColor (COLOR_3DDKSHADOW) };
HPEN hOldPen, hTicPen;
HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
if (theme)
{
int part = (dwStyle & TBS_VERT) ? TKP_TICSVERT : TKP_TICS;
GetThemeColor (theme, part, TSS_NORMAL, TMT_COLOR, &ticPen.lopnColor);
}
/* create the pen to draw the tics with */
hTicPen = CreatePenIndirect(&ticPen);
hOldPen = hTicPen ? SelectObject(hdc, hTicPen) : 0;
/* actually draw the tics */
for (i=0; i<infoPtr->uNumTics; i++)
TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->tics[i], ticFlags);
TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMin, ticFlags | TIC_EDGE);
TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMax, ticFlags | TIC_EDGE);
if ((dwStyle & TBS_ENABLESELRANGE) && TRACKBAR_HasSelection(infoPtr)) {
TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMin,
ticFlags | TIC_SELECTIONMARKMIN);
TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMax,
ticFlags | TIC_SELECTIONMARKMAX);
}
/* clean up the pen, if we created one */
if (hTicPen) {
SelectObject(hdc, hOldPen);
DeleteObject(hTicPen);
}
}
static void
TRACKBAR_DrawThumb(TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
{
HBRUSH oldbr;
HPEN oldpen;
RECT thumb = infoPtr->rcThumb;
int BlackUntil = 3;
int PointCount = 6;
POINT points[6];
int fillClr;
int PointDepth;
HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
if (theme)
{
int partId;
int stateId;
if (dwStyle & TBS_BOTH)
partId = (dwStyle & TBS_VERT) ? TKP_THUMBVERT : TKP_THUMB;
else if (dwStyle & TBS_LEFT)
partId = (dwStyle & TBS_VERT) ? TKP_THUMBLEFT : TKP_THUMBTOP;
else
partId = (dwStyle & TBS_VERT) ? TKP_THUMBRIGHT : TKP_THUMBBOTTOM;
if (dwStyle & WS_DISABLED)
stateId = TUS_DISABLED;
else if (infoPtr->flags & TB_DRAG_MODE)
stateId = TUS_PRESSED;
else if (infoPtr->flags & TB_THUMB_HOT)
stateId = TUS_HOT;
else
stateId = TUS_NORMAL;
DrawThemeBackground (theme, hdc, partId, stateId, &thumb, 0);
return;
}
fillClr = infoPtr->flags & TB_DRAG_MODE ? COLOR_BTNHILIGHT : COLOR_BTNFACE;
oldbr = SelectObject (hdc, GetSysColorBrush(fillClr));
SetPolyFillMode (hdc, WINDING);
if (dwStyle & TBS_BOTH)
{
points[0].x=thumb.right;
points[0].y=thumb.top;
points[1].x=thumb.right;
points[1].y=thumb.bottom;
points[2].x=thumb.left;
points[2].y=thumb.bottom;
points[3].x=thumb.left;
points[3].y=thumb.top;
points[4].x=points[0].x;
points[4].y=points[0].y;
PointCount = 5;
BlackUntil = 3;
}
else
{
if (dwStyle & TBS_VERT)
{
PointDepth = (thumb.bottom - thumb.top) / 2;
if (dwStyle & TBS_LEFT)
{
points[0].x=thumb.right;
points[0].y=thumb.top;
points[1].x=thumb.right;
points[1].y=thumb.bottom;
points[2].x=thumb.left + PointDepth;
points[2].y=thumb.bottom;
points[3].x=thumb.left;
points[3].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1;
points[4].x=thumb.left + PointDepth;
points[4].y=thumb.top;
points[5].x=points[0].x;
points[5].y=points[0].y;
BlackUntil = 4;
}
else
{
points[0].x=thumb.right;
points[0].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1;
points[1].x=thumb.right - PointDepth;
points[1].y=thumb.bottom;
points[2].x=thumb.left;
points[2].y=thumb.bottom;
points[3].x=thumb.left;
points[3].y=thumb.top;
points[4].x=thumb.right - PointDepth;
points[4].y=thumb.top;
points[5].x=points[0].x;
points[5].y=points[0].y;
}
}
else
{
PointDepth = (thumb.right - thumb.left) / 2;
if (dwStyle & TBS_TOP)
{
points[0].x=(thumb.right - thumb.left) / 2 + thumb.left + 1;
points[0].y=thumb.top;
points[1].x=thumb.right;
points[1].y=thumb.top + PointDepth;
points[2].x=thumb.right;
points[2].y=thumb.bottom;
points[3].x=thumb.left;
points[3].y=thumb.bottom;
points[4].x=thumb.left;
points[4].y=thumb.top + PointDepth;
points[5].x=points[0].x;
points[5].y=points[0].y;
BlackUntil = 4;
}
else
{
points[0].x=thumb.right;
points[0].y=thumb.top;
points[1].x=thumb.right;
points[1].y=thumb.bottom - PointDepth;
points[2].x=(thumb.right - thumb.left) / 2 + thumb.left + 1;
points[2].y=thumb.bottom;
points[3].x=thumb.left;
points[3].y=thumb.bottom - PointDepth;
points[4].x=thumb.left;
points[4].y=thumb.top;
points[5].x=points[0].x;
points[5].y=points[0].y;
}
}
}
/* Draw the thumb now */
Polygon (hdc, points, PointCount);
oldpen = SelectObject(hdc, GetStockObject(BLACK_PEN));
Polyline(hdc,points, BlackUntil);
SelectObject(hdc, GetStockObject(WHITE_PEN));
Polyline(hdc, &points[BlackUntil-1], PointCount+1-BlackUntil);
SelectObject(hdc, oldpen);
SelectObject(hdc, oldbr);
}
inline static void
TRACKBAR_ActivateToolTip (TRACKBAR_INFO *infoPtr, BOOL fShow)
{
TTTOOLINFOW ti;
if (!infoPtr->hwndToolTip) return;
ZeroMemory(&ti, sizeof(ti));
ti.cbSize = sizeof(ti);
ti.hwnd = infoPtr->hwndSelf;
SendMessageW (infoPtr->hwndToolTip, TTM_TRACKACTIVATE, fShow, (LPARAM)&ti);
}
static void
TRACKBAR_UpdateToolTip (TRACKBAR_INFO *infoPtr)
{
DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
WCHAR buf[80];
static const WCHAR fmt[] = { '%', 'l', 'd', 0 };
TTTOOLINFOW ti;
POINT pt;
RECT rcClient;
LRESULT size;
if (!infoPtr->hwndToolTip) return;
ZeroMemory(&ti, sizeof(ti));
ti.cbSize = sizeof(ti);
ti.hwnd = infoPtr->hwndSelf;
ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
wsprintfW (buf, fmt, infoPtr->lPos);
ti.lpszText = buf;
SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti);
GetClientRect (infoPtr->hwndSelf, &rcClient);
size = SendMessageW (infoPtr->hwndToolTip, TTM_GETBUBBLESIZE, 0, (LPARAM)&ti);
if (dwStyle & TBS_VERT) {
if (infoPtr->fLocation == TBTS_LEFT)
pt.x = 0 - LOWORD(size) - TOOLTIP_OFFSET;
else
pt.x = rcClient.right + TOOLTIP_OFFSET;
pt.y = (infoPtr->rcThumb.top + infoPtr->rcThumb.bottom - HIWORD(size))/2;
} else {
if (infoPtr->fLocation == TBTS_TOP)
pt.y = 0 - HIWORD(size) - TOOLTIP_OFFSET;
else
pt.y = rcClient.bottom + TOOLTIP_OFFSET;
pt.x = (infoPtr->rcThumb.left + infoPtr->rcThumb.right - LOWORD(size))/2;
}
ClientToScreen(infoPtr->hwndSelf, &pt);
SendMessageW (infoPtr->hwndToolTip, TTM_TRACKPOSITION,
0, (LPARAM)MAKELPARAM(pt.x, pt.y));
}
static void
TRACKBAR_Refresh (TRACKBAR_INFO *infoPtr, HDC hdcDst)
{
DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
RECT rcClient;
HDC hdc;
HBITMAP hOldBmp = 0, hOffScreenBmp = 0;
NMCUSTOMDRAW nmcd;
int gcdrf, icdrf;
if (infoPtr->flags & TB_THUMBCHANGED) {
TRACKBAR_UpdateThumb (infoPtr);
if (infoPtr->flags & TB_THUMBSIZECHANGED)
TRACKBAR_CalcChannel (infoPtr);
}
if (infoPtr->flags & TB_SELECTIONCHANGED)
TRACKBAR_CalcSelection (infoPtr);
if (infoPtr->flags & TB_DRAG_MODE)
TRACKBAR_UpdateToolTip (infoPtr);
infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED);
GetClientRect (infoPtr->hwndSelf, &rcClient);
/* try to render offscreen, if we fail, carrry onscreen */
hdc = CreateCompatibleDC(hdcDst);
if (hdc) {
hOffScreenBmp = CreateCompatibleBitmap(hdcDst, rcClient.right, rcClient.bottom);
if (hOffScreenBmp) {
hOldBmp = SelectObject(hdc, hOffScreenBmp);
} else {
DeleteObject(hdc);
hdc = hdcDst;
}
} else {
hdc = hdcDst;
}
ZeroMemory(&nmcd, sizeof(nmcd));
nmcd.hdr.hwndFrom = infoPtr->hwndSelf;
nmcd.hdr.idFrom = GetWindowLongPtrW (infoPtr->hwndSelf, GWLP_ID);
nmcd.hdr.code = NM_CUSTOMDRAW;
nmcd.hdc = hdc;
/* start the paint cycle */
nmcd.rc = rcClient;
gcdrf = notify_customdraw(infoPtr, &nmcd, CDDS_PREPAINT);
if (gcdrf & CDRF_SKIPDEFAULT) goto cleanup;
/* Erase backbround */
if (gcdrf == CDRF_DODEFAULT ||
notify_customdraw(infoPtr, &nmcd, CDDS_PREERASE) != CDRF_SKIPDEFAULT) {
if (GetWindowTheme (infoPtr->hwndSelf))
DrawThemeParentBackground (infoPtr->hwndSelf, hdc, &rcClient);
else
FillRect (hdc, &rcClient, GetSysColorBrush(COLOR_BTNFACE));
if (gcdrf != CDRF_DODEFAULT)
notify_customdraw(infoPtr, &nmcd, CDDS_POSTERASE);
}
/* draw channel */
if (gcdrf & CDRF_NOTIFYITEMDRAW) {
nmcd.dwItemSpec = TBCD_CHANNEL;
nmcd.uItemState = CDIS_DEFAULT;
nmcd.rc = infoPtr->rcChannel;
icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT);
} else icdrf = CDRF_DODEFAULT;
if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
TRACKBAR_DrawChannel (infoPtr, hdc, dwStyle);
if (icdrf & CDRF_NOTIFYPOSTPAINT)
notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT);
}
/* draw tics */
if (!(dwStyle & TBS_NOTICKS)) {
if (gcdrf & CDRF_NOTIFYITEMDRAW) {
nmcd.dwItemSpec = TBCD_TICS;
nmcd.uItemState = CDIS_DEFAULT;
nmcd.rc = rcClient;
icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT);
} else icdrf = CDRF_DODEFAULT;
if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
TRACKBAR_DrawTics (infoPtr, hdc, dwStyle);
if (icdrf & CDRF_NOTIFYPOSTPAINT)
notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT);
}
}
/* draw thumb */
if (!(dwStyle & TBS_NOTHUMB)) {
if (gcdrf & CDRF_NOTIFYITEMDRAW) {
nmcd.dwItemSpec = TBCD_THUMB;
nmcd.uItemState = infoPtr->flags & TB_DRAG_MODE ? CDIS_HOT : CDIS_DEFAULT;
nmcd.rc = infoPtr->rcThumb;
icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT);
} else icdrf = CDRF_DODEFAULT;
if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
TRACKBAR_DrawThumb(infoPtr, hdc, dwStyle);
if (icdrf & CDRF_NOTIFYPOSTPAINT)
notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT);
}
}
/* draw focus rectangle */
if (infoPtr->bFocussed) {
DrawFocusRect(hdc, &rcClient);
}
/* finish up the painting */
if (gcdrf & CDRF_NOTIFYPOSTPAINT)
notify_customdraw(infoPtr, &nmcd, CDDS_POSTPAINT);
cleanup:
/* cleanup, if we rendered offscreen */
if (hdc != hdcDst) {
BitBlt(hdcDst, 0, 0, rcClient.right, rcClient.bottom, hdc, 0, 0, SRCCOPY);
SelectObject(hdc, hOldBmp);
DeleteObject(hOffScreenBmp);
DeleteObject(hdc);
}
}
static void
TRACKBAR_AlignBuddies (TRACKBAR_INFO *infoPtr)
{
DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
HWND hwndParent = GetParent (infoPtr->hwndSelf);
RECT rcSelf, rcBuddy;
INT x, y;
GetWindowRect (infoPtr->hwndSelf, &rcSelf);
MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcSelf, 2);
/* align buddy left or above */
if (infoPtr->hwndBuddyLA) {
GetWindowRect (infoPtr->hwndBuddyLA, &rcBuddy);
MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
if (dwStyle & TBS_VERT) {
x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
(rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
y = rcSelf.top - (rcBuddy.bottom - rcBuddy.top);
}
else {
x = rcSelf.left - (rcBuddy.right - rcBuddy.left);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -