📄 coolscroll.c
字号:
}
//
// Find the size in pixels of all the inserted buttons,
// either before or after the specified scrollbar
//
static int GetButtonSize(SCROLLBAR *sbar, HWND hwnd, UINT uBeforeAfter)
{
int i;
int nPixels = 0;
SCROLLBUT *sbut = sbar->sbButtons;
for(i = 0; i < sbar->nButtons; i++)
{
//only consider those buttons on the same side as nTopBottom says
if(sbut[i].uPlacement == uBeforeAfter)
{
nPixels += GetSingleButSize(sbar, &sbut[i]);
}
}
return nPixels;
}
#endif //INCLUDE_BUTTONS
//
// Work out the scrollbar width/height for either type of scrollbar (SB_HORZ/SB_VERT)
// rect - coords of the scrollbar.
// store results into *thumbsize and *thumbpos
//
static int CalcThumbSize(SCROLLBAR *sbar, const RECT *rect, int *pthumbsize, int *pthumbpos)
{
SCROLLINFO *si;
int scrollsize; //total size of the scrollbar including arrow buttons
int workingsize; //working area (where the thumb can slide)
int siMaxMin;
int butsize;
int startcoord;
int thumbpos = 0, thumbsize = 0;
int adjust=0;
static int count=0;
//work out the width (for a horizontal) or the height (for a vertical)
//of a standard scrollbar button
butsize = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
if(1) //sbar->nBarType == SB_HORZ)
{
scrollsize = rect->right - rect->left;
startcoord = rect->left;
}
/*else if(sbar->nBarType == SB_VERT)
{
scrollsize = rect->bottom - rect->top;
startcoord = rect->top;
}
else
{
return 0;
}*/
si = &sbar->scrollInfo;
siMaxMin = si->nMax - si->nMin + 1;
workingsize = scrollsize - butsize * 2;
//
// Work out the scrollbar thumb SIZE
//
if(si->nPage == 0)
{
thumbsize = butsize;
}
else if(siMaxMin > 0)
{
thumbsize = MulDiv(si->nPage, workingsize, siMaxMin);
if(thumbsize < sbar->nMinThumbSize)
thumbsize = sbar->nMinThumbSize;
}
//
// Work out the scrollbar thumb position
//
if(siMaxMin > 0)
{
int pagesize = max(1, si->nPage);
thumbpos = MulDiv(si->nPos - si->nMin, workingsize-thumbsize, siMaxMin - pagesize);
if(thumbpos < 0)
thumbpos = 0;
if(thumbpos >= workingsize-thumbsize)
thumbpos = workingsize-thumbsize;
}
thumbpos += startcoord + butsize;
*pthumbpos = thumbpos;
*pthumbsize = thumbsize;
return 1;
}
//
// return a hit-test value for whatever part of the scrollbar x,y is located in
// rect, x, y: SCREEN coordinates
// the rectangle must not include space for any inserted buttons
// (i.e, JUST the scrollbar area)
//
static UINT GetHorzScrollPortion(SCROLLBAR *sbar, HWND hwnd, const RECT *rect, int x, int y)
{
int thumbwidth, thumbpos;
int butwidth = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
int scrollwidth = rect->right-rect->left;
int workingwidth = scrollwidth - butwidth*2;
if(y < rect->top || y >= rect->bottom)
return HTSCROLL_NONE;
CalcThumbSize(sbar, rect, &thumbwidth, &thumbpos);
//if we have had to scale the buttons to fit in the rect,
//then adjust the button width accordingly
if(scrollwidth <= butwidth * 2)
{
butwidth = scrollwidth / 2;
}
//check for left button click
if(x >= rect->left && x < rect->left + butwidth)
{
return HTSCROLL_LEFT;
}
//check for right button click
else if(x >= rect->right-butwidth && x < rect->right)
{
return HTSCROLL_RIGHT;
}
//if the thumb is too big to fit (i.e. it isn't visible)
//then return a NULL scrollbar area
if(thumbwidth >= workingwidth)
return HTSCROLL_NONE;
//check for point in the thumbbar
if(x >= thumbpos && x < thumbpos+thumbwidth)
{
return HTSCROLL_THUMB;
}
//check for left margin
else if(x >= rect->left+butwidth && x < thumbpos)
{
return HTSCROLL_PAGELEFT;
}
else if(x >= thumbpos+thumbwidth && x < rect->right-butwidth)
{
return HTSCROLL_PAGERIGHT;
}
return HTSCROLL_NONE;
}
//
// For vertical scrollbars, rotate all coordinates by -90 degrees
// so that we can use the horizontal version of this function
//
static UINT GetVertScrollPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
{
UINT r;
RotateRect(rect);
r = GetHorzScrollPortion(sb, hwnd, rect, y, x);
RotateRect(rect);
return r;
}
//
// CUSTOM DRAW support
//
static LRESULT PostCustomPrePostPaint0(HWND hwnd, HDC hdc, SCROLLBAR *sb, UINT dwStage)
{
#ifdef CUSTOM_DRAW
NMCSBCUSTOMDRAW nmcd;
CoolSB_ZeroMemory(&nmcd, sizeof nmcd);
nmcd.hdr.hwndFrom = hwnd;
nmcd.hdr.idFrom = GetWindowLong(hwnd, GWL_ID);
nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW;
nmcd.nBar = sb->nBarType;
nmcd.dwDrawStage = dwStage;
nmcd.hdc = hdc;
hwnd = GetParent(hwnd);
return SendMessage(hwnd, WM_NOTIFY, 0, (LPARAM)&nmcd);
#else
return 0;
#endif
}
static LRESULT PostCustomDrawNotify0(HWND hwnd, HDC hdc, UINT nBar, RECT *prect, UINT nItem, BOOL fMouseDown, BOOL fMouseOver, BOOL fInactive)
{
#ifdef CUSTOM_DRAW
NMCSBCUSTOMDRAW nmcd;
//fill in the standard header
nmcd.hdr.hwndFrom = hwnd;
nmcd.hdr.idFrom = GetWindowLong(hwnd, GWL_ID);
nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW;
nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
nmcd.nBar = nBar;
nmcd.rect = *prect;
nmcd.uItem = nItem;
nmcd.hdc = hdc;
if(fMouseDown)
nmcd.uState = CDIS_SELECTED;
else if(fMouseOver)
nmcd.uState = CDIS_HOT;
else if(fInactive)
nmcd.uState = CDIS_DISABLED;
else
nmcd.uState = CDIS_DEFAULT;
hwnd = GetParent(hwnd);
return SendMessage(hwnd, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
#else
return 0;
#endif
}
// Depending on if we are supporting custom draw, either define
// a macro to the function name, or to nothing at all. If custom draw
// is turned off, then we can save ALOT of code space by binning all
// calls to the custom draw support.
//
#ifdef CUSTOM_DRAW
#define PostCustomDrawNotify PostCustomDrawNotify0
#define PostCustomPrePostPaint PostCustomPrePostPaint0
#else
#define PostCustomDrawNotify 1 ? (void)0 : PostCustomDrawNotify0
#define PostCustomPrePostPaint 1 ? (void)0 : PostCustomPrePostPaint0
#endif
static LRESULT PostMouseNotify0(HWND hwnd, UINT msg, UINT nBar, RECT *prect, UINT nCmdId, POINT pt)
{
#ifdef NOTIFY_MOUSE
NMCOOLBUTMSG nmcb;
//fill in the standard header
nmcb.hdr.hwndFrom = hwnd;
nmcb.hdr.idFrom = GetWindowLong(hwnd, GWL_ID);
nmcb.hdr.code = NM_CLICK;
nmcb.nBar = nBar;
nmcb.uCmdId = nCmdId;
nmcb.uState = 0;
nmcb.rect = *prect;
nmcb.pt = pt;
hwnd = GetParent(hwnd);
return SendMessage(hwnd, WM_NOTIFY, nmcb.hdr.idFrom, (LPARAM)&nmcb);
#else
return 0;
#endif
}
#ifdef NOTIFY_MOUSE
#define PostMouseNotify PostMouseNotify0
#else
#define PostMouseNotify 1 ? (void)0 : PostMouseNotify0
#endif
//
// Draw a complete HORIZONTAL scrollbar in the given rectangle
// Don't draw any inserted buttons in this procedure
//
// uDrawFlags - hittest code, to say if to draw the
// specified portion in an active state or not.
//
//
static LRESULT NCDrawHScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
{
SCROLLINFO *si;
RECT ctrl, thumb;
RECT sbm;
int butwidth = GetScrollMetric(sb, SM_SCROLL_LENGTH);
int scrollwidth = rect->right-rect->left;
int workingwidth = scrollwidth - butwidth*2;
int thumbwidth = 0, thumbpos = 0;
int siMaxMin;
BOOL fCustomDraw = 0;
BOOL fMouseDownL = 0, fMouseOverL = 0, fBarHot = 0;
BOOL fMouseDownR = 0, fMouseOverR = 0;
COLORREF crCheck1 = GetSBForeColor();
COLORREF crCheck2 = GetSBBackColor();
COLORREF crInverse1 = InvertCOLORREF(crCheck1);
COLORREF crInverse2 = InvertCOLORREF(crCheck2);
UINT uDFCFlat = sb->fFlatScrollbar ? DFCS_FLAT : 0;
UINT uDEFlat = sb->fFlatScrollbar ? BF_FLAT : 0;
//drawing flags to modify the appearance of the scrollbar buttons
UINT uLeftButFlags = DFCS_SCROLLLEFT;
UINT uRightButFlags = DFCS_SCROLLRIGHT;
if(scrollwidth <= 0)
return 0;
si = &sb->scrollInfo;
siMaxMin = si->nMax - si->nMin;
if(hwnd != hwndCurCoolSB)
uDrawFlags = HTSCROLL_NONE;
//
// work out the thumb size and position
//
CalcThumbSize(sb, rect, &thumbwidth, &thumbpos);
if(sb->fScrollFlags & ESB_DISABLE_LEFT) uLeftButFlags |= DFCS_INACTIVE;
if(sb->fScrollFlags & ESB_DISABLE_RIGHT) uRightButFlags |= DFCS_INACTIVE;
//if we need to grey the arrows because there is no data to scroll
if(!IsScrollInfoActive(si) && !(sb->fScrollFlags & CSBS_THUMBALWAYS))
{
uLeftButFlags |= DFCS_INACTIVE;
uRightButFlags |= DFCS_INACTIVE;
}
if(hwnd == hwndCurCoolSB)
{
#ifdef FLAT_SCROLLBARS
BOOL ldis = !(uLeftButFlags & DFCS_INACTIVE);
BOOL rdis = !(uRightButFlags & DFCS_INACTIVE);
fBarHot = (sb->nBarType == (int)uMouseOverScrollbar && sb->fFlatScrollbar == CSBS_HOTTRACKED);
fMouseOverL = uHitTestPortion == HTSCROLL_LEFT && fBarHot && ldis;
fMouseOverR = uHitTestPortion == HTSCROLL_RIGHT && fBarHot && rdis;
#endif
fMouseDownL = (uDrawFlags == HTSCROLL_LEFT);
fMouseDownR = (uDrawFlags == HTSCROLL_RIGHT);
}
#ifdef CUSTOM_DRAW
fCustomDraw = ((PostCustomPrePostPaint(hwnd, hdc, sb, CDDS_PREPAINT)) == CDRF_SKIPDEFAULT);
#endif
//
// Draw the scrollbar now
//
if(scrollwidth > butwidth*2)
{
//LEFT ARROW
SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
RotateRect0(sb, &ctrl);
if(fCustomDraw)
PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE);
else
DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL);
RotateRect0(sb, &ctrl);
//MIDDLE PORTION
//if we can fit the thumbbar in, then draw it
if(thumbwidth > 0 && thumbwidth <= workingwidth
&& IsScrollInfoActive(si) && ((sb->fScrollFlags & ESB_DISABLE_BOTH) != ESB_DISABLE_BOTH))
{
//Draw the scrollbar margin above the thumb
SetRect(&sbm, rect->left + butwidth, rect->top, thumbpos, rect->bottom);
RotateRect0(sb, &sbm);
if(fCustomDraw)
{
PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGELEFT, uDrawFlags == HTSCROLL_PAGELEFT, FALSE, FALSE);
}
else
{
if(uDrawFlags == HTSCROLL_PAGELEFT)
DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
else
DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
}
RotateRect0(sb, &sbm);
//Draw the margin below the thumb
sbm.left = thumbpos+thumbwidth;
sbm.right = rect->right - butwidth;
RotateRect0(sb, &sbm);
if(fCustomDraw)
{
PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGERIGHT, uDrawFlags == HTSCROLL_PAGERIGHT, 0, 0);
}
else
{
if(uDrawFlags == HTSCROLL_PAGERIGHT)
DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
else
DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
}
RotateRect0(sb, &sbm);
//Draw the THUMB finally
SetRect(&thumb, thumbpos, rect->top, thumbpos+thumbwidth, rect->bottom);
RotateRect0(sb, &thumb);
if(fCustomDraw)
{
PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &thumb, SB_THUMBTRACK, uDrawFlags==HTSCROLL_THUMB, uHitTestPortion == HTSCROLL_THUMB && fBarHot, FALSE);
}
else
{
#ifdef FLAT_SCROLLBARS
if(hwnd == hwndCurCoolSB && sb->fFlatScrollbar && (uDrawFlags == HTSCROLL_THUMB ||
(uHitTestPortion == HTSCROLL_THUMB && fBarHot)))
{
PaintRect(hdc, &thumb, GetSysColor(COLOR_3DSHADOW));
}
else
#endif
{
DrawBlankButton(hdc, &thumb, uDEFlat);
}
}
RotateRect0(sb, &thumb);
}
//otherwise, just leave that whole area blank
else
{
OffsetRect(&ctrl, butwidth, 0);
ctrl.right = rect->right - butwidth;
//if we always show the thumb covering the whole scrollbar,
//then draw it that way
if(!IsScrollInfoActive(si) && (sb->fScrollFlags & CSBS_THUMBALWAYS)
&& ctrl.right - ctrl.left > sb->nMinThumbSize)
{
//leave a 1-pixel gap between the thumb + right button
ctrl.right --;
RotateRect0(sb, &ctrl);
if(fCustomDraw)
PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_THUMBTRACK, fMouseDownL, FALSE, FALSE);
else
{
#ifdef FLAT_SCROLLBARS
if(sb->fFlatScrollbar == CSBS_HOTTRACKED && uDrawFlags == HTSCROLL_THUMB)
PaintRect(hdc, &ctrl, GetSysColor(COLOR_3DSHADOW));
else
#endif
DrawBlankButton(hdc, &ctrl, uDEFlat);
}
RotateRect0(sb, &ctrl);
//draw the single-line gap
ctrl.left = ctrl.right;
ctrl.right += 1;
RotateRect0(sb, &ctrl);
if(fCustomDraw)
PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
else
PaintRect(hdc, &ctrl, GetSysColor(COLOR_SCROLLBAR));
RotateRect0(sb, &ctrl);
}
//otherwise, paint a blank if the thumb doesn't fit in
else
{
RotateRect0(sb, &ctrl);
if(fCustomDraw)
PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
else
DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2);
RotateRect0(sb, &ctrl);
}
}
//RIGHT ARROW
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -