求非HOOK方式自绘CListViewCtrl滚动条的办法???

Sou2012 2010-03-24 05:33:22
一直在做一个 CListViewCtrl 的自绘滚动条, 但是我现在想到的,就是以下代码。

下面我实现的, 不能拖着滚动条上下移动。有没有人帮我完善一下。 非常感谢。



#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;
};
...全文
136 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
hurryboylqs 2010-03-25
  • 打赏
  • 举报
回复
建议的是用scrollbar控件替换这个
这样不仅具有通用性而且实现也方便
job82824 2010-03-25
  • 打赏
  • 举报
回复
楼主的代码不错,我拷贝回去研究研究再说:)
fakemajia2 2010-03-25
  • 打赏
  • 举报
回复
HOOK API SetScrollPos相关的几个,参加codejoke的xtremetoolkit,其他方法都不是好的解决方案
cnzdgs 2010-03-25
  • 打赏
  • 举报
回复
鼠标按下时记录鼠标的位置和滑块的位置,并执行SetCapture;鼠标放开时执行ReleaseCapture;鼠标移动时根据当前位置和按下时的位置来计算移动距离。
另外,图像应在初始化时Load,每次绘制Load会降低效率。
Sou2012 2010-03-24
  • 打赏
  • 举报
回复
自己顶一下!!!
hurryboylqs 2010-03-24
  • 打赏
  • 举报
回复
http://www.codeproject.com/KB/list/skinlist.aspx
这里有个例子自己看看吧
老掉牙的问题了

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧