15,979
社区成员
发帖
与我相关
我的任务
分享
#pragma once
#define WM_UPDATE_SCROLL_BAR_THUMB_HEIGHT (WM_USER + 300)
#define CUSTOM_SCROLL_BAR_THUMB_MIN_HEIGHT 10
class CCustomScrollbar : public CWindowImpl<CCustomScrollbar>
//template <class T, class TBase = CStatic, class TWinTraits = CControlWinTraits>
//class CCustomScrollbarImpl : public CWindowImpl<T, TBase, TWinTraits>
{
public:
BEGIN_MSG_MAP(CCustomScrollbar)
MSG_WM_PAINT(OnPaint)
MSG_WM_ERASEBKGND(OnEraseBkgnd)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
MSG_WM_LBUTTONUP(OnLButtonUp)
MSG_WM_MOUSEMOVE(OnMouseMove)
END_MSG_MAP()
public:
CCustomScrollbar()
{
m_nThumbTop = 0;
m_nThumbHeight = CUSTOM_SCROLL_BAR_THUMB_MIN_HEIGHT;
m_dbThumbInterval = 0;
m_bMouseDown = false;
}
void InitScrollBarRect()
{
m_upBtnRect = CRect(CPoint(0, 0), CSize(16, 16));
m_thumbBtnRect = CRect(CPoint(0, m_nThumbTop), CSize(16, m_nThumbHeight));
m_downBtnRect = CRect(CPoint(0, 515 - 16), CSize(16, 16));
}
public:
BOOL OnEraseBkgnd(CDCHandle dc)
{
return TRUE;
}
void OnPaint(CDCHandle dc)
{
CRect rect;
GetClientRect(&rect);
CPaintDC paintDC(m_hWnd);
CMemoryDC memDC(paintDC, rect);
DoPaintEx(memDC);
}
void DoPaintEx(CMemoryDC &memDC)
{
InitScrollBarRect();
CRect rect;
GetClientRect(&rect);
memDC.FillSolidRect(&rect, RGB(74,82,107));
CImage img;
// draw bg
img.LoadFromResource(_Module.GetResourceInstance(), IDB_SCROLL_BAR_BG);
img.Draw(memDC, rect);
img.Destroy();
// draw up btn
img.LoadFromResource(_Module.GetResourceInstance(), IDB_SCROLL_BAR_UP_BTN);
img.Draw(memDC, rect.left, rect.top, 16, 16);
img.Destroy();
DrawThumbBtn(memDC, rect, img);
// draw down btn
img.LoadFromResource(_Module.GetResourceInstance(), IDB_SCROLL_BAR_DOWN_BTN);
img.Draw(memDC, rect.left, rect.bottom - 16, 16, 16);
img.Destroy();
}
void DrawThumbBtn(CMemoryDC &memDC, CRect &rect, CImage &img)
{
// _nThumbHeight Min is 5 = 2 * 2 + 1 ( 4 is thumb_up + thumb_down, 2 + 2), 1 is offet
if (m_nThumbHeight >= 5)
{
// 上半块 紧贴 在 UP BTN 的下面
img.LoadFromResource(_Module.GetResourceInstance(), IDB_SCROLL_BAR_THUMB);
img.Draw(memDC, rect.left, rect.top + 16 + m_nThumbTop, img.GetWidth(), 2,
0, 0, img.GetWidth(), 2);
img.Destroy();
// 中间块
img.LoadFromResource(_Module.GetResourceInstance(), IDB_SCROLL_BAR_THUMB);
img.Draw(memDC, rect.left, rect.top + 16 + 2 + (m_nThumbTop), img.GetWidth(), m_nThumbHeight - 2 - 2,
0, 2, img.GetWidth(), img.GetHeight() - 2 - 2);
img.Destroy();
// 下半块
img.LoadFromResource(_Module.GetResourceInstance(), IDB_SCROLL_BAR_THUMB);
img.Draw(memDC, rect.left, rect.top + 16 + 2 + (m_nThumbHeight - 2 - 2) + (m_nThumbTop), img.GetWidth(), 2,
0, 14, img.GetWidth(), 2);
img.Destroy();
}
}
void OnLButtonDown(UINT nFlags, CPoint point)
{
m_bMouseDown = true;
}
void OnLButtonUp(UINT nFlags, CPoint point)
{
CRect rect;
GetClientRect(&rect);
if (m_bMouseDown)
{
if (m_upBtnRect.PtInRect(point))
{
LineUp();
}
else if (m_thumbBtnRect.PtInRect(point))
{
//ThumbPosition
}
else if (m_downBtnRect.PtInRect(point))
{
LineDown();
}
else if (rect.PtInRect(point))
{
if (point.y < m_thumbBtnRect.top)
{
PageUp();
}
else if (point.y >= m_thumbBtnRect.bottom)
{
PageDown();
}
}
m_bMouseDown = false;
}
Invalidate();
}
void OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bMouseDown)
{
m_nThumbTop = point.y;
Invalidate();
}
}
public:
void PageUp()
{
m_pListViewCtrl->SendMessage(WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), NULL);
UpdateThumbPosition();
}
void PageDown()
{
m_pListViewCtrl->SendMessage(WM_VSCROLL, MAKELONG(SB_PAGEDOWN,0), NULL);
UpdateThumbPosition();
}
void LineUp()
{
m_pListViewCtrl->SendMessage(WM_VSCROLL, MAKELONG(SB_LINEUP, 0), NULL);
UpdateThumbPosition();
}
void LineDown()
{
m_pListViewCtrl->SendMessage(WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), NULL);
UpdateThumbPosition();
}
public:
void UpdateThumbPosition()
{
m_pListViewCtrl->SendMessage(WM_UPDATE_SCROLL_BAR_THUMB_HEIGHT, 0, 0);
CRect rect;
GetClientRect(&rect);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
m_pListViewCtrl->GetScrollInfo(SB_VERT, &si);
double dbPos = si.nPos;
double dbPageSize = si.nPage;
double dbMax = si.nMax;
// 屏幕高度 = rect.Height() - 2个(up,down)按钮的高度 - 滚动框本身的高度
double dbHeight = rect.Height() - (2 * 16) - m_nThumbHeight;
// 滚动框每次移动的间距 = 屏幕高度 / (滚动的最大值 - 页面大小)
// 这里每次都计算是因为 如果 InsertItem 这个间距就变化了
m_dbThumbInterval = dbHeight / (dbMax - dbPageSize);
// 设置 (滚动框top) 的最终位置 = 间距 * 当前位置
m_nThumbTop = m_dbThumbInterval * dbPos;
InitScrollBarRect();
}
void SetThumbHeight(int height)
{
if (height > CUSTOM_SCROLL_BAR_THUMB_MIN_HEIGHT)
{
m_nThumbHeight = height;
}
}
public:
CListViewCtrl *m_pListViewCtrl;
private:
CRect m_upBtnRect;
CRect m_thumbBtnRect;
CRect m_downBtnRect;
private:
bool m_bMouseDown;
int m_nThumbHeight;
double m_dbThumbInterval;
int m_nThumbTop;
};